package domain

import (
	"errors"
	"testing"
)

func TestNormalizeTargetCount(t *testing.T) {
	for _, tc := range []struct {
		input, want int
	}{
		{0, 20}, {-2, 20}, {1, 1}, {40, 40}, {41, 40},
	} {
		if got := NormalizeTargetCount(tc.input); got != tc.want {
			t.Fatalf("NormalizeTargetCount(%d) = %d, want %d", tc.input, got, tc.want)
		}
	}
}

func TestRunTransitionGuarded(t *testing.T) {
	run := NewRun("run-1", "job-1", 9, RunBrief{Intent: "topic", TargetCount: 3}, 1_700_000_000_000_000_000)
	if run.Status != RunQueued || run.CreatedAt == 0 {
		t.Fatalf("new run not queued with timestamp: %+v", run)
	}
	if err := run.Transition(RunSucceeded, 2); !errors.Is(err, ErrIllegalRunStatus) {
		t.Fatalf("queued -> succeeded should be guarded, got %v", err)
	}
	if err := run.Transition(RunRunning, 2); err != nil {
		t.Fatalf("queued -> running: %v", err)
	}
	if run.StartedAt != 2 {
		t.Fatalf("started_at = %d, want 2", run.StartedAt)
	}
	if err := run.Transition(RunSucceeded, 3); err != nil {
		t.Fatalf("running -> succeeded: %v", err)
	}
	if run.CompletedAt != 3 || !IsRunTerminal(run.Status) {
		t.Fatalf("terminal timestamps/status not set: %+v", run)
	}
	if err := run.Transition(RunRunning, 4); !errors.Is(err, ErrIllegalRunStatus) {
		t.Fatalf("terminal -> running should be guarded, got %v", err)
	}
}

func TestRunShortfallReasonsAreStableConstants(t *testing.T) {
	reasons := []string{
		ShortfallSourceExhausted,
		ShortfallDuplicateExhausted,
		ShortfallRelevanceExhausted,
		ShortfallSourceUnavailable,
		ShortfallLimitReached,
	}
	seen := map[string]bool{}
	for _, reason := range reasons {
		if reason == "" || seen[reason] {
			t.Fatalf("invalid duplicate reason %q", reason)
		}
		seen[reason] = true
	}
}
