-- ============================================================================
-- Vamoose's Companion - Theme Engine
-- Manages theme registry and skinners for live theme switching
-- ============================================================================

VC = VC or {}
VC.Theme = {}

-- Weak table: automatically stops tracking widgets if they are garbage collected
VC.Theme.registry = setmetatable({}, { __mode = "k" })
VC.Theme.currentScheme = nil

-- ============================================================================
-- CENTRALIZED BACKDROP
-- ============================================================================

VC.Theme.BACKDROP_FLAT = {
    bgFile = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    edgeSize = 1,
    insets = { left = 0, right = 0, top = 0, bottom = 0 }
}

VC.Theme.BACKDROP_BORDERLESS = {
    bgFile = "Interface\\Buttons\\WHITE8x8",
    edgeFile = nil,
    tile = false,
}

-- Standard panel: 1px border, content inset 1px (border doesn't overlap content)
VC.Theme.BACKDROP_PANEL = {
    bgFile   = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    edgeSize = 1,
    insets   = { left = 1, right = 1, top = 1, bottom = 1 }
}

-- Inset panel: no border inset (for inner containers)
VC.Theme.BACKDROP_INSET = {
    bgFile   = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    edgeSize = 1,
    insets   = { left = 0, right = 0, top = 0, bottom = 0 }
}

-- ============================================================================
-- INITIALIZATION
-- ============================================================================

function VC.Theme:Initialize()
    local themeKey = "slipstreamdark"
    if VC.Store and VC.Store.state and VC.Store.state.config then
        themeKey = VC.Store.state.config.theme or "slipstreamdark"
    elseif VC_DB and VC_DB.config and VC_DB.config.theme then
        themeKey = VC_DB.config.theme or "slipstreamdark"
    end
    local themeName = VC.Constants.ThemeNames[themeKey] or "SlipstreamDark"
    self.currentScheme = VC.Colors.Schemes[themeName] or VC.Colors.Schemes.SlipstreamDark

    if VC.EventBus then
        VC.EventBus:Register("VC_THEME_UPDATE", function(payload)
            if payload.themeName then
                self.currentScheme = VC.Colors.Schemes[payload.themeName] or VC.Colors.Schemes.SlipstreamDark
            end
            self:UpdateAll()
        end)
    end
end

-- ============================================================================
-- UPDATE ALL REGISTERED WIDGETS
-- ============================================================================

function VC.Theme:UpdateAll()
    for widget, widgetType in pairs(self.registry) do
        if self.Skinners[widgetType] then
            self.Skinners[widgetType](widget, self.currentScheme)
        end
    end
end

-- ============================================================================
-- REGISTER WIDGET
-- ============================================================================

function VC.Theme:Register(widget, widgetType)
    self.registry[widget] = widgetType
    if self.Skinners[widgetType] and self.currentScheme then
        self.Skinners[widgetType](widget, self.currentScheme)
    end
end

-- ============================================================================
-- GET CURRENT SCHEME
-- ============================================================================

function VC.Theme:GetScheme()
    return self.currentScheme or VC.Colors.Schemes.SlipstreamDark
end

-- ============================================================================
-- TEXT STYLING HELPERS
-- ============================================================================

local function ApplyTextShadow(fontString, scheme)
    if not fontString or not fontString.SetShadowOffset then return end
    fontString:SetShadowOffset(1, -1)
    if scheme.isLight then
        local r, g, b = fontString:GetTextColor()
        fontString:SetShadowColor(r, g, b, 0.4)
    else
        fontString:SetShadowColor(0, 0, 0, 1)
    end
end

local function ApplyFont(fontString, scheme, fontType)
    if not fontString or not fontString.SetFont then return end
    fontType = fontType or "body"
    local f = scheme.fonts and scheme.fonts[fontType] or (scheme.fonts and scheme.fonts.body)
    if f then
        local fontFile = VC.Constants:GetFontFile()
        local fontScale = 0
        if VC.Store and VC.Store.state and VC.Store.state.config then
            fontScale = VC.Store.state.config.fontScale or 0
        end
        fontString:SetFont(fontFile, f.size + fontScale, f.flags)
    end
    ApplyTextShadow(fontString, scheme)
end

VC.Theme.ApplyTextShadow = ApplyTextShadow
VC.Theme.ApplyFont = ApplyFont

-- ============================================================================
-- SKINNERS (Pure functions that apply colors to widgets)
-- ============================================================================

VC.Theme.Skinners = {

    -- Window/Frame skinner
    Frame = function(f, c)
        if f:GetBackdrop() then
            f:SetBackdropColor(c.bg.r, c.bg.g, c.bg.b, c.bg.a)
            f:SetBackdropBorderColor(c.border.r, c.border.g, c.border.b, c.border.a)
        end
        if f.title then
            f.title:SetTextColor(c.text_header.r, c.text_header.g, c.text_header.b, c.text_header.a)
            ApplyFont(f.title, c)
        end
    end,

    -- Panel skinner
    Panel = function(f, c)
        if f:GetBackdrop() then
            f:SetBackdropColor(c.panel.r, c.panel.g, c.panel.b, c.panel.a)
            f:SetBackdropBorderColor(c.border.r, c.border.g, c.border.b, c.border.a)
        end
    end,

    -- Button skinner (flat texture, no backdrop)
    Button = function(b, c)
        if b._bg then
            local col = b._activeColor or c.button_normal
            b._bg:SetVertexColor(col.r, col.g, col.b, col.a)
        end
        local fs = b:GetFontString()
        if fs then
            fs:SetTextColor(c.button_text_norm.r, c.button_text_norm.g, c.button_text_norm.b, c.button_text_norm.a)
            ApplyFont(fs, c)
        end
        b._scheme = c
    end,

    -- Text/Label skinner
    Text = function(fs, c)
        if fs.isHeader then
            fs:SetTextColor(c.text_header.r, c.text_header.g, c.text_header.b, c.text_header.a)
        else
            fs:SetTextColor(c.text.r, c.text.g, c.text.b, c.text.a)
        end
        ApplyFont(fs, c)
    end,

    -- Checkbox skinner
    Checkbox = function(f, c)
        if f.label then
            f.label:SetTextColor(c.text.r, c.text.g, c.text.b)
            ApplyFont(f.label, c)
        end
    end,

    -- Dim text skinner (labels, descriptions, subtitles — works on FontStrings and Textures)
    DimText = function(fs, c)
        if fs.SetTextColor then
            fs:SetTextColor(c.text_dim.r, c.text_dim.g, c.text_dim.b, 1)
        elseif fs.SetVertexColor then
            fs:SetVertexColor(c.text_dim.r, c.text_dim.g, c.text_dim.b, 1)
        end
    end,

    -- Accent text skinner (scale values, highlights — works on FontStrings and Textures)
    AccentText = function(fs, c)
        if fs.SetTextColor then
            fs:SetTextColor(c.accent.r, c.accent.g, c.accent.b, 1)
        elseif fs.SetVertexColor then
            fs:SetVertexColor(c.accent.r, c.accent.g, c.accent.b, 1)
        end
    end,

    -- Separator skinner (border-colored line textures)
    Separator = function(tex, c)
        tex:SetVertexColor(c.border.r, c.border.g, c.border.b, tex._alpha or 0.4)
    end,

    -- Highlight row skinner
    Highlight = function(f, c)
        if f.bg then
            f.bg:SetColorTexture(c.panel.r, c.panel.g, c.panel.b, 0.3)
        end
    end,

    -- Section label skinner (accent line + header text)
    SectionLabel = function(f, c)
        if f.line then
            f.line:SetColorTexture(c.accent.r, c.accent.g, c.accent.b, 0.3)
        end
        if f.label then
            f.label:SetTextColor(c.text_header.r, c.text_header.g, c.text_header.b, c.text_header.a)
            ApplyFont(f.label, c)
        end
    end,

    -- Segmented button (inactive state; active state applied via btn:SetActive(true))
    SegmentedButton = function(btn, c)
        if btn:GetBackdrop() then
            btn:SetBackdropColor(c.panel.r, c.panel.g, c.panel.b, 1)
            btn:SetBackdropBorderColor(c.border.r, c.border.g, c.border.b, 1)
        end
        local fs = btn:GetFontString()
        if fs then fs:SetTextColor(c.text_dim.r, c.text_dim.g, c.text_dim.b, 1) end
        btn._scheme = c
    end,

    -- Companion pill button (active/inactive managed externally via _activeColor)
    PillButton = function(btn, c)
        if btn:GetBackdrop() then
            local col = btn._activeColor
            if col then
                btn:SetBackdropColor(c.accent.r, c.accent.g, c.accent.b, 0.20)
                btn:SetBackdropBorderColor(c.accent.r, c.accent.g, c.accent.b, 1)
            else
                btn:SetBackdropColor(c.panel.r, c.panel.g, c.panel.b, 1)
                btn:SetBackdropBorderColor(c.border.r, c.border.g, c.border.b, 1)
            end
        end
        local fs = btn:GetFontString()
        if fs then
            if btn._activeColor then
                fs:SetTextColor(c.text_header.r, c.text_header.g, c.text_header.b, 1)
            else
                fs:SetTextColor(c.text_dim.r, c.text_dim.g, c.text_dim.b, 1)
            end
        end
        btn._scheme = c
    end,

    -- Tab button (flat button with accent underline when active)
    TabButton = function(btn, c)
        local fs = btn:GetFontString()
        if fs then
            if btn._active then
                fs:SetTextColor(c.text_header.r, c.text_header.g, c.text_header.b, 1)
            else
                fs:SetTextColor(c.text_dim.r, c.text_dim.g, c.text_dim.b, 1)
            end
        end
        if btn._underline then
            btn._underline:SetColorTexture(c.accent.r, c.accent.g, c.accent.b, 1)
            btn._underline:SetShown(btn._active)
        end
        btn._scheme = c
    end,

    -- Scrollbar skinner (accent-colored thumb)
    ScrollBar = function(sb, c)
        local tr, tg, tb = c.accent.r, c.accent.g, c.accent.b
        if sb._vcThumbTexture then
            sb._vcThumbTexture:SetVertexColor(tr, tg, tb, 0.7)
        end
    end,

    -- Quote bubble skinner (companion-specific)
    QuoteBubble = function(f, c)
        if f:GetBackdrop() then
            f:SetBackdropColor(c.panel.r, c.panel.g, c.panel.b, c.panel.a * 0.95)
            f:SetBackdropBorderColor(c.accent.r, c.accent.g, c.accent.b, c.accent.a * 0.6)
        end
        if f.nameText then
            f.nameText:SetTextColor(c.accent.r, c.accent.g, c.accent.b, c.accent.a)
            ApplyFont(f.nameText, c, "small")
        end
        if f.quoteText then
            f.quoteText:SetTextColor(c.text.r, c.text.g, c.text.b, c.text.a)
            ApplyFont(f.quoteText, c)
        end
    end,
}
