local addonName, ZL = ...

local CATEGORY_SETTINGS = {
    { key = "achievements", label = "Achievements" },
    { key = "pets", label = "Battle Pets" },
    { key = "decor", label = "Decor" },
    { key = "instances", label = "Instances" },
    { key = "mounts", label = "Mounts" },
    { key = "quests", label = "Quests" },
    { key = "rares", label = "Rare Drops" },
    { key = "transmogs", label = "Transmog" },
}

local HISTORY_SETTINGS = {
    { key = "zones", label = "Zone Completions", description = "Record when a zone reaches 100%." },
    { key = "journeys", label = "Journey Milestones", description = "Record completed continent journey legs." },
    { key = "achievements", label = "Achievements", description = "Record newly earned tracked achievements." },
    { key = "quests", label = "Quests", description = "Record quest turn-ins in the active route zone." },
    { key = "mounts", label = "Mounts", description = "Record newly collected tracked mounts." },
    { key = "pets", label = "Battle Pets", description = "Record newly collected tracked battle pets." },
    { key = "decor", label = "Decor", description = "Record newly obtained tracked Decor." },
    { key = "rares", label = "Rare Drops", description = "Record newly obtained tracked rare drops." },
    { key = "transmogs", label = "Transmog", description = "Record newly collected appearances." },
}

function ZL:SetCategoryEnabled(key, enabled)
    local oldActive = self:GetActiveZone()
    ZL_Saved.settings.categories[key] = enabled and true or false
    local newActive = self:GetActiveZone()
    if oldActive and newActive and oldActive ~= newActive then
        ZL_Saved.transition = { from = oldActive, to = newActive }
    end
    self._uiSignature = nil
    self:CheckZoneState()
    self:RefreshUI()
end

local function CreateCheck(panel, label, description, x, y, getter, setter, descriptionWidth)
    local check = CreateFrame("CheckButton", nil, panel, "UICheckButtonTemplate")
    -- SettingsCheckBoxTemplate expects Blizzard's data-binding system and can
    -- suppress its tick for manually-managed controls. Use the ordinary
    -- checkbox template and an explicit checked texture instead.
    check:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check")
    check.mark = check:CreateTexture(nil, "OVERLAY")
    check.mark:SetTexture(130751) -- Interface/Buttons/UI-CheckBox-Check
    check.mark:SetAllPoints(check)
    check:SetPoint("TOPLEFT", x, y)
    check:SetSize(24, 24)
    check.label = check:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    check.label:SetPoint("LEFT", check, "RIGHT", 7, 2)
    check.label:SetText(label)
    check.description = check:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    check.description:SetPoint("TOPLEFT", check.label, "BOTTOMLEFT", 0, -3)
    check.description:SetWidth(descriptionWidth or 520)
    check.description:SetJustifyH("LEFT")
    check.description:SetText(description)
    check.description:SetTextColor(0.65, 0.69, 0.73)
    check:SetHitRectInsets(0, -math.max(160, check.label:GetStringWidth() + 12), -8, -20)
    check:SetScript("OnClick", function(button)
        local checked = button:GetChecked() and true or false
        button.mark:SetShown(checked)
        setter(checked)
    end)
    check.RefreshValue = function()
        local checked = getter() and true or false
        check:SetChecked(checked)
        check.mark:SetShown(checked)
    end
    panel.controls[#panel.controls + 1] = check
    check.RefreshValue()
    return check
end

function ZL:CreateSettingsPanel()
    if not Settings or not Settings.RegisterCanvasLayoutCategory then return end

    local panel = CreateFrame("Frame", "ZoneLockedSettingsPanel")
    panel:SetSize(760, 640)
    panel.name = "Zone Locked"
    panel.controls = {}

    local title = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlightHuge")
    title:SetPoint("TOPLEFT", 24, -24)
    title:SetText("Zone Locked")
    local subtitle = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
    subtitle:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8)
    subtitle:SetWidth(620)
    subtitle:SetJustifyH("LEFT")
    subtitle:SetText("Configure challenge rules and choose which collections count toward completing a zone.")
    local divider = panel:CreateTexture(nil, "ARTWORK")
    divider:SetAtlas("Options_HorizontalDivider", true)
    divider:SetPoint("TOPLEFT", subtitle, "BOTTOMLEFT", -8, -14)

    local attNotice = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    attNotice:SetPoint("TOPLEFT", 24, -84)
    attNotice:SetWidth(680)
    attNotice:SetJustifyH("LEFT")
    attNotice:SetText("|cffffcc00All The Things (ATT) must be installed and enabled for complete, accurate zone data.|r The built-in catalog is only a limited fallback.")

    local general = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    general:SetPoint("TOPLEFT", 24, -126)
    general:SetText("Challenge Interface")

    CreateCheck(panel, "Locked-Zone Blackout", "Darken zones which have not been unlocked yet.", 28, -159,
        function() return ZL_Saved.settings.blackout end,
        function(value) ZL_Saved.settings.blackout = value; self:CheckZoneState() end, 250)
    CreateCheck(panel, "Collection Alerts", "Show a Blizzard-style alert when a tracked collectible is obtained.", 28, -216,
        function() return ZL_Saved.settings.alerts end,
        function(value) ZL_Saved.settings.alerts = value end, 250)
    CreateCheck(panel, "Persistent Mini-List", "Keep the compact active-zone progress window visible.", 350, -159,
        function() return ZL_Saved.settings.minilist.enabled end,
        function(value) ZL_Saved.settings.minilist.enabled = value; self:RefreshMiniList() end, 250)
    CreateCheck(panel, "Show Next Missing Objectives", "Show individual missing objectives beneath category progress.", 350, -216,
        function() return ZL_Saved.settings.minilist.showMissing end,
        function(value) ZL_Saved.settings.minilist.showMissing = value; self:RefreshMiniList() end, 250)
    CreateCheck(panel, "World Map Overlay", "Colour locked, active, and completed route zones on the world map.", 28, -273,
        function() return ZL_Saved.settings.mapOverlay end,
        function(value) ZL_Saved.settings.mapOverlay = value; self:RefreshWorldMapOverlay() end, 270)

    local completion = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    completion:SetPoint("TOPLEFT", 24, -340)
    completion:SetText("Counts Toward 100% Completion")
    local completionHint = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    completionHint:SetPoint("TOPLEFT", completion, "BOTTOMLEFT", 0, -5)
    completionHint:SetText("Excluded categories remain visible, but do not block the next zone roll.")
    completionHint:SetTextColor(0.65, 0.69, 0.73)

    local testAlert = CreateFrame("Button", nil, panel, "UIPanelButtonTemplate")
    testAlert:SetSize(112, 24)
    testAlert:SetPoint("TOPLEFT", 380, -273)
    testAlert:SetText("Test Alert")
    testAlert:SetScript("OnClick", function()
        self:ShowCollectionAlert("Zone Locked test alert", nil, 236621, true)
    end)

    for index, descriptor in ipairs(CATEGORY_SETTINGS) do
        local categoryKey = descriptor.key
        local categoryLabel = descriptor.label
        local column = (index - 1) % 2
        local row = math.floor((index - 1) / 2)
        CreateCheck(panel, categoryLabel, "Include " .. categoryLabel:lower() .. " in zone progress.",
            28 + (column * 310), -392 - (row * 58),
            function() return self:IsCategoryEnabled(categoryKey) end,
            function(value) self:SetCategoryEnabled(categoryKey, value) end, 250)
    end

    panel:SetScript("OnShow", function()
        for _, control in ipairs(panel.controls) do control.RefreshValue() end
    end)

    local category = Settings.RegisterCanvasLayoutCategory(panel, "Zone Locked")
    Settings.RegisterAddOnCategory(category)

    local expansionPanel = CreateFrame("Frame", "ZoneLockedExpansionSettingsPanel")
    expansionPanel:SetSize(760, 520)
    expansionPanel.name = "Expansions"
    expansionPanel.controls = {}
    local expansionTitle = expansionPanel:CreateFontString(nil, "ARTWORK", "GameFontHighlightHuge")
    expansionTitle:SetPoint("TOPLEFT", 24, -24)
    expansionTitle:SetText("Expansion Packs")
    local expansionHint = expansionPanel:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
    expansionHint:SetPoint("TOPLEFT", expansionTitle, "BOTTOMLEFT", 0, -8)
    expansionHint:SetWidth(680)
    expansionHint:SetJustifyH("LEFT")
    expansionHint:SetText("Choose which expansions participate in the Zone Locked challenge.")
    local function AddExpansionCheck(expansion, index)
        local expansionKey, expansionName = expansion.key, expansion.name
        local column = (index - 1) % 2
        local row = math.floor((index - 1) / 2)
        CreateCheck(expansionPanel, expansionName, "Enable zones, dungeons, and raids from this expansion.",
            28 + (column * 350), -102 - (row * 60),
            function() return self:IsExpansionEnabled(expansionKey) end,
            function(value) self:SetExpansionEnabled(expansionKey, value) end, 245)
    end
    for index, expansion in ipairs(self.Expansions or {}) do AddExpansionCheck(expansion, index) end
    expansionPanel:SetScript("OnShow", function()
        for _, control in ipairs(expansionPanel.controls) do control.RefreshValue() end
    end)
    local expansionCategory = Settings.RegisterCanvasLayoutSubcategory(category, expansionPanel, "Expansions")

    local historyPanel = CreateFrame("Frame", "ZoneLockedHistorySettingsPanel")
    historyPanel:SetSize(760, 580)
    historyPanel.name = "History"
    historyPanel.controls = {}
    local historyTitle = historyPanel:CreateFontString(nil, "ARTWORK", "GameFontHighlightHuge")
    historyTitle:SetPoint("TOPLEFT", 24, -24)
    historyTitle:SetText("History Tracking")
    local historyHint = historyPanel:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
    historyHint:SetPoint("TOPLEFT", historyTitle, "BOTTOMLEFT", 0, -8)
    historyHint:SetWidth(680)
    historyHint:SetJustifyH("LEFT")
    historyHint:SetText("Choose which events are recorded in this character's completion history.")

    CreateCheck(historyPanel, "Enable History Tracking",
        "Master switch for new history entries. Existing history is retained.", 28, -92,
        function() return ZL_Saved.settings.history.enabled end,
        function(value) ZL_Saved.settings.history.enabled = value end, 580)

    local categoryTitle = historyPanel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    categoryTitle:SetPoint("TOPLEFT", 24, -154)
    categoryTitle:SetText("Tracked Events")
    for index, descriptor in ipairs(HISTORY_SETTINGS) do
        local historyKey = descriptor.key
        local column = (index - 1) % 2
        local row = math.floor((index - 1) / 2)
        CreateCheck(historyPanel, descriptor.label, descriptor.description,
            28 + (column * 350), -190 - (row * 66),
            function() return ZL_Saved.settings.history.categories[historyKey] ~= false end,
            function(value) ZL_Saved.settings.history.categories[historyKey] = value end, 285)
    end
    historyPanel:SetScript("OnShow", function()
        for _, control in ipairs(historyPanel.controls) do control.RefreshValue() end
    end)
    local historyCategory = Settings.RegisterCanvasLayoutSubcategory(category, historyPanel, "History")

    local miniListPanel = CreateFrame("Frame", "ZoneLockedMiniListSettingsPanel")
    miniListPanel:SetSize(760, 580)
    miniListPanel.name = "Mini-List"
    miniListPanel.controls = {}
    local miniListTitle = miniListPanel:CreateFontString(nil, "ARTWORK", "GameFontHighlightHuge")
    miniListTitle:SetPoint("TOPLEFT", 24, -24)
    miniListTitle:SetText("Mini-List")
    local miniListHint = miniListPanel:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
    miniListHint:SetPoint("TOPLEFT", miniListTitle, "BOTTOMLEFT", 0, -8)
    miniListHint:SetWidth(680)
    miniListHint:SetJustifyH("LEFT")
    miniListHint:SetText("Choose what appears in the persistent zone-progress window.")
    CreateCheck(miniListPanel, "Persistent Mini-List", "Show the Mini-List whenever a route is active.", 28, -92,
        function() return ZL_Saved.settings.minilist.enabled end,
        function(value) ZL_Saved.settings.minilist.enabled = value; self:RefreshMiniList() end, 280)
    CreateCheck(miniListPanel, "Show Missing Objectives", "Show individual missing objectives when space allows.", 378, -92,
        function() return ZL_Saved.settings.minilist.showMissing end,
        function(value) ZL_Saved.settings.minilist.showMissing = value; self:RefreshMiniList() end, 280)
    local visibleTitle = miniListPanel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    visibleTitle:SetPoint("TOPLEFT", 24, -162)
    visibleTitle:SetText("Visible Categories")
    local visibleHint = miniListPanel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    visibleHint:SetPoint("TOPLEFT", visibleTitle, "BOTTOMLEFT", 0, -5)
    visibleHint:SetText("These options only affect the Mini-List; completion rules are unchanged.")
    visibleHint:SetTextColor(0.65, 0.69, 0.73)
    for index, descriptor in ipairs(CATEGORY_SETTINGS) do
        local categoryKey, categoryLabel = descriptor.key, descriptor.label
        local column = (index - 1) % 2
        local row = math.floor((index - 1) / 2)
        CreateCheck(miniListPanel, categoryLabel, "Show " .. categoryLabel:lower() .. " progress in the Mini-List.",
            28 + (column * 350), -218 - (row * 66),
            function() return ZL_Saved.settings.minilist.categories[categoryKey] ~= false end,
            function(value)
                ZL_Saved.settings.minilist.categories[categoryKey] = value
                self:RefreshMiniList()
            end, 280)
    end
    miniListPanel:SetScript("OnShow", function()
        for _, control in ipairs(miniListPanel.controls) do control.RefreshValue() end
    end)
    local miniListCategory = Settings.RegisterCanvasLayoutSubcategory(category, miniListPanel, "Mini-List")

    local themePanel = CreateFrame("Frame", "ZoneLockedThemeSettingsPanel")
    themePanel:SetSize(720, 540)
    themePanel.name = "Theme"
    local themeTitle = themePanel:CreateFontString(nil, "ARTWORK", "GameFontHighlightHuge")
    themeTitle:SetPoint("TOPLEFT", 24, -24)
    themeTitle:SetText("Interface Theme")
    local themeHint = themePanel:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
    themeHint:SetPoint("TOPLEFT", themeTitle, "BOTTOMLEFT", 0, -8)
    themeHint:SetText("Choose a visual treatment for Zone Locked windows and journals.")
    themePanel.cards = {}
    local function RefreshThemeCards()
        for key, card in pairs(themePanel.cards) do
            local selected = ZL_Saved.settings.theme == key
            local theme = self.ThemeDefinitions[key]
            card:SetBackdropBorderColor(unpack(selected and theme.accent or theme.border))
            card.selected:SetText(selected and "SELECTED" or "")
            card.selected:SetShown(selected)
            card.selectedBar:SetShown(selected)
        end
    end
    for index, key in ipairs({ "gilded", "parchment", "arcane", "emerald", "crimson", "frost",
        "midnight", "rosewood", "monochrome" }) do
        local themeKey, theme = key, self.ThemeDefinitions[key]
        local card = CreateFrame("Button", nil, themePanel, "BackdropTemplate")
        local column, row = (index - 1) % 3, math.floor((index - 1) / 3)
        card:SetSize(205, 126)
        card:SetPoint("TOPLEFT", 24 + (column * 218), -88 - (row * 138))
        card:SetBackdrop({ bgFile = "Interface/Buttons/WHITE8X8",
            edgeFile = "Interface/Tooltips/UI-Tooltip-Border", edgeSize = 14 })
        card:SetBackdropColor(unpack(theme.window))
        card.name = card:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
        card.name:SetPoint("TOPLEFT", 16, -13)
        card.name:SetWidth(173)
        card.name:SetJustifyH("LEFT")
        card.name:SetText(theme.name)
        card.name:SetTextColor(unpack(theme.accent))
        card.description = card:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        card.description:SetPoint("TOPLEFT", card.name, "BOTTOMLEFT", 0, -5)
        card.description:SetWidth(173)
        card.description:SetJustifyH("LEFT")
        card.description:SetText(theme.description)
        card.description:SetTextColor(theme.secondary[1] * 0.88, theme.secondary[2] * 0.88,
            theme.secondary[3] * 0.88, 1)
        card.swatches = {}
        for swatchIndex, color in ipairs({ theme.header, theme.accent, theme.secondary }) do
            local swatch = card:CreateTexture(nil, "ARTWORK")
            swatch:SetSize(34, 11)
            swatch:SetPoint("BOTTOMLEFT", 16 + ((swatchIndex - 1) * 39), 11)
            swatch:SetColorTexture(unpack(color))
        end
        card.selected = card:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
        card.selected:SetPoint("BOTTOMRIGHT", -12, 10)
        card.selected:SetText("")
        card.selectedBar = card:CreateTexture(nil, "ARTWORK")
        card.selectedBar:SetPoint("TOPLEFT", 2, -2)
        card.selectedBar:SetPoint("BOTTOMLEFT", 2, 2)
        card.selectedBar:SetWidth(4)
        card.selectedBar:SetColorTexture(unpack(theme.accent))
        card.selectedBar:Hide()
        card:SetScript("OnClick", function()
            ZL_Saved.settings.theme = themeKey
            RefreshThemeCards()
            self:ApplyTheme()
        end)
        card:SetScript("OnEnter", function(button) button:SetBackdropColor(unpack(theme.panel)) end)
        card:SetScript("OnLeave", function(button) button:SetBackdropColor(unpack(theme.window)) end)
        themePanel.cards[themeKey] = card
    end
    themePanel:SetScript("OnShow", RefreshThemeCards)
    local themeCategory = Settings.RegisterCanvasLayoutSubcategory(category, themePanel, "Theme")
    self.SettingsCategory = category
    self.ExpansionSettingsCategory = expansionCategory
    self.HistorySettingsCategory = historyCategory
    self.MiniListSettingsCategory = miniListCategory
    self.ThemeSettingsCategory = themeCategory
    self.SettingsPanel = panel
    self.ExpansionSettingsPanel = expansionPanel
    self.HistorySettingsPanel = historyPanel
    self.MiniListSettingsPanel = miniListPanel
    self.ThemeSettingsPanel = themePanel
end

function ZL:OpenSettings()
    if self.SettingsCategory and Settings and Settings.OpenToCategory then
        Settings.OpenToCategory(self.SettingsCategory:GetID())
    else
        self:Print("The Blizzard Settings panel is not available yet.")
    end
end
