local _, addon = ...
local HLY = addon.HLY

-- New options UI built on LibHLYUI-1.0, reachable via /hlyqol2.
-- Modules register a category by appending to `addon.options`:
--     addon.options[#addon.options + 1] = {
--         name = "French Connection", order = 50, build = "BuildFrenchConnectionOptions",
--     }
-- and defining HLY:<build>(tab) that fills the category via the layout API.
-- Runs alongside the existing AceConfig options until v2 reaches parity.

function HLY:BuildGeneralOptions(tab)
    tab:Section("Minimap")
    tab:Checkbox({
        label = "Show Minimap Button",
        tooltip = "Toggle the HLYqol minimap icon.",
        get = function() return not self.db.minimap.hide end,
        set = function(value)
            self.db.minimap.hide = not value
            self:UpdateMinimapButton()
        end,
    })

end

function HLY:GetOptionsPanel()
    if self.optionsPanel then
        return self.optionsPanel
    end

    local LibHLYUI = LibStub("LibHLYUI-1.0", true)
    if not LibHLYUI then
        return nil
    end

    local panel = LibHLYUI:CreatePanel({
        name   = "HLYqolOptions",
        title  = addon.displayName,
        accent = addon.uiAccent,
        width  = 760,
        height = 560,
    })

    -- Assemble the sidebar. A module registers in addon.options as:
    --   standalone : { name, order, build }
    --   grouped    : { group, groupOrder, name, order, build }            -> header + entries
    --   nested     : { parent, parentOrder, group, groupOrder, name, ... } -> parent header + sub-header + entries
    local function ordOf(x) return x.order or 100 end
    local function byOrder(a, b)
        if ordOf(a) == ordOf(b) then return a.name < b.name end
        return ordOf(a) < ordOf(b)
    end

    -- blocks: top-level items (standalone categories, top-level groups, parents)
    local blocks = {
        { kind = "cat", name = "General", order = 1, build = "BuildGeneralOptions" },
    }
    local groupByName, parentByName = {}, {}

    for _, entry in ipairs(addon.options or {}) do
        if not entry.group then
            blocks[#blocks + 1] = { kind = "cat", name = entry.name, order = ordOf(entry), build = entry.build }
        else
            local g = groupByName[entry.group]
            if not g then
                g = { kind = "group", name = entry.group, order = entry.groupOrder or 100, items = {}, asEntry = entry.groupAsEntry }
                groupByName[entry.group] = g
                if entry.parent then
                    local p = parentByName[entry.parent]
                    if not p then
                        p = { kind = "parent", name = entry.parent, order = entry.parentOrder or 100, groups = {} }
                        parentByName[entry.parent] = p
                        blocks[#blocks + 1] = p
                    end
                    if entry.parentOrder and entry.parentOrder < p.order then p.order = entry.parentOrder end
                    p.groups[#p.groups + 1] = g
                else
                    blocks[#blocks + 1] = g
                end
            end
            if entry.groupOrder and entry.groupOrder < g.order then g.order = entry.groupOrder end
            g.items[#g.items + 1] = entry
        end
    end

    table.sort(blocks, byOrder)

    -- Live previews keyed by sidebar tab index. A module may register
    -- onShow/onHide method names to drive an on-screen preview while its page
    -- is open (e.g. Join Reminder, Tank Marker).
    local previews = {}
    local function registerPreview(item)
        if item.onShow or item.onHide then
            previews[#panel.tabs] = {
                show = item.onShow and function() local m = self[item.onShow] if m then m(self) end end,
                hide = item.onHide and function() local m = self[item.onHide] if m then m(self) end end,
            }
        end
    end

    -- Top-level group: sidebar header + one clickable entry per member. Each
    -- entry's content is wrapped in a single-tab TabGroup so the tab bar shows
    -- consistently (same look as nested single-module groups like Inspect).
    local function renderGroupAsEntries(g)
        panel:AddSidebarHeader(g.name, false)
        table.sort(g.items, byOrder)
        for _, item in ipairs(g.items) do
            local tab = panel:AddTab(item.name)
            local builder = self[item.build]
            if item.ownTabs then
                -- Module builds its own TabGroup; don't double-wrap.
                if builder then builder(self, tab) end
            else
                local method = item.build
                tab:TabGroup({
                    {
                        name = item.name,
                        build = function(pane)
                            local b = self[method]
                            if b then b(self, pane) end
                        end,
                    },
                })
            end
            registerPreview(item)
        end
    end

    -- A group as one clickable entry; members render as content sub-tabs (always
    -- a TabGroup). `headerStyle` makes a top-level consolidated group read like a
    -- section title. Per-member onShow/onHide drive previews on the active sub-tab.
    local function renderGroupAsEntry(g, headerStyle)
        table.sort(g.items, byOrder)
        local tab = panel:AddTab(g.name, false, headerStyle)
        local hasPreview = false
        local defs = {}
        for _, item in ipairs(g.items) do
            local method = item.build
            defs[#defs + 1] = {
                name = item.name,
                build = function(pane)
                    local b = self[method]
                    if b then b(self, pane) end
                end,
                onShow = item.onShow and function() local m = self[item.onShow] if m then m(self) end end,
                onHide = item.onHide and function() local m = self[item.onHide] if m then m(self) end end,
            }
            if item.onShow or item.onHide then hasPreview = true end
        end
        local container = tab:TabGroup(defs)
        if hasPreview and container then
            previews[#panel.tabs] = {
                show = container.showActivePreview,
                hide = container.hideActivePreview,
            }
        end
    end

    for _, block in ipairs(blocks) do
        if block.kind == "cat" then
            local tab = panel:AddTab(block.name)
            local builder = self[block.build]
            if builder then builder(self, tab) end
        elseif block.kind == "group" then
            if block.asEntry then
                renderGroupAsEntry(block, true)
            else
                renderGroupAsEntries(block)
            end
        elseif block.kind == "parent" then
            panel:AddSidebarHeader(block.name, false)
            table.sort(block.groups, byOrder)
            for _, g in ipairs(block.groups) do
                renderGroupAsEntry(g, false)
            end
        end
    end

    -- Hidden categories reached via footer links.
    local changelog = panel:AddTab("Changelog", true)
    local GREEN, RED, WHITE = "|cff40ff40+|r ", "|cffff4040-|r ", "|cffffffff~|r "
    changelog:Section("v2.0.2")
    changelog:Note(table.concat({
        GREEN .. "Neues Modul Fishing: Shift + Doppel-Rechtsklick wirft die Angel aus.",
        GREEN .. "EllesmereUIBags-Unterstützung: Upgrade Track & BoE/WuE in Taschen, Bank und Kriegsmeuten-Bank.",
        WHITE .. "Join Reminder: Vorschau bleibt nicht mehr im Raid/Dungeon hängen, erscheint aber beim Öffnen sofort.",
        WHITE .. "Fishing: kein Fehler mehr im Kampf (geschützte Funktion).",
    }, "\n"))

    changelog:Section("v2.0.1")
    changelog:Note(table.concat({
        WHITE .. "Déjà Vu: „Verlauf löschen\" wirkt jetzt pro Reiter (nur Gruppen bzw. nur Mitspieler).",
        WHITE .. "Join Reminder: Vorschau im Optionsmenü wird zuverlässig ausgeblendet.",
        WHITE .. "French Connection: Bewerber-Name wird beim Aus-/Einschalten des Baguette-Icons korrekt zurückgesetzt.",
    }, "\n"))

    changelog:Section("v2.0.0")
    changelog:Note(table.concat({
        GREEN .. "Komplett neues Optionsmenü auf eigener Bibliothek LibHLYUI: Sidebar-Navigation, flaches Design in der Akzentfarbe.",
        GREEN .. "Live-Vorschauen für Join Reminder, Tank Marker und PvP Gear Check.",
        GREEN .. "Schriftart- und Sound-Vorschau direkt in den Dropdowns.",
        GREEN .. "Statistiken als Balken: Spielzeit pro Klasse (klassenfarben) und Gold.",
        GREEN .. "Déjà Vu (ehem. NotAgain): markiert auch Mitspieler in der Bewerberliste und im Raid-Tab.",
        GREEN .. "French Connection: Demon Hunter Alert (eigener Sound bei DH-Bewerbung).",
        GREEN .. "Bonus Roll: Delve und Open World ergänzt.",
        WHITE .. "Theme folgt einer einzigen Akzentfarbe (addon.uiAccent) — steuert das ganze Menü.",
        WHITE .. "French Connection: Tricolore über die volle Bewerberzeile; Demon Hunter als eigener Reiter.",
        WHITE .. "Optionen neu strukturiert: UI, Group Finder, Alerts, Other + Footer (Changelog | Statistics).",
        WHITE .. "Bonus Roll aus dem Loot-Modul in ein eigenes Modul ausgelagert.",
        WHITE .. "Join Reminder: zeigt bei mehreren gleichzeitigen Annahmen die korrekte Gruppe.",
        RED .. "Altes AceConfig/AceGUI-Optionsmenü entfernt.",
        RED .. "Roter Markierungsbalken links an French-Connection-Bewerberzeilen entfernt.",
    }, "\n"))

    changelog:Section("v1.8.1")
    changelog:Note(table.concat({
        GREEN .. "Déjà Vu: markiert auch Mitspieler, mit denen du in einer Gruppe warst (Bewerberliste + Raid-Tab).",
        WHITE .. "Getrennte Merkdauer und Balkenfarbe für Gruppen und Mitspieler; Optionen in zwei Abschnitte unterteilt.",
    }, "\n"))

    changelog:Section("v1.8.0")
    changelog:Note(table.concat({
        GREEN .. "Déjà Vu: markiert Gruppen, denen du bereits beigetreten bist, im Gruppenfinder.",
        GREEN .. "French Connection: Demon Hunter Alert.",
        WHITE .. "French Connection: Optionen in zwei Abschnitte unterteilt.",
        WHITE .. "Join Reminder: falsche Gruppe bei Raid-Beitritt behoben.",
        RED .. "Roter Markierungsbalken an Bewerberzeilen entfernt.",
    }, "\n"))

    local changelogIndex = #panel.tabs

    local statistics = panel:AddTab("Statistics", true)
    self:BuildStatisticsOptions(statistics)
    local statisticsIndex = #panel.tabs

    panel:SetFooterRight("v" .. (addon.version or "?"))
    panel:AddFooterLink("Changelog", function(p) p:SelectTab(changelogIndex) end)
    panel:AddFooterLink("Statistics", function(p) p:SelectTab(statisticsIndex) end)

    -- Defensive: hide every module preview (called on open/close/switch so a
    -- preview never lingers regardless of how the active path changed).
    local function hideAllPreviews()
        if self.HideJoinReminderPreview then self:HideJoinReminderPreview() end
        if self.HideMarkerReminderPreview then self:HideMarkerReminderPreview() end
        if self.HideGearCheckPreview then self:HideGearCheckPreview() end
    end

    -- Drive live previews on tab switch + hide on close.
    local activePreview
    local function setPreview(index)
        local p = previews[index]
        if p == activePreview then return end
        if activePreview and activePreview.hide then activePreview.hide() end
        activePreview = p
        hideAllPreviews()
        if activePreview and activePreview.show then activePreview.show() end
    end
    panel.onTabChanged = function(index) setPreview(index) end
    panel.frame:HookScript("OnShow", function()
        hideAllPreviews()
        activePreview = nil
        setPreview(panel.activeTab)
    end)
    panel.frame:HookScript("OnHide", function()
        if activePreview and activePreview.hide then activePreview.hide() end
        activePreview = nil
        hideAllPreviews()
    end)

    hideAllPreviews()
    self.optionsPanel = panel
    return panel
end

function HLY:OpenOptions()
    local panel = self:GetOptionsPanel()
    if panel then
        panel:Toggle()
    else
        print(addon.displayName .. ": LibHLYUI-1.0 not loaded.")
    end
end
