//go:build integration

package inttest

import (
	"context"
	"testing"
	"time"

	"github.com/google/uuid"

	"scrabble/backend/internal/account"
	"scrabble/backend/internal/game"
)

// TestMoveDurationAnalytics seeds a game with crafted move timestamps and checks the
// admin-console move-duration reports compute the think time (gap to the previous
// move, the first move measured from game creation) correctly, per account and per
// the account's move ordinal.
func TestMoveDurationAnalytics(t *testing.T) {
	ctx := context.Background()
	accounts := account.NewStore(testDB)
	a, err := accounts.ProvisionByIdentity(ctx, account.KindTelegram, "tg-"+uuid.NewString())
	if err != nil {
		t.Fatalf("provision A: %v", err)
	}
	b, err := accounts.ProvisionByIdentity(ctx, account.KindTelegram, "tg-"+uuid.NewString())
	if err != nil {
		t.Fatalf("provision B: %v", err)
	}

	gid := uuid.New()
	t0 := time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC)
	if _, err := testDB.ExecContext(ctx,
		`INSERT INTO backend.games (game_id, variant, dict_version, seed, players, turn_timeout_secs, created_at)
		 VALUES ($1,'scrabble_en','v1',1,2,86400,$2)`, gid, t0); err != nil {
		t.Fatalf("insert game: %v", err)
	}
	if _, err := testDB.ExecContext(ctx,
		`INSERT INTO backend.game_players (game_id, seat, account_id) VALUES ($1,0,$2),($1,1,$3)`, gid, a.ID, b.ID); err != nil {
		t.Fatalf("insert seats: %v", err)
	}
	// seq, seat, commit time as seconds from t0. Durations: A:60,50  B:120,200.
	moves := []struct{ seq, seat, at int }{{0, 0, 60}, {1, 1, 180}, {2, 0, 230}, {3, 1, 430}}
	for _, m := range moves {
		if _, err := testDB.ExecContext(ctx,
			`INSERT INTO backend.game_moves (game_id, seq, seat, action, created_at) VALUES ($1,$2,$3,'play',$4)`,
			gid, m.seq, m.seat, t0.Add(time.Duration(m.at)*time.Second)); err != nil {
			t.Fatalf("insert move %d: %v", m.seq, err)
		}
	}

	store := game.NewStore(testDB)
	stats, err := store.MoveDurationStats(ctx, []uuid.UUID{a.ID, b.ID})
	if err != nil {
		t.Fatalf("stats: %v", err)
	}
	if sa := stats[a.ID]; sa.Moves != 2 || sa.MinSecs != 50 || sa.MaxSecs != 60 || sa.AvgSecs != 55 {
		t.Errorf("A stats = %+v, want min50 max60 avg55 moves2", sa)
	}
	if sb := stats[b.ID]; sb.Moves != 2 || sb.MinSecs != 120 || sb.MaxSecs != 200 || sb.AvgSecs != 160 {
		t.Errorf("B stats = %+v, want min120 max200 avg160 moves2", sb)
	}

	byOrd, err := store.MoveDurationByOrdinal(ctx, a.ID)
	if err != nil {
		t.Fatalf("by ordinal: %v", err)
	}
	want := []game.OrdinalDuration{
		{Ordinal: 1, MinSecs: 60, MaxSecs: 60, AvgSecs: 60},
		{Ordinal: 2, MinSecs: 50, MaxSecs: 50, AvgSecs: 50},
	}
	if len(byOrd) != len(want) {
		t.Fatalf("by ordinal = %+v, want %+v", byOrd, want)
	}
	for i, w := range want {
		if byOrd[i] != w {
			t.Errorf("ordinal[%d] = %+v, want %+v", i, byOrd[i], w)
		}
	}
}
