package repository

import (
	"context"
	"testing"

	"apps/backend/internal/module/radar/domain"
)

func TestSweep_CreateAccumulateQuery(t *testing.T) {
	ctx := context.Background()
	m := NewMemory()

	sw := &domain.RadarSweep{
		OwnerUID:  7,
		WatchID:   "watch-a",
		JobID:     "job-1",
		Path:      domain.SweepPathAPI,
		StartedAt: domain.NowNano(),
	}
	if err := m.CreateSweep(ctx, sw); err != nil {
		t.Fatalf("create: %v", err)
	}
	if sw.ID == "" {
		t.Fatal("id not assigned")
	}

	// First progress tick.
	got, err := m.UpdateSweep(ctx, sw.ID, domain.SweepDelta{
		HitCount:          3,
		JudgedCount:       2,
		CreatedCount:      1,
		JudgedExternalIDs: []string{"e1", "e2"},
		CreditsUsed:       4,
	})
	if err != nil {
		t.Fatal(err)
	}
	if got.HitCount != 3 || got.JudgedCount != 2 || got.CreatedCount != 1 || got.CreditsUsed != 4 {
		t.Fatalf("after first delta: %+v", got)
	}
	if len(got.JudgedExternalIDs) != 2 {
		t.Fatalf("judged ids: %v", got.JudgedExternalIDs)
	}

	// Second tick: more hits, one new id, one duplicate id — must de-dupe.
	reason := "path unavailable"
	got, err = m.UpdateSweep(ctx, sw.ID, domain.SweepDelta{
		HitCount:          1,
		JudgedCount:       1,
		TruncatedCount:    2,
		JudgedExternalIDs: []string{"e2", "e3"},
		FailedReason:      &reason,
		EndedAt:           domain.NowNano(),
	})
	if err != nil {
		t.Fatal(err)
	}
	if got.HitCount != 4 || got.JudgedCount != 3 || got.TruncatedCount != 2 {
		t.Fatalf("after second delta counts wrong: %+v", got)
	}
	if len(got.JudgedExternalIDs) != 3 {
		t.Fatalf("want 3 unique judged ids, got %v", got.JudgedExternalIDs)
	}
	seen := map[string]bool{}
	for _, id := range got.JudgedExternalIDs {
		if seen[id] {
			t.Fatalf("duplicate judged id %s", id)
		}
		seen[id] = true
	}
	if !seen["e1"] || !seen["e2"] || !seen["e3"] {
		t.Fatalf("missing ids: %v", got.JudgedExternalIDs)
	}
	if got.FailedReason != reason {
		t.Fatalf("failed_reason=%q", got.FailedReason)
	}
	if got.EndedAt == 0 {
		t.Fatal("ended_at not set")
	}

	byJob, err := m.GetSweepByJobID(ctx, "job-1")
	if err != nil {
		t.Fatal(err)
	}
	if byJob.ID != sw.ID {
		t.Fatalf("GetSweepByJobID id mismatch")
	}

	list, total, err := m.ListSweeps(ctx, 7, domain.SweepListFilter{WatchID: "watch-a"})
	if err != nil {
		t.Fatal(err)
	}
	if total != 1 || len(list) != 1 {
		t.Fatalf("list want 1, total=%d len=%d", total, len(list))
	}
}
