package memory

import (
	"context"
	"testing"

	"github.com/tidbcloud/AgentTeam/internal/service/resource/activity"
	"github.com/tidbcloud/AgentTeam/internal/store/resource/repos"

	"github.com/stretchr/testify/require"
)

func TestMemoryServiceWritesControlPlaneActivityEvents(t *testing.T) {
	ctx := context.Background()
	svc := newMemoryServiceForTest(t)

	memory, err := svc.CreateMemory(ctx, "wsp_1", "owner", MemoryCreateMutation{Name: "Runbooks"})
	require.NoError(t, err)
	viewerGrant, err := svc.UpsertMemoryPermission(ctx, "wsp_1", "owner", memory.ID, MemoryPermissionGrantMutation{SubjectType: "user", SubjectID: "viewer", Role: "view"})
	require.NoError(t, err)
	_, err = svc.UpsertMemoryPermission(ctx, "wsp_1", "owner", memory.ID, MemoryPermissionGrantMutation{GrantID: viewerGrant.ID, Role: "manage"})
	require.NoError(t, err)
	_, err = svc.BindAgentMemory(ctx, "wsp_1", "owner", "agt_alice", AgentMemoryBindingMutation{MemoryID: memory.ID, Branch: "main", ImportExistingLocalContent: true})
	require.NoError(t, err)
	_, err = svc.UnbindAgentMemory(ctx, "wsp_1", "owner", "agt_alice")
	require.NoError(t, err)
	require.NoError(t, svc.DeleteMemoryPermission(ctx, "wsp_1", "owner", memory.ID, viewerGrant.ID))

	page, err := svc.ListMemoryActivity(ctx, "wsp_1", "owner", activity.ResourceActivityListOptions{Limit: 20})
	require.NoError(t, err)
	counts := map[string]int{}
	byType := map[string]activity.ResourceActivityItem{}
	for _, item := range page.Items {
		counts[item.EventType]++
		byType[item.EventType] = item
	}
	require.Equal(t, 1, counts[memoryActivityCreated])
	require.Equal(t, 1, counts[memoryActivityGrantAdded])
	require.Equal(t, 1, counts[memoryActivityGrantRoleChanged])
	require.Equal(t, 1, counts[memoryActivityBound])
	require.Equal(t, 1, counts[memoryActivityUnbound])
	require.Equal(t, 1, counts[memoryActivityGrantRemoved])

	created := byType[memoryActivityCreated]
	require.Equal(t, "created", created.SummaryKey)
	require.Equal(t, "resource", created.Target.Kind)
	require.Equal(t, "owner", created.Actor.ID)
	require.Equal(t, "", created.Actor.Name)
	require.Equal(t, "owner/runbooks.mem", created.RepoFullName)

	grantChanged := byType[memoryActivityGrantRoleChanged]
	require.Equal(t, "grant", grantChanged.Target.Kind)
	require.Equal(t, viewerGrant.ID, grantChanged.Target.ID)
	require.Equal(t, "viewer", grantChanged.Details["subjectName"])
	require.Equal(t, "view", grantChanged.Details["previousRole"])
	require.Equal(t, "manage", grantChanged.Details["role"])

	bound := byType[memoryActivityBound]
	require.Equal(t, "binding", bound.Target.Kind)
	require.Equal(t, "agt_alice", bound.Target.ID)
	require.Equal(t, "agt_alice", bound.Details["agentName"])
	require.Equal(t, "main", bound.Details["branch"])
	require.Equal(t, true, bound.Details["importExistingLocalContent"])

	removed := byType[memoryActivityGrantRemoved]
	require.Equal(t, "grant", removed.Target.Kind)
	require.Equal(t, "viewer", removed.Details["subjectId"])
}

func TestMemoryServiceWritesResourceRepositoryLifecycleActivity(t *testing.T) {
	ctx := context.Background()
	svc := newMemoryServiceForTest(t)

	memory, err := svc.CreateMemory(ctx, "wsp_1", "owner", MemoryCreateMutation{Name: "Runbooks"})
	require.NoError(t, err)
	repo, err := svc.repositoryStore.Get(ctx, "wsp_1", "memory", memory.ID, repos.RepoRolePrimary)
	require.NoError(t, err)

	created, err := svc.activityStore.GetBySourceEventID(ctx, "wsp_1", activity.ActivitySourceControl, activity.ResourceActivityControlSourceEventID(repo.ResourceType, repo.ResourceID, repo.RepoRole, "created"))
	require.NoError(t, err)
	require.Equal(t, activity.ResourceRepositoryActivityCreated, created.EventType)
	require.Equal(t, "repository", created.TargetKind)
	require.Equal(t, "owner/runbooks.mem", created.TargetID)
	require.Equal(t, "owner/runbooks.mem", created.RepoFullName)
	require.Equal(t, "owner", created.ActorID)

	require.NoError(t, svc.DeleteMemory(ctx, "wsp_1", "owner", memory.ID))

	deleted, err := svc.activityStore.GetBySourceEventID(ctx, "wsp_1", activity.ActivitySourceControl, activity.ResourceActivityControlSourceEventID(repo.ResourceType, repo.ResourceID, repo.RepoRole, "deleted"))
	require.NoError(t, err)
	require.Equal(t, activity.ResourceRepositoryActivityDeleted, deleted.EventType)
	require.Equal(t, "repository", deleted.TargetKind)
	require.Equal(t, "owner/runbooks.mem", deleted.TargetID)
	require.Equal(t, "owner", deleted.ActorID)
}
