local ADDON_NAME, ns = ...

-- unify namespace table (avoids split ns tables)
ns = _G[ADDON_NAME] or ns
_G[ADDON_NAME] = ns

-- Backwards compatible exports:
-- old code expects ns.BaseColorsUI:ToggleFrame()
-- new code can use ns.basecolors_ui:Toggle()
ns.BaseColorsUI   = ns.BaseColorsUI or {}
ns.basecolors_ui  = ns.basecolors_ui or ns.BaseColorsUI

local UI = ns.BaseColorsUI

-- =============================================================
-- pom_base_colors_ui.lua
-- Base colors settings (NOT threat) in its own window
-- Backwards compatible API: ToggleFrame()
-- Modern color picker: SetupColorPickerAndShow()
--
-- RULE:
--   UI must be READ-ONLY except when user clicks (pick/reset).
--   Defaults + migrations are owned by InitDB() in pom.lua.
-- =============================================================

local DEFAULTS = {
    normal    = { r=0.8, g=0.8, b=0.8, a=1 },
    plusOne   = { r=1.0, g=0.5, b=0.0, a=1 },
    highlevel = { r=0.8, g=0.0, b=1.0, a=1 },
    caster    = { r=1.0, g=0.4, b=0.8, a=1 },
    melee     = { r=0.0, g=0.6, b=1.0, a=1 },
    neutral   = { r=1.0, g=0.82, b=0.0, a=1 },
}

local ORDER = {
    { key="normal",    label="Normal" },
    { key="highlevel", label="Highlevel (+2)" },
    { key="plusOne",   label="Player +1" },
    { key="caster",    label="Elite Caster" },
    { key="melee",     label="Elite Melee" },
    { key="neutral",   label="Neutral (Reaction=4 lock)" },
}

-- -------------------------------------------------------------
-- DB helpers
-- -------------------------------------------------------------
local function GetDB()
    if not PlateOMaticDB then return nil end
    if type(PlateOMaticDB.baseColors) ~= "table" then return nil end
    return PlateOMaticDB.baseColors
end

local function ClampColor(c, fallback)
    fallback = fallback or { r=1, g=1, b=1, a=1 }
    if type(c) ~= "table" then c = fallback end
    return {
        r = tonumber(c.r) or fallback.r or 1,
        g = tonumber(c.g) or fallback.g or 1,
        b = tonumber(c.b) or fallback.b or 1,
        a = tonumber(c.a) or fallback.a or 1,
    }
end

-- Write helper: create key ONLY when user actually edits
local function GetOrCreateColor(key)
    if not PlateOMaticDB then return nil end
    PlateOMaticDB.baseColors = PlateOMaticDB.baseColors or {}
    local bdb = PlateOMaticDB.baseColors
    if type(bdb[key]) ~= "table" then
        local d = DEFAULTS[key] or { r=1, g=1, b=1, a=1 }
        bdb[key] = { r=d.r, g=d.g, b=d.b, a=d.a }
    end
    return bdb[key]
end

local function ApplyAll(applyAll)
    if applyAll then applyAll() end
end

local function MakeTitle(parent, text)
    local t = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
    t:SetPoint("TOPLEFT", 12, -10)
    t:SetText(text)
    return t
end

local function MakeColorRow(parent, label, key, y, applyAll)
    local row = CreateFrame("Frame", nil, parent)
    row:SetSize(360, 22)
    row:SetPoint("TOPLEFT", 12, y)

    local txt = row:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    txt:SetPoint("LEFT")
    txt:SetText(label)

    local btn = CreateFrame("Button", nil, row)
    btn:SetSize(18, 18)
    btn:SetPoint("RIGHT", -12, 0)

    local bg = btn:CreateTexture(nil, "BACKGROUND")
    bg:SetAllPoints()
    bg:SetColorTexture(0.15, 0.15, 0.15, 1)

    local sw = btn:CreateTexture(nil, "OVERLAY")
    sw:SetPoint("TOPLEFT", 1, -1)
    sw:SetPoint("BOTTOMRIGHT", -1, 1)

    local function getC_ReadOnly()
        local bdb = GetDB()
        local d = DEFAULTS[key] or { r=1, g=1, b=1, a=1 }
        local c = (bdb and bdb[key]) or d
        return ClampColor(c, d)
    end

    local function refresh()
        local c = getC_ReadOnly()
        sw:SetColorTexture(c.r, c.g, c.b, c.a or 1)
    end
    refresh()

    btn:SetScript("OnClick", function()
        local c0 = getC_ReadOnly()

        ColorPickerFrame:SetupColorPickerAndShow({
            r = c0.r, g = c0.g, b = c0.b,
            opacity = 1 - (c0.a or 1),
            hasOpacity = true,

            swatchFunc = function()
                local r, g, b = ColorPickerFrame:GetColorRGB()
                local a = 1 - (ColorPickerFrame:GetColorAlpha() or 0)

                local c = GetOrCreateColor(key)
                if c then
                    c.r, c.g, c.b, c.a = r, g, b, a
                end

                refresh()
                ApplyAll(applyAll)
            end,

            opacityFunc = function()
                local r, g, b = ColorPickerFrame:GetColorRGB()
                local a = 1 - (ColorPickerFrame:GetColorAlpha() or 0)

                local c = GetOrCreateColor(key)
                if c then
                    c.r, c.g, c.b, c.a = r, g, b, a
                end

                refresh()
                ApplyAll(applyAll)
            end,

            cancelFunc = function(prev)
                if prev then
                    local a = 1 - (prev.opacity or 0)
                    local c = GetOrCreateColor(key)
                    if c then
                        c.r, c.g, c.b, c.a = prev.r, prev.g, prev.b, a
                    end
                end
                refresh()
                ApplyAll(applyAll)
            end,
        })
    end)

    return refresh
end

function UI:BuildFrame(applyAll)
    local f = CreateFrame("Frame", "POM_BaseColorsFrame", UIParent, "BasicFrameTemplateWithInset")
    f:SetSize(420, 320)
    f:SetPoint("CENTER")
    f:SetFrameStrata("DIALOG")
    f:SetMovable(true)
    f:EnableMouse(true)
    f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", f.StopMovingOrSizing)
    if f.TitleText then f.TitleText:SetText("POM - Base Colors") end

    MakeTitle(f, "Base Colors")

    f._refreshers = {}
    local y = -50
    for _, it in ipairs(ORDER) do
        local ref = MakeColorRow(f, it.label, it.key, y, applyAll)
        f._refreshers[#f._refreshers+1] = ref
        y = y - 26
    end

    local reset = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    reset:SetSize(180, 22)
    reset:SetPoint("BOTTOMLEFT", 12, 10)
    reset:SetText("Reset Defaults")
    reset:SetScript("OnClick", function()
        if not PlateOMaticDB then return end
        PlateOMaticDB.baseColors = PlateOMaticDB.baseColors or {}
        local bdb = PlateOMaticDB.baseColors

        for k, v in pairs(DEFAULTS) do
            bdb[k] = bdb[k] or {}
            bdb[k].r, bdb[k].g, bdb[k].b, bdb[k].a = v.r, v.g, v.b, v.a
        end

        if f._refreshers then
            for _, fn in ipairs(f._refreshers) do
                if fn then fn() end
            end
        end

        ApplyAll(applyAll)
    end)

    local close = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    close:SetSize(120, 22)
    close:SetPoint("BOTTOMRIGHT", -12, 10)
    close:SetText("Close")
    close:SetScript("OnClick", function() f:Hide() end)

    return f
end

-- New API
function UI:Toggle(applyAll)
    if self._frame and self._frame:IsShown() then
        self._frame:Hide()
        return
    end
    if not self._frame then
        -- NO EnsureDB() here. InitDB owns defaults+migrations.
        self._frame = self:BuildFrame(applyAll)
    end
    self._frame:Show()
end

-- Old API (compat)
function UI:ToggleFrame(applyAll)
    self:Toggle(applyAll)
end

-- also expose through ns.basecolors_ui
ns.basecolors_ui = UI
