package main

import (
	"os"
	"regexp"
	"strings"
	"testing"
)

// Every user-visible string ships in BOTH languages. That is a project rule,
// and until now it was only a rule: seventeen keys had drifted into English
// only, among them the whole update panel and two DX-cluster settings, found by
// a French operator photographing his own screen.
//
// A key present in one dictionary and not the other falls back to the key
// itself, so the interface shows "clu.spotTtl" where a label belongs — or, as
// here, the English text, which reads as deliberate and is not.
func TestEveryStringIsInBothLanguages(t *testing.T) {
	src, err := os.ReadFile("frontend/src/lib/i18n.tsx")
	if err != nil {
		t.Fatalf("read i18n.tsx: %v", err)
	}
	en := dictKeys(t, string(src), "const en: Dict = {")
	fr := dictKeys(t, string(src), "const fr: Dict = {")

	if len(en) == 0 || len(fr) == 0 {
		t.Fatal("one of the dictionaries came back empty — this test has stopped checking anything")
	}
	for k := range en {
		if !fr[k] {
			t.Errorf("%q has no French — a French operator sees the English string, or the key itself", k)
		}
	}
	for k := range fr {
		if !en[k] {
			t.Errorf("%q exists only in French — an English operator sees the key", k)
		}
	}
}

// dictKeys collects the keys of one dictionary literal: from its opening line
// to the closing brace in column 0.
func dictKeys(t *testing.T, src, opening string) map[string]bool {
	t.Helper()
	i := strings.Index(src, opening)
	if i < 0 {
		t.Fatalf("%q not found — the dictionaries have been renamed and this test needs updating", opening)
	}
	body := src[i+len(opening):]
	if j := strings.Index(body, "\n};"); j >= 0 {
		body = body[:j]
	}
	keyRe := regexp.MustCompile(`'([a-zA-Z0-9_.]+)'\s*:`)
	out := map[string]bool{}
	for _, m := range keyRe.FindAllStringSubmatch(body, -1) {
		out[m[1]] = true
	}
	return out
}
