-- NP_CastbarTest/colorpicker.lua  (works for pom/ca/colorpicker.lua too)
-- =========================================================
-- Simple Color Picker Utility (12.0 safe)
-- Provides:
--   ns.Util.ColorPicker.CreateRow(parent, opts)
--
-- opts = {
--   label      = "Text",
--   point      = "TOPLEFT",
--   rel        = "TOPLEFT",
--   x, y       = numbers,
--   color      = table {r,g,b,a},
--   hasOpacity = true/false,
--   onChanged  = function(colorTable) end,
-- }
-- =========================================================

local ADDON, ns = ...
ns.Util = ns.Util or {}
ns.Util.ColorPicker = ns.Util.ColorPicker or {}
local CP = ns.Util.ColorPicker

local function Clamp01(v)
    v = tonumber(v) or 0
    if v < 0 then return 0 end
    if v > 1 then return 1 end
    return v
end

local function EnsureColorTable(t)
    if type(t) ~= "table" then t = {} end
    t.r = Clamp01(t.r or 1)
    t.g = Clamp01(t.g or 1)
    t.b = Clamp01(t.b or 1)
    t.a = Clamp01(t.a or 1)
    return t
end

local function SetSwatchVisual(btn, c)
    if not btn then return end
    c = EnsureColorTable(c)
    if btn.swatchTex then
        btn.swatchTex:SetColorTexture(c.r, c.g, c.b, 1)
    end
    if btn.alphaTex then
        -- show alpha as a subtle overlay darkness
        btn.alphaTex:SetColorTexture(0, 0, 0, Clamp01(1 - c.a) * 0.55)
    end
end

-- =========================================================
-- OPEN PICKER (12.0 safe)
--   - Prefer SetupColorPickerAndShow (modern API)
--   - Fallback to legacy fields if needed
--   - NEVER assume SetColorRGB exists (your crash)
-- =========================================================
local function OpenPicker(opts)
    local color = EnsureColorTable(opts.color)
    local hasOpacity = opts.hasOpacity and true or false
    local onChanged = opts.onChanged
    local swatchBtn = opts.swatchBtn

    local CPF = _G.ColorPickerFrame
    if not CPF then return end

    -- Save old to support cancel
    local prev = { r=color.r, g=color.g, b=color.b, a=color.a }

    local function ApplyColor(r, g, b, a)
        color.r, color.g, color.b, color.a = Clamp01(r), Clamp01(g), Clamp01(b), Clamp01(a)
        SetSwatchVisual(swatchBtn, color)
        if type(onChanged) == "function" then
            pcall(onChanged, color)
        end
    end

    local function ReadAlphaFromOpacitySlider()
        if not hasOpacity then
            return color.a
        end
        local slider = _G.OpacitySliderFrame or (CPF.Content and CPF.Content.OpacitySliderFrame)
        if slider and slider.GetValue then
            return 1 - Clamp01(slider:GetValue())
        end
        return color.a
    end

    local function OnColorChanged()
        local r, g, b = CPF:GetColorRGB()
        ApplyColor(r, g, b, ReadAlphaFromOpacitySlider())
    end

    local function OnOpacityChanged()
        local r, g, b = CPF:GetColorRGB()
        ApplyColor(r, g, b, ReadAlphaFromOpacitySlider())
    end

    local function OnCancel()
        ApplyColor(prev.r, prev.g, prev.b, prev.a)
    end

    -- ✅ MODERN (12.0+) API — this avoids SetColorRGB being missing
    if CPF.SetupColorPickerAndShow then
        local info = {
            r = color.r,
            g = color.g,
            b = color.b,

            hasOpacity = hasOpacity,
            opacity = 1 - Clamp01(color.a), -- Blizzard uses opacity: 0=opaque,1=transparent

            swatchFunc  = OnColorChanged,
            opacityFunc = hasOpacity and OnOpacityChanged or nil,
            cancelFunc  = OnCancel,
        }
        CPF:SetupColorPickerAndShow(info)
        return
    end

    -- Fallback (older clients)
    CPF.func = OnColorChanged
    CPF.opacityFunc = hasOpacity and OnOpacityChanged or nil
    CPF.cancelFunc = OnCancel
    CPF.hasOpacity = hasOpacity

    -- Init current (SetColorRGB can be missing → pcall or skip)
    if CPF.SetColorRGB then
        pcall(CPF.SetColorRGB, CPF, color.r, color.g, color.b)
    elseif CPF.Content and CPF.Content.ColorPicker and CPF.Content.ColorPicker.SetColorRGB then
        pcall(CPF.Content.ColorPicker.SetColorRGB, CPF.Content.ColorPicker, color.r, color.g, color.b)
    end

    local slider = _G.OpacitySliderFrame or (CPF.Content and CPF.Content.OpacitySliderFrame)
    if hasOpacity and slider and slider.SetValue then
        pcall(slider.SetValue, slider, 1 - Clamp01(color.a))
        if slider.Show then slider:Show() end
    elseif slider and slider.Hide then
        slider:Hide()
    end

    if CPF.Show then CPF:Show() end
end

-- =========================================================
-- PUBLIC: CreateRow
-- =========================================================
function CP.CreateRow(parent, opts)
    if not parent then return end
    opts = opts or {}

    local label = tostring(opts.label or "Color")
    local x = tonumber(opts.x) or 0
    local y = tonumber(opts.y) or 0
    local point = opts.point or "TOPLEFT"
    local rel = opts.rel or "TOPLEFT"

    local color = EnsureColorTable(opts.color)
    local hasOpacity = opts.hasOpacity and true or false
    local onChanged = opts.onChanged

    local row = CreateFrame("Frame", nil, parent)
    row:SetSize(420, 22)
    row:SetPoint(point, parent, rel, x, y)

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

    local swatch = CreateFrame("Button", nil, row)
    swatch:SetSize(40, 16)
    swatch:SetPoint("LEFT", fs, "RIGHT", 12, 0)

    swatch.bg = swatch:CreateTexture(nil, "BACKGROUND")
    swatch.bg:SetAllPoints()
    swatch.bg:SetColorTexture(0.08, 0.08, 0.08, 1)

    swatch.swatchTex = swatch:CreateTexture(nil, "ARTWORK")
    swatch.swatchTex:SetPoint("TOPLEFT", 1, -1)
    swatch.swatchTex:SetPoint("BOTTOMRIGHT", -1, 1)

    swatch.alphaTex = swatch:CreateTexture(nil, "OVERLAY")
    swatch.alphaTex:SetAllPoints(swatch.swatchTex)

    SetSwatchVisual(swatch, color)

    local alphaText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    alphaText:SetPoint("LEFT", swatch, "RIGHT", 10, 0)

    local function UpdateAlphaText()
        if hasOpacity then
            alphaText:SetText(string.format("A: %.2f", color.a or 1))
        else
            alphaText:SetText("")
        end
    end
    UpdateAlphaText()

    swatch:SetScript("OnClick", function()
        OpenPicker({
            color = color,
            hasOpacity = hasOpacity,
            onChanged = function(c)
                SetSwatchVisual(swatch, c)
                UpdateAlphaText()
                if type(onChanged) == "function" then
                    pcall(onChanged, c)
                end
            end,
            swatchBtn = swatch,
        })
    end)

    -- expose for external updates
    row._color = color
    row.Refresh = function()
        SetSwatchVisual(swatch, color)
        UpdateAlphaText()
    end

    return row
end
