package ucca

import "testing"

func ares(reg, cu, sc string, score float64, weight int, out, in []string) LegalSearchResult {
	return LegalSearchResult{
		RegulationShort: reg, CitationUnit: cu, SourceClass: sc, Score: score,
		AuthorityWeight: weight, ReferencesOut: out, ReferencesIn: in,
	}
}

func TestAssess_Empty(t *testing.T) {
	if Assess(nil) != nil {
		t.Error("empty results → nil assessment")
	}
}

func TestAssess_BindingPrimary_NoReview(t *testing.T) {
	results := []LegalSearchResult{
		ares("CRA", "Art. 13 CRA", "binding_law", 1.05, 100,
			[]string{"CRA Anhang I", "Art. 14 CRA"}, []string{"Art. 12 CRA"}),
		ares("CRA", "Art. 14 CRA", "binding_law", 0.80, 100, nil, nil),
	}
	a := Assess(results)
	if a == nil {
		t.Fatal("nil assessment")
	}
	if a.PrimaryNorm != "Art. 13 CRA" || a.PrimaryRegulation != "CRA" {
		t.Errorf("primary wrong: %+v", a)
	}
	if len(a.ConnectedNorms) != 3 { // out(2) + in(1), self excluded, deduped
		t.Errorf("connected norms: %v", a.ConnectedNorms)
	}
	if a.CrossRegime {
		t.Error("single regime must not be cross-regime")
	}
	if a.WinnerMargin < 0.24 || a.WinnerMargin > 0.26 {
		t.Errorf("margin = %v, want ~0.25", a.WinnerMargin)
	}
	if a.HumanReviewFlag {
		t.Error("clean binding + healthy margin + single regime → no review")
	}
}

func TestAssess_CrossRegimeFlagsReview(t *testing.T) {
	a := Assess([]LegalSearchResult{
		ares("CRA", "Art. 13 CRA", "binding_law", 1.05, 100, nil, nil),
		ares("DORA", "Art. 6 DORA", "binding_law", 0.70, 100, nil, nil),
	})
	if !a.CrossRegime || !a.HumanReviewFlag {
		t.Errorf("cross-regime must flag review: %+v", a)
	}
}

func TestAssess_NonBindingFlagsReview(t *testing.T) {
	a := Assess([]LegalSearchResult{
		ares("ENISA", "ENISA SBOM", "supervisory_guidance", 0.90, 70, nil, nil),
		ares("ENISA", "ENISA X", "supervisory_guidance", 0.40, 70, nil, nil),
	})
	if !a.HumanReviewFlag {
		t.Error("non-binding primary → review")
	}
}

func TestAssess_TightMarginFlagsReview(t *testing.T) {
	a := Assess([]LegalSearchResult{
		ares("CRA", "Art. 13 CRA", "binding_law", 1.00, 100, nil, nil),
		ares("CRA", "Art. 14 CRA", "binding_law", 0.98, 100, nil, nil),
	})
	if a.WinnerMargin >= 0.05 || !a.HumanReviewFlag {
		t.Errorf("tight margin → review: %+v", a)
	}
}

func TestAssess_MarginIsNormLevelNotChunkLevel(t *testing.T) {
	// Two near-identical chunks of the SAME norm at the top, then a distinct norm.
	results := []LegalSearchResult{
		ares("CRA", "Art. 13 CRA", "binding_law", 1.050, 100, []string{"CRA Anhang I"}, nil),
		ares("CRA", "Art. 13 CRA", "binding_law", 1.049, 100, nil, nil), // same norm
		ares("CRA", "Art. 14 CRA", "binding_law", 0.800, 100, nil, nil),
	}
	a := Assess(results)
	if a.WinnerMargin < 0.24 || a.WinnerMargin > 0.26 { // Art.13 vs Art.14, not chunk vs chunk
		t.Errorf("margin must be norm-level (~0.25), got %v", a.WinnerMargin)
	}
	if a.HumanReviewFlag {
		t.Error("healthy norm-level margin → no review")
	}
}

func TestDistinctNorms(t *testing.T) {
	got := distinctNorms([]LegalSearchResult{
		{CitationUnit: "Art. 13 CRA"},
		{CitationUnit: "Art. 13 CRA"}, // duplicate norm → collapsed
		{CitationUnit: "Art. 14 CRA"},
		{CitationUnit: ""}, // no identity → kept
		{CitationUnit: ""}, // no identity → kept
	})
	if len(got) != 4 {
		t.Errorf("want 4 (2 distinct + 2 unidentified), got %d", len(got))
	}
}

func TestDedupStrings(t *testing.T) {
	got := dedupStrings([]string{"a", "b", "", "a"}, []string{"b", "c"}, "self")
	if len(got) != 3 || got[0] != "a" || got[1] != "b" || got[2] != "c" {
		t.Errorf("dedup: %v", got)
	}
	if len(dedupStrings([]string{"self"}, nil, "self")) != 0 {
		t.Error("excluded value must be dropped")
	}
}
