local addonName, ns = ...

local LibEditModeDrawer = LibStub("LibEditModeDrawer", true)
if not LibEditModeDrawer then return end

local CYAN = { r = 0, g = 207/255, b = 1.0 }

local settingsDrawer, unlockDrawer
local hooked = false

-- ── Helpers ───────────────────────────────────────────────────────────────

local function GetClassColorHex()
    local _, classFile = UnitClass("player")
    local c = classFile and RAID_CLASS_COLORS and RAID_CLASS_COLORS[classFile]
    if c then
        return string.format("|cff%02x%02x%02x", c.r * 255, c.g * 255, c.b * 255)
    end
    return "|cffffa300"  -- fallback orange
end

local function MakeLabel()
    local cc = GetClassColorHex()
    return "|cff00cfffBright|r" .. cc .. "QoL|r"
end

local function AreAllUnlocked()
    local registry = ns.MODULE_REGISTRY
    if not registry then return false end
    for _, entry in ipairs(registry) do
        if #entry.unlockKeys > 0 then
            local modDb = BrightQoL[entry.db]
            if modDb then
                for _, key in ipairs(entry.unlockKeys) do
                    if not modDb[key] then return false end
                end
            end
        end
    end
    return true
end

local function GetUnlockableEntries()
    local entries = {}
    local registry = ns.MODULE_REGISTRY
    local displayNames = ns.MODULE_DISPLAY_NAMES
    if not registry then return entries end
    local seen = {}
    for _, entry in ipairs(registry) do
        if #entry.unlockKeys > 0 and not seen[entry.db] then
            seen[entry.db] = true
            entries[#entries + 1] = displayNames and displayNames[entry.db] or entry.db
        end
    end
    return entries
end

local function SetAllUnlocks(state)
    local registry = ns.MODULE_REGISTRY
    if not registry then return end
    for _, entry in ipairs(registry) do
        local modDb = BrightQoL[entry.db]
        if modDb then
            for _, key in ipairs(entry.unlockKeys) do
                modDb[key] = state
            end
        end
    end
    if ns.RefreshAllModuleDisplays then ns.RefreshAllModuleDisplays() end
    -- Toggle DisableEditModeSnap for unlock state (guard — may not exist)
    if not state and ns.DisplayUtils and ns.DisplayUtils.DisableEditModeSnap then
        ns.DisplayUtils.DisableEditModeSnap()
    end
    -- Toggle ReportCard preview
    if ns.BWV2ReportCard then
        if state then
            pcall(ns.BWV2ReportCard.ApplySettings, ns.BWV2ReportCard)
            pcall(ns.BWV2ReportCard.ShowPreview,   ns.BWV2ReportCard)
        else
            pcall(ns.BWV2ReportCard.Hide,          ns.BWV2ReportCard)
        end
    end
    -- Toggle BuffDropAlert preview
    if ns.BWV2BuffDropAlert then
        if state then
            pcall(ns.BWV2BuffDropAlert.ShowPreview, ns.BWV2BuffDropAlert)
        else
            pcall(ns.BWV2BuffDropAlert.HidePreview, ns.BWV2BuffDropAlert)
        end
    end
end

-- ── BrightQoL styling ─────────────────────────────────────────────────────

local function StyleDrawer(drawer, subtitleText)
    if not drawer or not drawer.frame then return end
    local frame = drawer.frame

    frame:SetBackdropColor(0.05, 0.05, 0.05, 0.92)
    frame:SetBackdropBorderColor(CYAN.r, CYAN.g, CYAN.b, 1)

    -- Update label with class color at runtime
    local lbl = drawer.checkbox and drawer.checkbox.Label
    if lbl then
        lbl:SetText(MakeLabel() .. "\n" .. (subtitleText or ""))
        lbl:SetTextColor(1, 1, 1, 1)
    end

    -- Cyan fill when checked
    drawer.UpdateCheckboxVisual = function(self)
        if self.checkbox:GetChecked() then
            self.checkbox.Fill:SetVertexColor(CYAN.r, CYAN.g, CYAN.b, 1)
        else
            self.checkbox.Fill:SetVertexColor(0, 0, 0, 1)
        end
    end
    drawer:UpdateCheckboxVisual()
end

-- ── Right-click on unlocked frame → open config tab ───────────────────────

local function OpenModuleTab(tabKey)
    if not ns.MainFrame then return end
    if not ns.MainFrame:IsShown() then
        SlashCmdList["BRIGHTQOL"]()
    end
    C_Timer.After(0.05, function()
        if ns.OpenTab then ns:OpenTab(tabKey) end
    end)
end

local rightClickRegistered = {}

local function RegisterRightClickOnFrame(frame, tabKey, dbKey, unlockKeys)
    if not frame or not tabKey or not frame.EnableMouse then return end
    if rightClickRegistered[frame] then return end
    rightClickRegistered[frame] = true

    -- Frames use RegisterForDrag (not buttons) so use SetScript OnMouseDown
    local prevScript = frame:GetScript("OnMouseDown")
    frame:SetScript("OnMouseDown", function(self, btn)
        if btn == "RightButton" then
            local modDb = BrightQoL[dbKey]
            local isUnlocked = false
            if modDb then
                for _, key in ipairs(unlockKeys) do
                    if modDb[key] then isUnlocked = true; break end
                end
            end
            if isUnlocked then
                OpenModuleTab(tabKey)
            end
        elseif prevScript then
            prevScript(self, btn)
        end
    end)
end

local function HookAllFrames()
    local registry = ns.MODULE_REGISTRY
    if not registry then return end
    for _, entry in ipairs(registry) do
        if entry.frameKey and entry.tab and #entry.unlockKeys > 0 then
            local obj = ns[entry.frameKey]
            if obj then
                -- Try the object directly (most display frames ARE the WoW frame)
                local frame = obj.EnableMouse and obj
                           or (obj.frame and obj.frame.EnableMouse and obj.frame)
                           or nil
                if frame then
                    RegisterRightClickOnFrame(frame, entry.tab, entry.db, entry.unlockKeys)
                end
            end
        end
    end
end

-- ── Edit Mode hooks ────────────────────────────────────────────────────────

local function OnEnterEditMode()
    if settingsDrawer then settingsDrawer:EnterEditMode() end
    if unlockDrawer   then unlockDrawer:EnterEditMode()   end
end

local function OnExitEditMode()
    if settingsDrawer then settingsDrawer:ExitEditMode() end
    if unlockDrawer   then unlockDrawer:ExitEditMode()   end
end

local function InitDrawers()
    local baseLabel = "|cff00cfffBright|rQoL"  -- placeholder, updated after login

    settingsDrawer = LibEditModeDrawer:CreateDrawer({
        id         = "BrightQoLSettings",
        label      = baseLabel .. "\nSettings",
        getEntries = function() return { "Settings Panel" } end,
        getValue   = function() return ns.MainFrame and ns.MainFrame:IsShown() end,
        setValue   = function(checked)
            if not ns.MainFrame then return end
            if checked and not ns.MainFrame:IsShown() then
                SlashCmdList["BRIGHTQOL"]()
            elseif not checked and ns.MainFrame:IsShown() then
                ns.MainFrame:Hide()
            end
        end,
        tooltipHeader              = "BrightQoL Settings",
        tooltipDescriptionTemplate = "Open the %s configuration panel.\n\n%s",
        tooltipProductName         = "BrightQoL",
    })

    unlockDrawer = LibEditModeDrawer:CreateDrawer({
        id         = "BrightQoLUnlock",
        label      = baseLabel .. "\nUnlock All",
        getEntries = GetUnlockableEntries,
        getValue   = AreAllUnlocked,
        setValue   = function(checked) SetAllUnlocks(checked) end,
        tooltipHeader              = "BrightQoL Unlock / Lock All",
        tooltipDescriptionTemplate = "Toggle all %s movable frames:\n\n%s",
        tooltipProductName         = "BrightQoL",
    })

    -- Apply styling after a tick (frames must be built) and after PLAYER_LOGIN
    -- so RAID_CLASS_COLORS is populated
    C_Timer.After(0.1, function()
        StyleDrawer(settingsDrawer, "Settings")
        StyleDrawer(unlockDrawer,   "Unlock All")
    end)
end

local function TryHook()
    if hooked then return true end
    if not EditModeManagerFrame then return false end
    if not EditModeManagerFrame.EnterEditMode then return false end
    hooksecurefunc(EditModeManagerFrame, "EnterEditMode", OnEnterEditMode)
    hooksecurefunc(EditModeManagerFrame, "ExitEditMode",  OnExitEditMode)
    hooked = true
    return true
end

-- ── Loader ─────────────────────────────────────────────────────────────────

local loader = CreateFrame("Frame")
loader:RegisterEvent("PLAYER_LOGIN")
loader:RegisterEvent("ADDON_LOADED")
loader:SetScript("OnEvent", function(self, event)
    if event == "PLAYER_LOGIN" then
        InitDrawers()
        TryHook()
        -- Hook right-click after everything is initialised
        C_Timer.After(1.0, HookAllFrames)
        -- Re-apply label with class color (available after PLAYER_LOGIN)
        C_Timer.After(0.2, function()
            StyleDrawer(settingsDrawer, "Settings")
            StyleDrawer(unlockDrawer,   "Unlock All")
        end)
        if hooked then self:UnregisterAllEvents() end
    elseif event == "ADDON_LOADED" then
        if settingsDrawer and TryHook() then
            self:UnregisterAllEvents()
        end
    end
end)
