// Unit tests for the lightweight i18n primitive in
// `src/lib/i18n/index.svelte.ts`. The locale singleton is reset
// between cases through `resetForTests`; the default constructor
// derives the locale from JSDOM's `navigator.language`, so the
// reset takes an explicit value when a case needs a deterministic
// starting state.

import { afterEach, beforeEach, describe, expect, test } from "vitest";
import {
	DEFAULT_LOCALE,
	SUPPORTED_LOCALES,
	detectInitialLocale,
	i18n,
	type Locale,
} from "../src/lib/i18n/index.svelte";

beforeEach(() => {
	i18n.resetForTests("en");
});

afterEach(() => {
	i18n.resetForTests("en");
});

describe("detectInitialLocale", () => {
	test("matches the first supported primary subtag", () => {
		expect(detectInitialLocale(["ru-RU", "en-US"])).toBe("ru");
		expect(detectInitialLocale(["en-GB", "ru"])).toBe("en");
		expect(detectInitialLocale(["RU"])).toBe("ru");
	});

	test("skips unsupported tags and falls back to the default locale", () => {
		expect(detectInitialLocale(["fr-FR", "de-DE", "ja"])).toBe(DEFAULT_LOCALE);
		expect(detectInitialLocale([])).toBe(DEFAULT_LOCALE);
	});

	test("ignores whitespace and casing", () => {
		expect(detectInitialLocale(["  En-us  "])).toBe("en");
		expect(detectInitialLocale(["RU_ru"])).toBe("ru");
	});
});

describe("SUPPORTED_LOCALES", () => {
	test("each entry exposes a code, native name and translation table", () => {
		for (const entry of SUPPORTED_LOCALES) {
			expect(entry.code).toMatch(/^[a-z]{2}$/);
			expect(entry.nativeName.length).toBeGreaterThan(0);
			expect(entry.translations["login.title"].length).toBeGreaterThan(0);
		}
	});

	test("native names cover the two phase-7 locales", () => {
		const codes = SUPPORTED_LOCALES.map((l) => l.code);
		const names = SUPPORTED_LOCALES.map((l) => l.nativeName);
		expect(codes).toEqual(["en", "ru"]);
		expect(names).toEqual(["English", "Русский"]);
	});
});

describe("i18n.t", () => {
	test("returns the active locale's translation", () => {
		i18n.setLocale("en");
		expect(i18n.t("login.title")).toBe("sign in to Galaxy");
		i18n.setLocale("ru");
		expect(i18n.t("login.title")).toBe("вход в Galaxy");
	});

	test("returns the key itself for an unknown identifier", () => {
		// `t` is typed `TranslationKey`, but bracket access at runtime
		// gracefully handles unknown keys — the fallback chain tries
		// the active locale, then the default locale, then the literal
		// key. This is the safety net for a future locale that adds
		// keys before another locale catches up.
		i18n.setLocale("en");
		expect(
			i18n.t("does.not.exist" as unknown as Parameters<typeof i18n.t>[0]),
		).toBe("does.not.exist");
	});

	test("interpolates {placeholder} parameters", () => {
		i18n.setLocale("en");
		expect(i18n.t("login.code_sent_to", { email: "x@y.z" })).toBe(
			"code sent to x@y.z",
		);
		i18n.setLocale("ru");
		expect(i18n.t("login.code_sent_to", { email: "x@y.z" })).toBe(
			"код отправлен на x@y.z",
		);
	});

	test("leaves unresolved placeholders intact", () => {
		i18n.setLocale("en");
		expect(i18n.t("login.code_sent_to")).toContain("{email}");
		expect(i18n.t("login.code_sent_to", { other: "x" })).toContain(
			"{email}",
		);
	});
});

describe("i18n.setLocale", () => {
	test("setLocale updates the reactive state", () => {
		i18n.setLocale("en");
		expect(i18n.locale).toBe<Locale>("en");
		i18n.setLocale("ru");
		expect(i18n.locale).toBe<Locale>("ru");
	});
});
