-- Locale smoke: locale registry + fallback chain + binding
-- engine's "locale:" prefix resolution.

dofile("wow_mock.lua")
dofile("../Core/HDGR_SchemeConstants.lua")
dofile("../Core/HDGR_Constants.lua")
dofile("../Core/HDGR_Format.lua")
dofile("../Core/HDGR_Paths.lua")
dofile("../Core/HDGR_Log.lua")
dofile("../Core/HDGR_Locale.lua")

local function assertEq(actual, expected, label)
    if actual ~= expected then
        error(label .. ": expected " .. tostring(expected) .. ", got " .. tostring(actual), 2)
    end
end

HDG.Locale:_Reset()

-- ===== Register + Get: simple enUS lookup =====
HDG.Locale:Register("enUS", {
    HELLO = "Hello",
    GOODBYE = "Goodbye",
})
assertEq(HDG.Locale:Get("HELLO"), "Hello", "enUS direct lookup")
assertEq(HDG.Locale:Get("GOODBYE"), "Goodbye", "another enUS key")

-- ===== Missing key returns key itself (loud failure) =====
assertEq(HDG.Locale:Get("NONEXISTENT"), "NONEXISTENT",
    "missing key returns the key string (loud)")

-- ===== Fallback chain: current locale -> enUS -> key =====
HDG.Locale:Register("deDE", {
    HELLO = "Hallo",
    -- GOODBYE intentionally absent -- tests fallback
})
HDG.Locale:SetLocale("deDE")
assertEq(HDG.Locale:Get("HELLO"), "Hallo", "deDE override")
assertEq(HDG.Locale:Get("GOODBYE"), "Goodbye",
    "deDE missing key falls back to enUS")
assertEq(HDG.Locale:Get("NEVER_DEFINED"), "NEVER_DEFINED",
    "deDE and enUS both missing -> key")

-- ===== Merge across multiple Register calls =====
HDG.Locale:SetLocale("enUS")
HDG.Locale:Register("enUS", { LATER_KEY = "added later" })
assertEq(HDG.Locale:Get("HELLO"), "Hello", "earlier keys survive merge")
assertEq(HDG.Locale:Get("LATER_KEY"), "added later", "new keys merged in")

-- Override existing key via later Register
HDG.Locale:Register("enUS", { HELLO = "Hi" })
assertEq(HDG.Locale:Get("HELLO"), "Hi", "later Register overrides")

-- ===== Empty / nil key handling =====
assertEq(HDG.Locale:Get(""), "", "empty string returns empty")
assertEq(HDG.Locale:Get(nil), "", "nil key returns empty string")

-- ===== Real shipped enUS table loads =====
dofile("../Locale/enUS.lua")
assertEq(HDG.Locale:Get("TAB_DECOR"), "Decor", "shipped key TAB_DECOR")
assertEq(HDG.Locale:Get("ACQ_ALL_FACTIONS"), "All factions",
    "shipped key ACQ_ALL_FACTIONS")

-- ===== Resolve: "locale:KEY" prefix on static fields =====
assertEq(HDG.Locale:Resolve("locale:TAB_DECOR"), "Decor",
    "Resolve strips locale: prefix and looks up")
assertEq(HDG.Locale:Resolve("Plain text"), "Plain text",
    "Resolve passes plain strings through")
assertEq(HDG.Locale:Resolve(42), 42, "Resolve passes non-strings through")
assertEq(HDG.Locale:Resolve("locale:DECOR_FILTER_LABEL"), "Filter:",
    "Resolve resolves a newly-added Decor key")

-- ===== Pseudolocale: bracket every enUS value (dev coverage tester) =====
HDG.Locale:SetLocale("enXX")
assertEq(HDG.Locale:Get("TAB_DECOR"), "[Decor]", "pseudo brackets enUS value")
assertEq(HDG.Locale:Resolve("locale:DECOR_BROWSER_TITLE"), "[Decor Browser]",
    "pseudo brackets via Resolve")
assertEq(HDG.Locale:Get("UNTRANSLATED_KEY"), "[UNTRANSLATED_KEY]",
    "pseudo brackets the raw key when no enUS entry exists")
HDG.Locale:SetLocale("enUS")  -- restore for the BindingEngine section below

-- ===== GetAvailableLocales: Auto first, enUS, pseudo last =====
local locales = HDG.Locale:GetAvailableLocales()
assertEq(locales[1].key, "", "first option is Auto (client locale)")
assertEq(locales[2].key, "enUS", "enUS sorts first among registered")
assertEq(locales[#locales].key, "enXX", "pseudolocale is the last option")

-- ===== BindingEngine resolves "locale:KEY" =====
dofile("../Core/HDGR_WidgetTypes.lua")
dofile("../UI/HDGR_Selectors.lua")
dofile("../UI/HDGR_Selectors_Status.lua")
dofile("../UI/HDGR_Selectors_Decor.lua")
dofile("../UI/HDGR_Selectors_Acquisition.lua")
dofile("../UI/HDGR_Selectors_Recipes.lua")
dofile("../UI/HDGR_BindingEngine.lua")

-- Register a tiny widget type so we can build a fake bound widget. The
-- WidgetTypes registry is deferred (Flush at OnInitialize); call Flush
-- manually since this test doesn't run the full bootstrap.
HDG.WidgetTypes:Register("testLabel", {
    build    = function(parent, spec) return {} end,
    dispatch = { fields = {"text"}, push = function(w, v) w.text = v.text end },
})
HDG.WidgetTypes:Flush()
-- Fake root with one widget that uses locale: binding
local fakeRoot = {
    widgets = {
        ["test.label"] = {},
    },
}
local fakeConfig = {
    widgets = {
        ["test.label"] = {
            kind = "testLabel",
            binding = "locale:TAB_DECOR",
        },
    },
}

HDG.BindingEngine:Build(fakeRoot, fakeConfig)
HDG.BindingEngine:Apply(fakeRoot, {})
assertEq(fakeRoot.widgets["test.label"].text, "Decor",
    "locale: prefix resolves through HDG.Locale")

-- Locale binding contributes no state-path reads (closure = empty)
local readsClosure = fakeRoot.widgets["test.label"]._hdgrReadsClosure
assertEq(type(readsClosure), "table", "locale binding has empty reads closure")
assertEq(#readsClosure, 0, "no state paths in closure for locale binding")

-- ===== Missing key surfaces as the key string =====
fakeRoot.widgets["test.label"]._hdgrReadsClosure = nil  -- reset
fakeConfig.widgets["test.label"].binding = "locale:NOT_DEFINED"
HDG.BindingEngine:Build(fakeRoot, fakeConfig)
HDG.BindingEngine:Apply(fakeRoot, {})
assertEq(fakeRoot.widgets["test.label"].text, "NOT_DEFINED",
    "missing locale key surfaces as raw key (loud)")

print("test_locale_smoke.lua passed")
