package taskboard

import (
	"context"
	"reflect"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

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

type scriptedReviewRollupQueryResult struct {
	rows [][]any
	err  error
}

type scriptedReviewRollupTx struct {
	queryQueries []string
	queryArgs    [][]any
	execQueries  []string
	execArgs     [][]any
	queryResults []scriptedReviewRollupQueryResult
}

func (tx *scriptedReviewRollupTx) Query(_ context.Context, query string, args ...any) (coredb.Rows, error) {
	tx.queryQueries = append(tx.queryQueries, query)
	tx.queryArgs = append(tx.queryArgs, append([]any(nil), args...))
	if len(tx.queryResults) == 0 {
		return &scriptedReviewRollupRows{}, nil
	}
	result := tx.queryResults[0]
	tx.queryResults = tx.queryResults[1:]
	if result.err != nil {
		return nil, result.err
	}
	return &scriptedReviewRollupRows{rows: result.rows}, nil
}

func (tx *scriptedReviewRollupTx) QueryRow(_ context.Context, _ string, _ ...any) coredb.Row {
	return scriptedTaskboardRow{err: nil}
}

func (tx *scriptedReviewRollupTx) Exec(_ context.Context, query string, args ...any) (coredb.Result, error) {
	tx.execQueries = append(tx.execQueries, query)
	tx.execArgs = append(tx.execArgs, append([]any(nil), args...))
	return testExecResult{rowsAffected: 1}, nil
}

func (tx *scriptedReviewRollupTx) Commit(context.Context) error {
	return nil
}

func (tx *scriptedReviewRollupTx) Rollback(context.Context) error {
	return nil
}

type scriptedReviewRollupRows struct {
	rows  [][]any
	index int
}

func (rows *scriptedReviewRollupRows) Close() {}

func (rows *scriptedReviewRollupRows) Err() error {
	return nil
}

func (rows *scriptedReviewRollupRows) Next() bool {
	if rows.index >= len(rows.rows) {
		return false
	}
	rows.index++
	return true
}

func (rows *scriptedReviewRollupRows) Scan(dest ...any) error {
	current := rows.rows[rows.index-1]
	for index, value := range current {
		reflect.ValueOf(dest[index]).Elem().Set(reflect.ValueOf(value))
	}
	return nil
}

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

	tx := &scriptedReviewRollupTx{
		queryResults: []scriptedReviewRollupQueryResult{
			{
				rows: [][]any{
					{"tsk_child_1"},
					{"tsk_child_2"},
				},
			},
			{
				rows: [][]any{
					{"wsp_1", int64(2)},
				},
			},
		},
	}

	err := (&Service{}).rollUpChildReviewsForParentTask(
		context.Background(),
		tx,
		"wsp_1",
		"tsk_parent",
		"mem_actor",
		time.Date(2026, 4, 19, 15, 0, 0, 0, time.UTC),
	)
	require.NoError(t, err)
	require.Len(t, tx.queryQueries, 3)
	require.Len(t, tx.execQueries, 6)
	require.Contains(t, tx.queryQueries[0], "SELECT id")
	require.Contains(t, tx.queryQueries[1], "COUNT(*) AS event_count")
	require.Contains(t, tx.queryQueries[2], "WITH requested_events AS")
	require.Contains(t, tx.queryQueries[2], "JOIN scope_activity_events ae")
	require.Contains(t, tx.execQueries[0], "UPDATE task_review_requests")
	require.Contains(t, tx.execQueries[1], "UPDATE tasks")
	require.Contains(t, tx.execQueries[2], "UPDATE scopes")
	require.Contains(t, tx.execQueries[3], "INSERT IGNORE INTO scope_activity_workspace_counters")
	require.Contains(t, tx.execQueries[4], "UPDATE scope_activity_workspace_counters")
	require.Contains(t, tx.execQueries[5], "INSERT INTO scope_activity_events")
	for _, query := range tx.execQueries {
		require.NotContains(t, query, "task_activity_unread_count")
		require.NotContains(t, query, "last_high_signal_at")
		require.NotContains(t, query, "task_inbox_active")
	}
}
