package app

import (
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/store/message"
	"github.com/tidbcloud/AgentTeam/internal/store/model"
)

func TestAppMessageFromDeliveryPreservesClientMessageID(t *testing.T) {
	got := appMessageFromDelivery("chn_1", message.AuthorProfile{ActorType: message.AuthorActorTypeHuman, PrincipalID: "usr_1", TargetID: "alice", DisplayName: "Alice"}, message.MessageDelivery{
		MessageID:       "msg_1",
		ClientMessageID: "client-1",
	})

	if got.ClientMessageID != "client-1" {
		t.Fatalf("ClientMessageID = %q, want client-1", got.ClientMessageID)
	}
}

func TestAppMessageFromDeliveryPreservesReplyThreadContext(t *testing.T) {
	got := appMessageFromDelivery("chn_thread_1", message.AuthorProfile{ActorType: message.AuthorActorTypeService, PrincipalID: "mem_app", MemberID: "mem_app", TargetID: "gitea", DisplayName: "Gitea", ServiceKind: message.AuthorServiceKindApp, ServiceSlug: "gitea"}, message.MessageDelivery{
		MessageID: "msg_1",
		MentionContext: message.MentionContext{
			ChannelType:       "thread",
			ParentChannelID:   "chn_parent_1",
			ParentChannelType: "channel",
			ParentMessageID:   "msg_parent_1",
		},
	})

	if got.ChannelType != "thread" {
		t.Fatalf("ChannelType = %q, want thread", got.ChannelType)
	}
	if got.ParentChannelID != "chn_parent_1" {
		t.Fatalf("ParentChannelID = %q, want chn_parent_1", got.ParentChannelID)
	}
	if got.ParentChannelType != "channel" {
		t.Fatalf("ParentChannelType = %q, want channel", got.ParentChannelType)
	}
	if got.ParentMessageID != "msg_parent_1" {
		t.Fatalf("ParentMessageID = %q, want msg_parent_1", got.ParentMessageID)
	}
}

func TestAppMessageFromDeliverySetsAuthorProfile(t *testing.T) {
	got := appMessageFromDelivery("chn_thread_1", message.AuthorProfile{ActorType: message.AuthorActorTypeService, PrincipalID: "mem_app", MemberID: "mem_app", TargetID: "gitea", DisplayName: "Gitea", ServiceKind: message.AuthorServiceKindApp, ServiceSlug: "gitea"}, message.MessageDelivery{
		MessageID: "msg_1",
	})

	require.Equal(t, "service", got.AuthorProfile.ActorType)
	require.Equal(t, "mem_app", got.AuthorProfile.MemberID)
	require.Equal(t, "gitea", got.AuthorProfile.TargetID)
	require.Equal(t, "Gitea", got.AuthorProfile.DisplayName)
	require.Equal(t, "app", got.AuthorProfile.ServiceKind)
	require.Equal(t, "gitea", got.AuthorProfile.ServiceSlug)
}

func TestHumanAuthorProfileFromUserUsesHumanPresentation(t *testing.T) {
	profile := humanAuthorProfileFromUser(model.User{
		ID:          "usr_1",
		Name:        "alice",
		DisplayName: "Alice Display",
		AvatarURL:   " https://example.com/alice.png ",
	}, " mem_1 ", "Old Member Name")

	require.Equal(t, message.AuthorActorTypeHuman, profile.ActorType)
	require.Equal(t, "usr_1", profile.PrincipalID)
	require.Equal(t, "mem_1", profile.MemberID)
	require.Equal(t, "mem_1", profile.TargetID)
	require.Equal(t, "Alice Display", profile.DisplayName)
	require.Equal(t, "https://example.com/alice.png", profile.AvatarURL)
}

func TestAttachAppMessageToDeliveryCopiesEffectiveAuthorProfile(t *testing.T) {
	appMessage := appMessageFromDelivery("chn_1", message.AuthorProfile{
		ActorType:   message.AuthorActorTypeHuman,
		PrincipalID: "usr_1",
		MemberID:    "mem_1",
		TargetID:    "mem_1",
		DisplayName: "Alice",
		AvatarURL:   "https://example.com/alice.png",
	}, message.MessageDelivery{
		MessageID: "msg_1",
	})
	delivery := message.MessageDelivery{MessageID: "msg_1"}

	attachAppMessageToDelivery(&delivery, &appMessage)

	require.NotNil(t, delivery.AppMessage)
	require.Equal(t, appMessage.AuthorProfile, delivery.Message.AuthorProfile)
	require.Equal(t, appMessage.AuthorProfile, delivery.AppMessage.AuthorProfile)
}

func TestAppMessageCreateDigestIgnoresDerivedMentionMetadata(t *testing.T) {
	t.Parallel()

	first, err := appMessageCreateDigest(preparedUserAppMessage{
		normalizedMessageType: "",
		trimmedContent:        "hello",
		metadata: map[string]any{
			"client": "stable",
			message.MentionMetadataKey: []any{
				map[string]any{
					"type":  "agent",
					"id":    "agt_1",
					"token": "before-rename",
				},
			},
		},
	}, SendAppMessageOptions{})
	require.NoError(t, err)
	replayed, err := appMessageCreateDigest(preparedUserAppMessage{
		normalizedMessageType: "",
		trimmedContent:        "hello",
		metadata: map[string]any{
			"client": "stable",
		},
	}, SendAppMessageOptions{})
	require.NoError(t, err)
	require.Equal(t, first, replayed)

	changed, err := appMessageCreateDigest(preparedUserAppMessage{
		normalizedMessageType: "",
		trimmedContent:        "hello",
		metadata:              map[string]any{"client": "changed"},
	}, SendAppMessageOptions{})
	require.NoError(t, err)
	require.NotEqual(t, first, changed)
}
