package award

import (
	"testing"

	"hamlog/internal/qso"
)

// ddfmLike is a small stand-in for the French departments award: predefined
// references whose codes carry a letter the operator does not type.
func ddfmLike() []Def {
	return []Def{{
		Code: "DDFM", Name: "Departments", Type: TypeQSOFields,
		Field: "state", MatchBy: "code", Prefix: "D",
	}}
}

func ddfmRefs() map[string][]RefMeta {
	return map[string][]RefMeta{"DDFM": {
		{Code: "D29", Name: "Finistère", Valid: true},
		{Code: "D49", Name: "Maine-et-Loire", Valid: true},
		{Code: "D74", Name: "Haute-Savoie", Valid: true},
	}}
}

func refsOf(t *testing.T, defs []Def, q qso.QSO) []string {
	t.Helper()
	res := Compute(defs, []qso.QSO{q}, ddfmRefs(), nil)
	if len(res) != 1 {
		t.Fatalf("want 1 result, got %d", len(res))
	}
	var out []string
	for _, r := range res[0].Refs {
		if r.Worked {
			out = append(out, r.Ref)
		}
	}
	return out
}

// The reported case: the operator writes just "74" in STATE, the award's codes
// are "D74", match-by is "code" and a Prefix of "D" is set. That found nothing —
// the prefix was applied only AFTER the list lookup, i.e. after the step that
// had already failed — so the only workaround was a regex, in a mode where the
// operator had explicitly chosen "code" rather than "pattern".
func TestPrefixCompletesABareReference(t *testing.T) {
	got := refsOf(t, ddfmLike(), qso.QSO{Callsign: "F5AYE", State: "74"})
	if len(got) != 1 || got[0] != "D74" {
		t.Errorf("bare state 74 with prefix D → %v, want [D74]", got)
	}
}

// And a field that ALREADY holds the whole code must not be prefixed twice.
// The blanket pass turned "D74" into "DD74" whenever a prefix was configured.
func TestPrefixDoesNotDoubleUpOnACompleteCode(t *testing.T) {
	got := refsOf(t, ddfmLike(), qso.QSO{Callsign: "F5AYE", State: "D74"})
	if len(got) != 1 || got[0] != "D74" {
		t.Errorf("state D74 with prefix D → %v, want [D74]", got)
	}
}

// A token that is neither a code nor a prefixable one stays unmatched: the
// prefix must not invent references.
func TestPrefixDoesNotInventReferences(t *testing.T) {
	if got := refsOf(t, ddfmLike(), qso.QSO{Callsign: "F5AYE", State: "99"}); len(got) != 0 {
		t.Errorf("unknown department 99 → %v, want none", got)
	}
}

// Without a prefix nothing changes: a bare number matches nothing, a full code
// matches itself.
func TestNoPrefixKeepsExactCodeMatching(t *testing.T) {
	defs := ddfmLike()
	defs[0].Prefix = ""
	if got := refsOf(t, defs, qso.QSO{Callsign: "F5AYE", State: "74"}); len(got) != 0 {
		t.Errorf("no prefix, state 74 → %v, want none", got)
	}
	if got := refsOf(t, defs, qso.QSO{Callsign: "F5AYE", State: "D74"}); len(got) != 1 || got[0] != "D74" {
		t.Errorf("no prefix, state D74 → %v, want [D74]", got)
	}
}
