package app

import (
	"context"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

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

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

	ctx := context.Background()
	pool := startAppRollbackDB(t, ctx)
	now := time.Unix(100, 0).UTC()
	fixture := seedAppAdminFixture(t, pool, "agent_role_binding_list", now)
	seedMachineWorkspaceAgent(t, pool, fixture.WorkspaceID, fixture.UserID, "mac_role_binding", "agt_role_binding", "mem_role_binding", "Role Bound Agent", "active", now)
	mustExec(t, pool, `
INSERT INTO agent_role_bindings (
    id, workspace_id, agent_id, binding_kind, role_id, role_version_id,
    source_preset_role_id, source_preset_version_id, active_definition_path,
    realization_id, created_by, updated_by, created_at, updated_at
) VALUES ($1, $2, $3, 'my_role', 'role_1', 'rv_1', '', '', 'memory/system/identity.md', 'real_1', $4, $4, $5, $5)
`, "arb_role_binding", fixture.WorkspaceID, "agt_role_binding", fixture.UserID, now)

	store := New(pool, Options{})
	agents, err := store.ListAgentsForWorkspaceWithOptions(ctx, fixture.UserID, fixture.WorkspaceID, agent.AppAgentListOptions{Limit: 10})
	require.NoError(t, err)
	appAgent := findAppAgentForTest(t, agents, "agt_role_binding")
	require.NotNil(t, appAgent.CurrentRoleBinding)
	require.Equal(t, "my_role", appAgent.CurrentRoleBinding.BindingKind)
	require.Equal(t, "rv_1", appAgent.CurrentRoleBinding.RoleVersionID)
	require.Equal(t, "memory/system/identity.md", appAgent.CurrentRoleBinding.ActiveDefinitionPath)
}

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

	ctx := context.Background()
	pool := startAppRollbackDB(t, ctx)
	now := time.Unix(100, 0).UTC()
	fixture := seedAppAdminFixture(t, pool, "agent_role_binding_detail", now)
	seedMachineWorkspaceAgent(t, pool, fixture.WorkspaceID, fixture.UserID, "mac_role_detail", "agt_role_detail", "mem_role_detail", "Role Detail Agent", "active", now)
	mustExec(t, pool, `
INSERT INTO agent_role_bindings (
    id, workspace_id, agent_id, binding_kind, role_id, role_version_id,
    source_preset_role_id, source_preset_version_id, active_definition_path,
    realization_id, created_by, updated_by, created_at, updated_at
) VALUES ($1, $2, $3, 'preset_derived', 'role_2', 'rv_2', 'preset_1', '7', 'memory/system/identity.md', 'real_2', $4, $4, $5, $5)
`, "arb_role_detail", fixture.WorkspaceID, "agt_role_detail", fixture.UserID, now)

	store := New(pool, Options{})
	appAgent, err := store.AgentForWorkspace(ctx, fixture.UserID, fixture.WorkspaceID, "agt_role_detail", agent.AppAgentDetailOptions{})
	require.NoError(t, err)
	require.NotNil(t, appAgent.CurrentRoleBinding)
	require.Equal(t, "preset_derived", appAgent.CurrentRoleBinding.BindingKind)
	require.Equal(t, "preset_1", appAgent.CurrentRoleBinding.SourcePresetRoleID)
	require.Equal(t, "memory/system/identity.md", appAgent.CurrentRoleBinding.ActiveDefinitionPath)
}

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

	ctx := context.Background()
	pool := startAppRollbackDB(t, ctx)
	now := time.Unix(100, 0).UTC()
	fixture := seedAppAdminFixture(t, pool, "agent_role_materialization", now)
	seedMachineWorkspaceAgent(t, pool, fixture.WorkspaceID, fixture.UserID, "mac_role_materialization", "agt_role_materialization", "mem_role_materialization", "Role Agent", "active", now)

	store := New(pool, Options{})
	err := store.UpsertAgentRoleMaterialization(ctx, agent.AgentRoleMaterializationInput{
		UserID:      fixture.UserID,
		WorkspaceID: fixture.WorkspaceID,
		AgentID:     "agt_role_materialization",
		Source: agent.AgentRoleMaterializationSource{
			BindingKind:        "preset_derived",
			PresetID:           "backend",
			SourcePresetRoleID: "backend",
		},
		RoleID:         "role_backend_copy",
		RoleVersionID:  "rlv_backend_copy",
		RealizationID:  "rrl_backend_copy",
		DefinitionPath: "memory/system/identity.md",
		ManifestItems: []agent.AgentRoleMaterializationItem{
			{Type: "role_definition_asset", Name: "IDENTITY.md", Content: "# Backend"},
			{Type: "portable_knowledge", Name: "Runbook", Content: "# Runbook"},
			{Type: "skill", Name: "Deploy", Content: "# Skill"},
			{Type: "knowledge_base", Name: "Private KB", Content: "must not materialize"},
		},
	})
	require.NoError(t, err)

	appAgent, err := store.AgentForWorkspace(ctx, fixture.UserID, fixture.WorkspaceID, "agt_role_materialization", agent.AppAgentDetailOptions{})
	require.NoError(t, err)
	require.NotNil(t, appAgent.CurrentRoleBinding)
	require.Equal(t, "preset_derived", appAgent.CurrentRoleBinding.BindingKind)
	require.Equal(t, "role_backend_copy", appAgent.CurrentRoleBinding.RoleID)
	require.Equal(t, "backend", appAgent.CurrentRoleBinding.SourcePresetRoleID)

	materialization, err := agent.New(pool).LoadAgentWorkspaceMaterialization(ctx, "agt_role_materialization")
	require.NoError(t, err)
	require.NotNil(t, materialization)
	require.Equal(t, "memory/system/identity.md", materialization.ActiveDefinitionPath)
	require.Equal(t, []agent.WorkspaceSeedFile{
		{Path: "memory/system/identity.md", Content: "# Backend"},
		{Path: ".agents/skills/Deploy/SKILL.md", Content: "# Skill"},
		{Path: ".agents/knowledge/Runbook.md", Content: "# Runbook"},
	}, materialization.SeedFiles)
}
