-- test_button_hover_theme.lua
-- Regression: the Button skinner's hover (OnEnter/OnLeave) text repaint must track
-- the TERTIARY text tokens, not the variant's. Every text button renders on the dark
-- tertiary atlas (variant tints only the border), so a `primary`/`danger` button keyed
-- to button.primary.text.hover got C.text_inverse (a DARK color tuned for a light fill)
-- and the label vanished on hover. This pins the fix: hover stays light/legible, and a
-- _textTone button keeps its tone in BOTH directions.
--
-- Skinner signature: Skinner(frame, scheme, state).

local _realPrint = print
local function out(s) _realPrint(s) end

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")

HDG.Store = HDG.Store or {
    Subscribe = function() end,
    GetState  = function() return { account = { config = { scheme = "" } } } end,
}

dofile("../UI/HDGR_Theme.lua")

local Button = HDG.Theme.Skinners.Button
local function assertTrue(v, label) if not v then error("ASSERT FAILED: " .. tostring(label), 2) end end
assertTrue(Button, "Button skinner registered")

-- Color compare (r,g,b,a within epsilon). nil-safe.
local function colorEq(a, b)
    if not (a and b) then return false end
    local e = 0.0005
    return math.abs((a.r or 0) - (b.r or 0)) < e and math.abs((a.g or 0) - (b.g or 0)) < e
       and math.abs((a.b or 0) - (b.b or 0)) < e and math.abs((a.a or 1) - (b.a or 1)) < e
end

-- Mock atlas-path text button: GetNormalTexture truthy -> the skinner takes the
-- atlas branch (the path HDG.UI:Button produces). Captures the last text color and
-- the hover handlers the skinner hooks.
local function mockButton(variant, textTone)
    local captured = {}
    local fs = { SetTextColor = function(_, r, g, b, a) captured.r, captured.g, captured.b, captured.a = r, g, b, a end }
    local function tex() return { SetVertexColor = function() end } end
    local handlers = {}
    local btn = {
        _hdgrVariant        = variant,
        _textTone           = textTone,
        GetFontString       = function() return fs end,
        GetNormalTexture    = tex,   -- truthy -> atlas path
        GetHighlightTexture = tex,
        GetPushedTexture    = tex,
        GetDisabledTexture  = tex,
        SetNormalAtlas      = function() end,
        SetHighlightAtlas   = function() end,
        HookScript          = function(_, name, fn) handlers[name] = fn end,
    }
    return btn, captured, handlers
end

local C = HDG.Theme
local tertiaryHover  = C:GetColor("button.tertiary.text.hover")
local tertiaryNormal = C:GetColor("button.tertiary.text.normal")
local primaryHover   = C:GetColor("button.primary.text.hover")   -- = text_inverse (the bug color)
local primaryNormal  = C:GetColor("button.primary.text.normal")  -- = text_inverse
assertTrue(not colorEq(tertiaryHover, primaryHover),
    "precondition: tertiary.text.hover differs from primary.text.hover (else the test proves nothing)")

-- ===== primary variant: hover must NOT flip to text_inverse =====
do
    local btn, captured, h = mockButton("primary", nil)
    Button(btn, "default", { active = false })
    assertTrue(colorEq(captured, tertiaryNormal), "steady-state primary text = tertiary.text.normal (light)")
    assertTrue(h.OnEnter and h.OnLeave, "hover handlers hooked")

    h.OnEnter(btn)
    assertTrue(colorEq(captured, tertiaryHover),  "OnEnter -> tertiary.text.hover (light, legible)")
    assertTrue(not colorEq(captured, primaryHover), "OnEnter is NOT primary.text.hover (text_inverse = the vanish bug)")

    h.OnLeave(btn)
    assertTrue(colorEq(captured, tertiaryNormal),   "OnLeave -> tertiary.text.normal")
    assertTrue(not colorEq(captured, primaryNormal), "OnLeave is NOT primary.text.normal (text_inverse)")
end

-- ===== danger variant: same family bug, same fix =====
do
    local btn, captured, h = mockButton("danger", nil)
    Button(btn, "default", { active = false })
    h.OnEnter(btn)
    assertTrue(colorEq(captured, tertiaryHover), "danger OnEnter -> tertiary.text.hover, not text_inverse")
end

-- ===== _textTone overrides in BOTH directions (was OnLeave-only) =====
do
    local errTone = C:GetColor("semantic.error")
    assertTrue(errTone, "semantic.error resolves")
    local btn, captured, h = mockButton("primary", "error")
    Button(btn, "default", { active = false })
    h.OnEnter(btn)
    assertTrue(colorEq(captured, errTone), "OnEnter honors _textTone (semantic.error)")
    h.OnLeave(btn)
    assertTrue(colorEq(captured, errTone), "OnLeave honors _textTone (semantic.error)")
end

-- ===== active state: hover repaint is skipped (active branch owns the color) =====
do
    local btn, captured, h = mockButton("primary", nil)
    HDG.Theme.states[btn] = { active = true }
    -- Paint with states set first so the active branch owns the color.
    Button(btn, "default", { active = true })
    local beforeEnter = { r = captured.r, g = captured.g, b = captured.b, a = captured.a }
    h.OnEnter(btn)
    assertTrue(colorEq(captured, beforeEnter), "active button: OnEnter is a no-op (active owns the color)")
    HDG.Theme.states[btn] = nil
end

out("test_button_hover_theme.lua passed")
