package onboarding

import (
	"context"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
)

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

	ctx := context.Background()
	db := startOnboardingRollbackDB(t, ctx)
	seedOnboardingWorkspace(t, ctx, db, "usr_tutorial", "org_tutorial", "ws_tutorial", "mem_tutorial")
	store := New(db)

	first, err := store.EnsureForUser(ctx, "usr_tutorial", "ws_tutorial", "zh-CN")
	require.NoError(t, err)
	require.True(t, first.Eligible)
	require.Equal(t, StatusActive, first.State.Status)
	require.Equal(t, StepCreateAgent, first.State.CurrentStep)
	require.NotEmpty(t, first.State.TutorialChannelID)

	second, err := store.EnsureForUser(ctx, "usr_tutorial", "ws_tutorial", "en")
	require.NoError(t, err)
	require.True(t, second.Eligible)
	require.Equal(t, first.State.TutorialChannelID, second.State.TutorialChannelID)
	var displayName string
	require.NoError(t, db.QueryRow(ctx, `
SELECT display_name
FROM scope_channel_profiles
WHERE scope_id = $1
`, first.State.TutorialChannelID).Scan(&displayName))
	require.Equal(t, "quick start", displayName)

	var profileCount int
	require.NoError(t, db.QueryRow(ctx, `
SELECT COUNT(*)
FROM scope_channel_profiles
WHERE workspace_id = $1
  AND subsystem = 'tutorial'
  AND owner_member_id = $2
  AND visibility = 'private'
`, "ws_tutorial", "mem_tutorial").Scan(&profileCount))
	require.Equal(t, 1, profileCount)

	var membershipCount int
	require.NoError(t, db.QueryRow(ctx, `
SELECT COUNT(*)
FROM scope_memberships
WHERE scope_id = $1
  AND member_id = $2
  AND removed_at IS NULL
`, first.State.TutorialChannelID, "mem_tutorial").Scan(&membershipCount))
	require.Equal(t, 1, membershipCount)
}

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

	ctx := context.Background()
	db := startOnboardingRollbackDB(t, ctx)
	seedOnboardingWorkspace(t, ctx, db, "usr_existing_agent", "org_existing_agent", "ws_existing_agent", "mem_existing_agent")
	store := New(db)

	now := time.Now().UTC()
	mustOnboardingExec(t, ctx, db, `
INSERT INTO machines (id, workspace_id, created_by_user_id, name, api_key, created_at, updated_at)
VALUES ('mch_existing_agent', 'ws_existing_agent', 'usr_existing_agent', 'mch_existing_agent', 'key-existing-agent', $1, $1)
`, now)
	mustOnboardingExec(t, ctx, db, `
INSERT INTO members (id, workspace_id, type, display_name, status, created_at, updated_at)
VALUES ('mem_agent_existing_agent', 'ws_existing_agent', 'agent', 'Existing Agent', 'active', $1, $1)
`, now)
	mustOnboardingExec(t, ctx, db, `
INSERT INTO agents (id, workspace_id, machine_id, member_id, name, runtime, model, description, activity_detail, status, created_at, updated_at)
VALUES ('agt_existing_agent', 'ws_existing_agent', 'mch_existing_agent', 'mem_agent_existing_agent', 'existing-agent', 'builtin', 'agentteam/deepseek-v4-flash', '', '', 'active', $1, $1)
`, now)

	result, err := store.EnsureForUser(ctx, "usr_existing_agent", "ws_existing_agent", "en")
	require.NoError(t, err)
	require.False(t, result.Eligible)
	require.Equal(t, EligibilityReasonPreexistingAgentRuntime, result.EligibilityReason)

	var stateCount int
	require.NoError(t, db.QueryRow(ctx, `
SELECT COUNT(*)
FROM desktop_onboarding_states
WHERE user_id = 'usr_existing_agent'
  AND workspace_id = 'ws_existing_agent'
`).Scan(&stateCount))
	require.Zero(t, stateCount)
}

func seedOnboardingWorkspace(t *testing.T, ctx context.Context, db coredb.DB, userID string, organizationID string, workspaceID string, memberID string) {
	t.Helper()
	now := time.Now().UTC()
	mustOnboardingExec(t, ctx, db, `
INSERT INTO users (id, email, name, display_name, password_hash, is_admin, created_at, updated_at)
VALUES ($1, $2, $1, $1, 'hash', FALSE, $3, $3)
`, userID, userID+"@example.com", now)
	mustOnboardingExec(t, ctx, db, `
INSERT INTO organizations (id, slug, name, created_by_user_id, created_at, updated_at)
VALUES ($1, $1, $1, $2, $3, $3)
`, organizationID, userID, now)
	mustOnboardingExec(t, ctx, db, `
INSERT INTO workspaces (id, organization_id, slug, name, latest_message_seq, created_at, updated_at)
VALUES ($1, $2, $1, $1, 0, $3, $3)
`, workspaceID, organizationID, now)
	mustOnboardingExec(t, ctx, db, `
INSERT INTO members (id, workspace_id, type, display_name, user_id, workspace_role, status, created_at, updated_at)
VALUES ($1, $2, 'human', $3, $4, 'owner', 'active', $5, $5)
`, memberID, workspaceID, userID, userID, now)
}

func mustOnboardingExec(t *testing.T, ctx context.Context, db coredb.DB, query string, args ...any) {
	t.Helper()
	_, err := db.Exec(ctx, query, args...)
	require.NoError(t, err)
}
