package identity

import (
	"context"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/store/testfixture"
)

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

	ctx := context.Background()
	pool := startIdentityTestPool(t, ctx)
	now := time.Now().UTC()

	const (
		userID      = "usr_deleted_agent_public_name"
		workspaceID = "wsp_deleted_agent_public_name"
		memberID    = "mem_deleted_agent_public_name"
	)

	mustExec(t, pool, `
INSERT INTO users (id, email, name, password_hash, is_admin, email_verified_at, created_at, updated_at)
VALUES ($1, 'deleted-agent-public-name@example.com', 'deleted-agent-owner', 'hash', FALSE, $2, $2, $2)
`, userID, now)
	mustExec(t, pool, `
INSERT INTO workspaces (id, organization_id, slug, name, latest_message_seq, created_at, updated_at)
VALUES ($1, $2, 'deleted-agent-public-name', 'deleted-agent-public-name', 0, $3, $3)
`, workspaceID, testfixture.SeedWorkspaceOrganization(t, ctx, pool, workspaceID, now), now)
	mustExec(t, pool, `
INSERT INTO members (id, workspace_id, type, display_name, user_id, workspace_role, created_at, updated_at)
VALUES ($1, $2, 'human', 'Deleted Agent Owner', $3, 'owner', $4, $4)
`, "mem_deleted_agent_owner", workspaceID, userID, now)
	mustExec(t, pool, `
INSERT INTO members (id, workspace_id, type, display_name, created_at, updated_at)
VALUES ($1, $2, 'agent', 'Deleted Agent Display', $3, $3)
`, memberID, workspaceID, now)
	publicNames, err := LoadPublicMemberNamesByMemberID(ctx, pool, workspaceID, []string{memberID})
	require.NoError(t, err)
	require.Equal(t, "Deleted Agent Display", PublicMemberNameForMemberID(memberID, publicNames))
}

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

	ctx := context.Background()
	pool := startIdentityTestPool(t, ctx)
	now := time.Now().UTC()

	const (
		userID      = "usr_human_public_name"
		workspaceID = "wsp_human_public_name"
		memberID    = "mem_human_public_name"
	)

	mustExec(t, pool, `
INSERT INTO users (id, email, name, display_name, password_hash, is_admin, email_verified_at, created_at, updated_at)
VALUES ($1, 'human-public-name@example.com', 'account-name', 'Preferred Name', 'hash', FALSE, $2, $2, $2)
`, userID, now)
	mustExec(t, pool, `
INSERT INTO workspaces (id, organization_id, slug, name, latest_message_seq, created_at, updated_at)
VALUES ($1, $2, 'human-public-name', 'human-public-name', 0, $3, $3)
`, workspaceID, testfixture.SeedWorkspaceOrganization(t, ctx, pool, workspaceID, now), now)
	mustExec(t, pool, `
INSERT INTO members (id, workspace_id, type, display_name, user_id, workspace_role, created_at, updated_at)
VALUES ($1, $2, 'human', 'Workspace Name', $3, 'member', $4, $4)
`, memberID, workspaceID, userID, now)

	publicNames, err := LoadPublicMemberNamesByMemberID(ctx, pool, workspaceID, []string{memberID})
	require.NoError(t, err)
	require.Equal(t, "Preferred Name", PublicMemberNameForMemberID(memberID, publicNames))

	mustExec(t, pool, `UPDATE users SET display_name = '' WHERE id = $1`, userID)
	publicNames, err = LoadPublicMemberNamesByMemberID(ctx, pool, workspaceID, []string{memberID})
	require.NoError(t, err)
	require.Equal(t, "account-name", PublicMemberNameForMemberID(memberID, publicNames))
}

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

	ctx := context.Background()
	pool := startIdentityTestPool(t, ctx)
	now := time.Now().UTC()

	const (
		workspaceID = "wsp_service_public_name"
		serviceID   = "svc_github"
	)

	mustExec(t, pool, `
INSERT INTO workspaces (id, organization_id, slug, name, latest_message_seq, created_at, updated_at)
VALUES ($1, $2, 'service-public-name', 'service-public-name', 0, $3, $3)
`, workspaceID, testfixture.SeedWorkspaceOrganization(t, ctx, pool, workspaceID, now), now)
	mustExec(t, pool, `
INSERT INTO members (id, workspace_id, type, display_name, user_id, workspace_role, created_at, updated_at)
VALUES ($1, $2, 'service', 'GitHub', NULL, NULL, $3, $3)
`, serviceID, workspaceID, now)

	publicNames, err := LoadPublicMemberNamesByMemberID(ctx, pool, workspaceID, []string{serviceID})
	require.NoError(t, err)
	require.Equal(t, serviceID, PublicMemberNameForMemberID(serviceID, publicNames))
}
