package iace

import (
	"encoding/json"
	"os"
	"strconv"
	"testing"
)

func TestExtractDistanceTokens_Normalisation(t *testing.T) {
	toks := extractDistanceTokens([]string{
		"Abstand >= 25 mm und max. 250 mm/s",
		"Hand-Speed 1.600 mm/s", // German thousands → 1600
		"Querschnitt 2,5 mm",    // German decimal → 2.5
		"850mm ohne Leerzeichen",
	})
	got := map[string]bool{}
	for _, tk := range toks {
		got[tk.Unit+":"+strconv.FormatFloat(tk.Value, 'f', 1, 64)] = true
	}
	for _, want := range []string{"mm:25.0", "mm/s:250.0", "mm/s:1600.0", "mm:2.5", "mm:850.0"} {
		if !got[want] {
			t.Errorf("expected token %s, got %+v", want, toks)
		}
	}
}

func TestCompareDistances_MatchesAndGaps(t *testing.T) {
	gt := []string{"Abstand >= 25 mm", "max. 250 mm/s", "min. 850 mm", "<= 150 mm/s"}
	eng := []string{"Spalt 25 mm Fingerschutz", "Teach 250 mm/s", "850 mm Tunnel"}
	cmp := CompareDistances(gt, eng)
	if cmp.GTCount != 4 || cmp.MatchedCount != 3 {
		t.Fatalf("expected 3/4 matched, got %d/%d", cmp.MatchedCount, cmp.GTCount)
	}
	if len(cmp.GTOnly) != 1 || cmp.GTOnly[0].Value != 150 {
		t.Errorf("expected 150 mm/s as the gap, got %+v", cmp.GTOnly)
	}
}

// Real GT sessions: the engine library must cover the professional's headline
// dimensions (the engine measures were authored from these sessions).
func TestCompareSessionDistances_RealGT(t *testing.T) {
	var engTexts []string
	for _, m := range GetProtectiveMeasureLibrary() {
		engTexts = append(engTexts, m.Name, m.Description)
	}

	cases := []struct {
		file string
		must []DistanceToken
	}{
		{"testdata/ground_truth_bremse.json", []DistanceToken{
			{Value: 250, Unit: "mm/s"}, {Value: 250, Unit: "mm"}, {Value: 850, Unit: "mm"},
		}},
		{"testdata/ground_truth_kistenhub.json", []DistanceToken{
			{Value: 25, Unit: "mm"}, {Value: 120, Unit: "mm"},
			{Value: 150, Unit: "mm/s"}, {Value: 75, Unit: "mm/s"}, // filled by M603/M605
		}},
	}

	for _, tc := range cases {
		raw, err := os.ReadFile(tc.file)
		if err != nil {
			t.Fatalf("read %s: %v", tc.file, err)
		}
		var gt GroundTruth
		if err := json.Unmarshal(raw, &gt); err != nil {
			t.Fatalf("parse %s: %v", tc.file, err)
		}
		var gtTexts []string
		for _, e := range gt.Entries {
			gtTexts = append(gtTexts, e.Measures...)
		}
		cmp := CompareDistances(gtTexts, engTexts)
		for _, want := range tc.must {
			matched := false
			for _, m := range cmp.Matched {
				if m.Unit == want.Unit && m.Value == want.Value {
					matched = true
					break
				}
			}
			if !matched {
				t.Errorf("%s: engine should cover %.0f %s but it is a gap", tc.file, want.Value, want.Unit)
			}
		}
	}
}
