local AddOnName, KeystonePercentageHelper = ...;

local _G = _G;
local pairs, unpack, select = pairs, unpack, select
local format = string.format
local gsub = string.gsub
local strsplit = strsplit

local AceConfig = LibStub("AceConfig-3.0")
local AceConfigDialog = LibStub("AceConfigDialog-3.0")

-- ---------------------------------------------------------------------------
-- Helper utilities
-- ---------------------------------------------------------------------------
-- Shallow-clone a table. If the WoW utility `CopyTable` exists we use it,
-- otherwise fall back to manual copy. This is needed so that changing the
-- `order` field for one AceConfig option group does not overwrite the value
-- used in another section.
local function CloneTable(tbl)
    if type(CopyTable) == "function" then return CopyTable(tbl) end
    local t = {}
    for k, v in pairs(tbl) do t[k] = v end
    return t
end

-- Insert dungeon option groups into an AceConfig args table in alphabetical
-- order. Every option is cloned from `sharedOptions[key]`, placed after the
-- section headers (offset with `baseOrder`), and assigned its own `order` so
-- AceConfig displays them deterministically.
--   addon        : reference to KeystonePercentageHelper for helper calls
--   dungeonKeys  : array of dungeon string keys (short names)
--   sharedOptions: table containing pre-built option groups for each dungeon
--   targetArgs   : the args table we are populating (e.g., dungeonArgs)
--   baseOrder    : numeric order to start from (usually 3)
local function InsertSortedDungeonOptions(addon, dungeonKeys, sharedOptions, targetArgs, baseOrder)
    local sortable = {}
    for _, key in ipairs(dungeonKeys) do
        local mapId = addon:GetDungeonIdByKey(key)
        local name = (mapId and select(1, C_ChallengeMode.GetMapUIInfo(mapId))) or key
        table.insert(sortable, { key = key, name = name })
    end
    table.sort(sortable, function(a, b) return a.name < b.name end)

    for idx, entry in ipairs(sortable) do
        local opt = CloneTable(sharedOptions[entry.key])
        opt.order = baseOrder + idx
        targetArgs[entry.key] = opt
    end
end

local L = LibStub("AceLocale-3.0"):GetLocale(AddOnName, true);
KeystonePercentageHelper.L = L

KeystonePercentageHelper.defaults = {
    profile = {
        general = {
            fontSize = 12,
            position = "CENTER",
            xOffset = 0,
            yOffset = 0,
            informGroup = true,
            informChannel = "PARTY",
            advancedOptionsEnabled = false,
            lastSeasonCheck = "",
            lastVersionCheck = "",
            rolesEnabled = {
                LEADER = true,
                TANK = true,
                HEALER = true,
                DAMAGER = true
            }
        },
        text = {font = "Friz Quadrata TT"},
        color = {
            inProgress = {r = 1, g = 1, b = 1, a = 1},
            finished = {r = 0, g = 1, b = 0, a = 1},
            missing = {r = 1, g = 0, b = 0, a = 1}
        },
        advanced = {}
    }
}

-- List of expansions and their corresponding data
local expansions = {
    {id = "TWW", name = "EXPANSION_WW", order = 4}, -- The War Within
    -- {id = "DF", name = "EXPANSION_DF", order = 5},         -- Dragonflight
    {id = "SL", name = "EXPANSION_SL", order = 6}, -- Shadowlands
    {id = "BFA", name = "EXPANSION_BFA", order = 7}, -- Battle for Azeroth
    -- {id = "LEGION", name = "EXPANSION_LEGION", order = 8}, -- Legion
    -- {id = "WOD", name = "EXPANSION_WOD", order = 9},       -- Warlords of Draenor
    -- {id = "MOP", name = "EXPANSION_MOP", order = 10},      -- Mists of Pandaria
    {id = "CATACLYSM", name = "EXPANSION_CATA", order = 11} -- Cataclysm
    -- {id = "TBC", name = "EXPANSION_TBC", order = 12} -- The Burning Crusade
    -- {id = "Vanilla", name = "EXPANSION_VANILLA", order = 12} -- Vanilla WoW
}

local portal = C_CVar.GetCVar("portal")
if portal == "US" then
    KeystonePercentageHelper.SEASON_START_DATES = {
        ["2024-09-10"] = "TWW_1", -- TWW Season 1 start date
        ["2025-03-04"] = "TWW_2", -- TWW Season 2 start date
        ["2025-08-12"] = "TWW_3"  -- TWW Season 3 start date
    }
elseif portal == "EU" then
    KeystonePercentageHelper.SEASON_START_DATES = {
        ["2024-09-10"] = "TWW_1", -- TWW Season 1 start date
        ["2025-03-05"] = "TWW_2", -- TWW Season 2 start date
        ["2025-08-13"] = "TWW_3"  -- TWW Season 3 start date
    }
else
    KeystonePercentageHelper.SEASON_START_DATES = {
        ["2024-09-10"] = "TWW_1", -- TWW Season 1 start date
        ["2025-03-05"] = "TWW_2", -- TWW Season 2 start date
        ["2025-08-13"] = "TWW_3"  -- TWW Season 3 start date
    }
end

-- Load defaults from all expansions
for _, expansion in ipairs(expansions) do
    local defaults = KeystonePercentageHelper[expansion.id .. "_DEFAULTS"]
    if defaults then
        for k, v in pairs(defaults) do
            KeystonePercentageHelper.defaults.profile.advanced[k] = v
        end
    end
end

function KeystonePercentageHelper:LoadExpansionDungeons()
    -- Process dungeon data and generate tables for all expansions
    for _, expansion in ipairs(expansions) do
        local dungeonData = self[expansion.id .. "_DUNGEON_DATA"]
        if dungeonData then
            -- Generate the tables for this expansion
            self:GenerateExpansionTables(expansion.id, dungeonData)

            -- Initialize advanced settings for each dungeon
            for shortName, _ in pairs(dungeonData) do
                -- Ensure the advanced settings table exists for this dungeon
                if not self.db.profile.advanced[shortName] then
                    self.db.profile.advanced[shortName] = {}
                end

                -- Initialize with defaults if needed
                local defaults = self[expansion.id .. "_DEFAULTS"][shortName]
                if defaults then
                    for key, value in pairs(defaults) do
                        if self.db.profile.advanced[shortName][key] == nil then
                            self.db.profile.advanced[shortName][key] = value
                        end
                    end
                end
            end

            -- Load dungeons into the main DUNGEONS table
            local dungeons = self[expansion.id .. "_DUNGEONS"]
            if dungeons then
                for id, data in pairs(dungeons) do
                    self.DUNGEONS[id] = data
                end
            end
        end
    end
end

function KeystonePercentageHelper:GetDungeonIdByKey(dungeonKey)
    -- Check each expansion's dungeon IDs table
    for _, expansion in ipairs(expansions) do
        local dungeonIds = self[expansion.id .. "_DUNGEON_IDS"]
        if dungeonIds and dungeonIds[dungeonKey] then
            return dungeonIds[dungeonKey]
        end
    end
    return nil
end

function KeystonePercentageHelper:GetDungeonKeyById(dungeonId)
    -- Check each expansion's dungeon IDs table
    for _, expansion in ipairs(expansions) do
        local dungeonIds = self[expansion.id .. "_DUNGEON_IDS"]
        if dungeonIds then
            for dungeonKey, id in pairs(dungeonIds) do
                if id == dungeonId then return dungeonKey end
            end
        end
    end
    return nil
end

function KeystonePercentageHelper:IsCurrentSeasonDungeon(dungeonId)
    -- Get the current date
    local currentDate = date("%Y-%m-%d")

    -- Find the most recent season
    local mostRecentSeasonDate = nil
    local currentSeasonId = nil

    for seasonDate, _ in pairs(self.SEASON_START_DATES) do
        if seasonDate <= currentDate and
            (not mostRecentSeasonDate or seasonDate > mostRecentSeasonDate) then
            currentSeasonId = self.SEASON_START_DATES[seasonDate]
            mostRecentSeasonDate = seasonDate
        end
    end

    if currentSeasonId then
        local seasonDungeonsTabName = currentSeasonId .. "_DUNGEONS"
        local seasonDungeons = self[seasonDungeonsTabName]

        if seasonDungeons then return seasonDungeons[dungeonId] or false end
    end

    return false
end

function KeystonePercentageHelper:IsNextSeasonDungeon(dungeonId)
    -- Get the current date
    local currentDate = date("%Y-%m-%d")

    -- Find the next season (first season that starts after current date)
    local nextSeasonDate = nil
    local nextSeasonId = nil

    for seasonDate, _ in pairs(self.SEASON_START_DATES) do
        if seasonDate > currentDate and
            (not nextSeasonDate or seasonDate < nextSeasonDate) then
            nextSeasonId = self.SEASON_START_DATES[seasonDate]
            nextSeasonDate = seasonDate
        end
    end

    if nextSeasonId then
        local nextSeasonDungeonsTabName = nextSeasonId .. "_DUNGEONS"
        local nextSeasonDungeons = self[nextSeasonDungeonsTabName]

        if nextSeasonDungeons then
            return nextSeasonDungeons[dungeonId] or false
        end
    end

    return false
end

function KeystonePercentageHelper:GetPositioningOptions()
    local self = KeystonePercentageHelper
    return {
        name = L["POSITIONING"],
        type = "group",
        inline = true,
        args = {
            showAnchor = {
                name = L["SHOW_ANCHOR"],
                type = "execute",
                order = 1,
                width = 2,
                func = function()
                    if self.anchorFrame then
                        self.anchorFrame:Show()
                        self.overlayFrame:Show()
                        -- Hide the WoW settings frame
                        HideUIPanel(SettingsPanel)
                    end
                end
            },
            position = {
                name = L["POSITION"],
                type = "select",
                order = 2,
                values = {
                    TOP = L["TOP"],
                    CENTER = L["CENTER"],
                    BOTTOM = L["BOTTOM"]
                },
                get = function()
                    return self.db.profile.general.position
                end,
                set = function(_, value)
                    self.db.profile.general.position = value
                    self:Refresh()
                end
            },
            xOffset = {
                name = L["X_OFFSET"],
                type = "range",
                order = 3,
                min = -500,
                max = 500,
                step = 1,
                get = function()
                    return self.db.profile.general.xOffset
                end,
                set = function(_, value)
                    self.db.profile.general.xOffset = value
                    self:Refresh()
                end
            },
            yOffset = {
                name = L["Y_OFFSET"],
                type = "range",
                order = 4,
                min = -500,
                max = 500,
                step = 1,
                get = function()
                    return self.db.profile.general.yOffset
                end,
                set = function(_, value)
                    self.db.profile.general.yOffset = value
                    self:Refresh()
                end
            }
        }
    }
end

function KeystonePercentageHelper:GetFontOptions()
    local self = KeystonePercentageHelper
    return {
        name = L["FONT"],
        type = "group",
        inline = true,
        order = 5.5,
        args = {
            font = {
                name = L["FONT"],
                type = "select",
                dialogControl = 'LSM30_Font',
                order = 1,
                values = AceGUIWidgetLSMlists.font,
                style = "dropdown",
                get = function() return self.db.profile.text.font end,
                set = function(_, value)
                    self.db.profile.text.font = value
                    self:Refresh()
                end
            },
            fontSize = {
                name = L["FONT_SIZE"],
                desc = L["FONT_SIZE_DESC"],
                type = "range",
                order = 2,
                min = 8,
                max = 64,
                step = 1,
                get = function()
                    return self.db.profile.general.fontSize
                end,
                set = function(_, value)
                    self.db.profile.general.fontSize = value
                    self:Refresh()
                end
            }
        }
    }
end

function KeystonePercentageHelper:GetColorOptions()
    local self = KeystonePercentageHelper
    return {
        name = L["COLORS"],
        type = "group",
        inline = true,
        order = 6,
        args = {
            inProgress = {
                name = L["IN_PROGRESS"],
                type = "color",
                order = 1,
                hasAlpha = true,
                get = function()
                    local color = self.db.profile.color.inProgress
                    return color.r, color.g, color.b, color.a
                end,
                set = function(_, r, g, b, a)
                    local color = self.db.profile.color.inProgress
                    color.r, color.g, color.b, color.a = r, g, b, a
                    self:Refresh()
                end
            },
            finished = {
                name = L["FINISHED"],
                type = "color",
                order = 2,
                hasAlpha = true,
                get = function()
                    local color = self.db.profile.color.finished
                    return color.r, color.g, color.b, color.a
                end,
                set = function(_, r, g, b, a)
                    local color = self.db.profile.color.finished
                    color.r, color.g, color.b, color.a = r, g, b, a
                    self:Refresh()
                end
            },
            missing = {
                name = L["MISSING"],
                type = "color",
                order = 3,
                hasAlpha = true,
                get = function()
                    local color = self.db.profile.color.missing
                    return color.r, color.g, color.b, color.a
                end,
                set = function(_, r, g, b, a)
                    local color = self.db.profile.color.missing
                    color.r, color.g, color.b, color.a = r, g, b, a
                    self:Refresh()
                end
            }
        }
    }
end

function KeystonePercentageHelper:GetOtherOptions()
    return {
        name = L["OPTIONS"],
        type = "group",
        inline = true,
        order = 10,
        args = {
            rolesEnabled = {
                name = L["ROLES_ENABLED"],
                desc = L["ROLES_ENABLED_DESC"],
                type = "multiselect",
                order = 2,
                values = {
                    LEADER = L["LEADER"],
                    TANK = L["TANK"],
                    HEALER = L["HEALER"],
                    DAMAGER = L["DPS"]
                },
                get = function(_, key)
                    return self.db.profile.general.rolesEnabled[key] or false
                end,
                set = function(_, key, state)
                    if state then
                        self.db.profile.general.rolesEnabled[key] = true
                    else
                        self.db.profile.general.rolesEnabled[key] = false
                    end
                    self:Refresh()
                end
            },
            informGroup = {
                name = L["INFORM_GROUP"],
                desc = L["INFORM_GROUP_DESC"],
                type = "toggle",
                order = 10,
                get = function()
                    return self.db.profile.general.informGroup
                end,
                set = function(_, value)
                    self.db.profile.general.informGroup = value
                end
            },
            informChannel = {
                name = L["MESSAGE_CHANNEL"],
                desc = L["MESSAGE_CHANNEL_DESC"],
                type = "select",
                order = 11,
                values = {PARTY = L["PARTY"], SAY = L["SAY"], YELL = L["YELL"]},
                disabled = function()
                    return not self.db.profile.general.informGroup
                end,
                get = function()
                    return self.db.profile.general.informChannel
                end,
                set = function(_, value)
                    self.db.profile.general.informChannel = value
                end
            },
            enabled = {
                name = L["ENABLE_ADVANCED_OPTIONS"],
                desc = L["ADVANCED_OPTIONS_DESC"],
                type = "toggle",
                width = "full",
                order = 12,
                get = function()
                    return self.db.profile.general.advancedOptionsEnabled
                end,
                set = function(_, value)
                    self.db.profile.general.advancedOptionsEnabled = value
                    self:UpdateDungeonData()
                end
            }
        }
    }
end

function KeystonePercentageHelper:GetAdvancedOptions()
    local self = KeystonePercentageHelper
    -- Helper function to get dungeon name with icon
    local function GetDungeonNameWithIcon(dungeonKey)
        local mapId = self:GetDungeonIdByKey(dungeonKey)

        local name, _, _, texture
        if mapId then
            name, _, _, texture = C_ChallengeMode.GetMapUIInfo(mapId)
        end

        -- Fallbacks
        local icon = texture
        local displayName = name

        return '|T' .. icon .. ":20:20:0:0|t " .. displayName
    end

    -- Helper function to format dungeon text
    local function FormatDungeonText(self, dungeonKey, defaults)
        local text = ""
        if defaults then
            text = text .. "|cffffd700" .. GetDungeonNameWithIcon(dungeonKey) ..
                       "|r:\n"
            local bossNum = 1
            while defaults["Boss" .. self:GetBossNumberString(bossNum)] do
                local bossKey = "Boss" .. self:GetBossNumberString(bossNum)
                local informKey = bossKey .. "Inform"
                text = text ..
                           string.format(
                               "  %s: |cff40E0D0%.2f%%|r - " ..
                                   L["INFORM_GROUP"] .. ": %s\n",
                               L[dungeonKey .. "_BOSS" .. bossNum],
                               defaults[bossKey],
                               defaults[informKey] and '|cff00ff00' .. L["YES"] ..
                                   '|r' or '|cffff0000' .. L["NO"] .. '|r')
                bossNum = bossNum + 1
            end
            text = text .. "\n"
        end
        return text
    end

    -- Create shared dungeon options
    local sharedDungeonOptions = {}
    for _, expansion in ipairs(expansions) do
        local dungeonIds = self[expansion.id .. "_DUNGEON_IDS"]
        if dungeonIds then
            for dungeonKey, dungeonId in pairs(dungeonIds) do
                sharedDungeonOptions[dungeonKey] =
                    self:CreateDungeonOptions(dungeonKey, 0)
            end
        end
    end

    -- Create expansion-specific dungeon args
    local function CreateExpansionDungeonArgs(dungeonIds, defaults)
        local args = {
            defaultPercentages = {
                order = 3,
                type = "description",
                fontSize = "medium",
                name = function()
                    local text = L["DEFAULT_PERCENTAGES"] .. ":\n\n"
                    for dungeonKey, _ in pairs(dungeonIds or {}) do
                        if defaults and defaults[dungeonKey] then
                            text = text ..
                                       FormatDungeonText(self, dungeonKey,
                                                         defaults[dungeonKey])
                        end
                    end
                    return text
                end
            }
        }

        -- Add dungeon options (alphabetical)
        if dungeonIds then
            local keys = {}
            for key, _ in pairs(dungeonIds) do table.insert(keys, key) end
            InsertSortedDungeonOptions(self, keys, sharedDungeonOptions, args, 3)
        end
        return args
    end

    -- Create current season options
    local currentSeasonDungeons = {}

    -- Get the current date
    local currentDate = date("%Y-%m-%d")

    -- Find the most recent season
    local mostRecentSeasonDate = nil
    local currentSeasonId = nil

    for seasonDate, _ in pairs(self.SEASON_START_DATES) do
        if seasonDate <= currentDate and
            (not mostRecentSeasonDate or seasonDate > mostRecentSeasonDate) then
            currentSeasonId = self.SEASON_START_DATES[seasonDate]
            mostRecentSeasonDate = seasonDate
        end
    end

    if currentSeasonId then
        local seasonDungeonsTabName = currentSeasonId .. "_DUNGEONS"
        local seasonDungeons = self[seasonDungeonsTabName]

        if seasonDungeons then
            for _, expansion in ipairs(expansions) do
                local dungeonIds = self[expansion.id .. "_DUNGEON_IDS"]
                if dungeonIds then
                    for dungeonKey, dungeonId in pairs(dungeonIds) do
                        if seasonDungeons[dungeonId] then
                            table.insert(currentSeasonDungeons,
                                         {key = dungeonKey, id = dungeonId})
                        end
                    end
                end
            end
        end
    end

    -- Sort dungeons alphabetically by their localized names
    table.sort(currentSeasonDungeons, function(a, b)
        local mapIdA = a.id or self:GetDungeonIdByKey(a.key)
        local mapIdB = b.id or self:GetDungeonIdByKey(b.key)

        local nameA
        if mapIdA then nameA = select(1, C_ChallengeMode.GetMapUIInfo(mapIdA)) end
        nameA = nameA or a.key

        local nameB
        if mapIdB then nameB = select(1, C_ChallengeMode.GetMapUIInfo(mapIdB)) end
        nameB = nameB or b.key

        return nameA < nameB
    end)

    -- Create current season dungeon args
    local dungeonArgs = {
        export = {
            order = 1,
            type = "execute",
            name = L["EXPORT_SECTION"],
            desc = (L["EXPORT_SECTION_DESC"]):format(L["CURRENT_SEASON"]),
            func = function()
                local addon = KeystonePercentageHelper
                local dungeonIds = {}

                -- Collect current season dungeon data
                for _, dungeon in ipairs(currentSeasonDungeons) do
                    local dungeonKey = dungeon.key
                    if addon.db.profile.advanced[dungeonKey] then
                        dungeonIds[dungeonKey] =
                            addon.db.profile.advanced[dungeonKey]
                    end
                end

                -- Export current season dungeon data
                addon:ExportDungeonSettings(dungeonIds, "section",
                                            L["CURRENT_SEASON"])
            end
        },
        import = {
            order = 2,
            type = "execute",
            name = L["IMPORT_SECTION"],
            desc = (L["IMPORT_SECTION_DESC"]):format(L["CURRENT_SEASON"]),
            func = function()
                local addon = KeystonePercentageHelper

                -- Create filter for current season dungeons
                local dungeonFilter = {}
                for _, dungeon in ipairs(currentSeasonDungeons) do
                    dungeonFilter[dungeon.key] = true
                end

                addon:ShowImportDialog(L["CURRENT_SEASON"], dungeonFilter)
            end
        },
        defaultPercentages = {
            order = 3,
            type = "description",
            fontSize = "medium",
            name = function()
                local text = L["DEFAULT_PERCENTAGES"] .. ":\n\n"
                for _, dungeon in ipairs(currentSeasonDungeons) do
                    local dungeonKey = dungeon.key
                    local defaults
                    for _, expansion in ipairs(expansions) do
                        if self[expansion.id .. "_DUNGEON_IDS"][dungeonKey] then
                            defaults =
                                self[expansion.id .. "_DEFAULTS"][dungeonKey]
                            break
                        end
                    end

                    text = text .. FormatDungeonText(self, dungeonKey, defaults)
                end
                return text
            end
        }
    }

    -- Add current season dungeon options (alphabetical)
    do
        local keys = {}
        for _, d in ipairs(currentSeasonDungeons) do table.insert(keys, d.key) end
        InsertSortedDungeonOptions(self, keys, sharedDungeonOptions, dungeonArgs, 3)
    end

    -- Create next season dungeon args
    local nextSeasonDungeons = {}

    -- Get the current date
    local currentDate = date("%Y-%m-%d")

    -- Find the next season (first season that starts after current date)
    local nextSeasonDate = nil
    local nextSeasonId = nil

    for seasonDate, _ in pairs(self.SEASON_START_DATES) do
        if seasonDate > currentDate and
            (not nextSeasonDate or seasonDate < nextSeasonDate) then
            nextSeasonId = self.SEASON_START_DATES[seasonDate]
            nextSeasonDate = seasonDate
        end
    end

    if nextSeasonId then
        local nextSeasonDungeonsTabName = nextSeasonId .. "_DUNGEONS"
        local nextSeasonDungeonsTable = self[nextSeasonDungeonsTabName]

        if nextSeasonDungeonsTable then
            for _, expansion in ipairs(expansions) do
                local dungeonIds = self[expansion.id .. "_DUNGEON_IDS"]
                if dungeonIds then
                    for dungeonKey, dungeonId in pairs(dungeonIds) do
                        if nextSeasonDungeonsTable[dungeonId] then
                            table.insert(nextSeasonDungeons,
                                         {key = dungeonKey, id = dungeonId})
                        end
                    end
                end
            end
        end
    end

    -- Sort dungeons alphabetically by their localized names
    table.sort(nextSeasonDungeons, function(a, b)
        local mapIdA = a.id or self:GetDungeonIdByKey(a.key)
        local mapIdB = b.id or self:GetDungeonIdByKey(b.key)

        local nameA
        if mapIdA then nameA = select(1, C_ChallengeMode.GetMapUIInfo(mapIdA)) end
        nameA = nameA or a.key

        local nameB
        if mapIdB then nameB = select(1, C_ChallengeMode.GetMapUIInfo(mapIdB)) end
        nameB = nameB or b.key

        return nameA < nameB
    end)

    -- Create next season dungeon args
    local nextSeasonDungeonArgs = {
        export = {
            order = 1,
            type = "execute",
            name = L["EXPORT_SECTION"],
            desc = (L["EXPORT_SECTION_DESC"]):format(L["NEXT_SEASON"]),
            func = function()
                local addon = KeystonePercentageHelper
                local dungeonIds = {}

                -- Collect next season dungeon data
                for _, dungeon in ipairs(nextSeasonDungeons) do
                    local dungeonKey = dungeon.key
                    if addon.db.profile.advanced[dungeonKey] then
                        dungeonIds[dungeonKey] =
                            addon.db.profile.advanced[dungeonKey]
                    end
                end

                -- Export next season dungeon data
                addon:ExportDungeonSettings(dungeonIds, "section",
                                            L["NEXT_SEASON"])
            end
        },
        import = {
            order = 2,
            type = "execute",
            name = L["IMPORT_SECTION"],
            desc = (L["IMPORT_SECTION_DESC"]):format(L["NEXT_SEASON"]),
            func = function()
                local addon = KeystonePercentageHelper

                -- Create filter for next season dungeons
                local dungeonFilter = {}
                for _, dungeon in ipairs(nextSeasonDungeons) do
                    dungeonFilter[dungeon.key] = true
                end

                addon:ShowImportDialog(L["NEXT_SEASON"], dungeonFilter)
            end
        },
        defaultPercentages = {
            order = 3,
            type = "description",
            fontSize = "medium",
            name = function()
                local text = L["DEFAULT_PERCENTAGES"] .. ":\n\n"
                for _, dungeon in ipairs(nextSeasonDungeons) do
                    local dungeonKey = dungeon.key
                    local defaults
                    for _, expansion in ipairs(expansions) do
                        if self[expansion.id .. "_DUNGEON_IDS"][dungeonKey] then
                            defaults =
                                self[expansion.id .. "_DEFAULTS"][dungeonKey]
                            break
                        end
                    end

                    text = text .. FormatDungeonText(self, dungeonKey, defaults)
                end
                return text
            end
        }
    }

    -- Add next season dungeon options (alphabetical)
    do
        local keys = {}
        for _, d in ipairs(nextSeasonDungeons) do table.insert(keys, d.key) end
        InsertSortedDungeonOptions(self, keys, sharedDungeonOptions, nextSeasonDungeonArgs, 3)
    end

    -- Create expansion sections
    local args = {
        resetAll = {
            order = 1,
            type = "execute",
            name = L["RESET_ALL_DUNGEONS"],
            desc = L["RESET_ALL_DUNGEONS_DESC"],
            confirm = true,
            confirmText = L["RESET_ALL_DUNGEONS_CONFIRM"],
            func = function()
                -- Reset all dungeons to their defaults
                self:ResetAllDungeons()
            end
        },
        exportAllDungeons = {
            order = 2,
            type = "execute",
            name = L["EXPORT_ALL_DUNGEONS"],
            desc = L["EXPORT_ALL_DUNGEONS_DESC"],
            func = function()
                local addon = KeystonePercentageHelper

                -- Collect all dungeon data
                local allDungeonData = {}
                for dungeonKey, _ in pairs(addon.db.profile.advanced) do
                    if type(addon.db.profile.advanced[dungeonKey]) == "table" then
                        allDungeonData[dungeonKey] =
                            addon.db.profile.advanced[dungeonKey]
                    end
                end

                -- Export all dungeon data
                addon:ExportDungeonSettings(allDungeonData, "all_dungeons")
            end
        },
        importAllDungeons = {
            order = 3,
            type = "execute",
            name = L["IMPORT_ALL_DUNGEONS"],
            desc = L["IMPORT_ALL_DUNGEONS_DESC"],
            func = function()
                local addon = KeystonePercentageHelper
                addon:ShowImportDialog()
            end
        },
        dungeons = {
            name = "|cff40E0D0" .. L["CURRENT_SEASON"] .. "|r",
            type = "group",
            childGroups = "tree",
            order = 3,
            args = dungeonArgs
        }
    }

    -- Only add next season section if there are next season dungeons
    if nextSeasonId and #nextSeasonDungeons > 0 then
        args.nextseason = {
            name = "|cffff5733" .. L["NEXT_SEASON"] .. "|r",
            type = "group",
            childGroups = "tree",
            order = 4,
            args = nextSeasonDungeonArgs
        }
    end

    -- Create expansion sections
    for _, expansion in ipairs(expansions) do
        local sectionKey = expansion.id:lower()
        args[sectionKey] = {
            name = "|cffffffff" .. L[expansion.name] .. "|r",
            type = "group",
            childGroups = "tree",
            order = expansion.order + 4, -- Shift expansion orders to after next season
            args = CreateExpansionDungeonArgs(
                self[expansion.id .. "_DUNGEON_IDS"],
                self[expansion.id .. "_DEFAULTS"])
        }

        -- Add export/import buttons for this section
        args[sectionKey].args.exportSection = {
            order = 1, -- Place before defaultPercentages
            type = "execute",
            name = L["EXPORT_SECTION"],
            desc = (L["EXPORT_SECTION_DESC"]):format(L[expansion.name]),
            func = function()
                local addon = KeystonePercentageHelper
                local dungeonIds = addon[expansion.id .. "_DUNGEON_IDS"]

                if not dungeonIds then return end

                -- Collect section dungeon data
                local sectionData = {}
                for dungeonKey, _ in pairs(dungeonIds) do
                    if addon.db.profile.advanced[dungeonKey] then
                        sectionData[dungeonKey] =
                            addon.db.profile.advanced[dungeonKey]
                    end
                end

                -- Export section dungeon data
                addon:ExportDungeonSettings(sectionData, "section",
                                            L[expansion.name])
            end
        }

        args[sectionKey].args.importSection = {
            order = 2, -- Place before defaultPercentages
            type = "execute",
            name = L["IMPORT_SECTION"],
            desc = (L["IMPORT_SECTION_DESC"]):format(L[expansion.name]),
            func = function()
                local addon = KeystonePercentageHelper
                local dungeonIds = addon[expansion.id .. "_DUNGEON_IDS"]

                if not dungeonIds then return end

                -- Create filter for this expansion's dungeons
                local dungeonFilter = {}
                for dungeonKey, _ in pairs(dungeonIds) do
                    dungeonFilter[dungeonKey] = true
                end

                addon:ShowImportDialog(L[expansion.name], dungeonFilter)
            end
        }
    end
    return {
        name = L["ADVANCED_SETTINGS"],
        type = "group",
        childGroups = "tree",
        order = 2,
        args = args
    }
end

function KeystonePercentageHelper:CreateDungeonOptions(dungeonKey, order)
    local self = KeystonePercentageHelper
    local numBosses = #self.DUNGEONS[self:GetDungeonIdByKey(dungeonKey)]

    -- Ensure the advanced settings table exists for this dungeon
    if not self.db.profile.advanced[dungeonKey] then
        self.db.profile.advanced[dungeonKey] = {}

        -- Initialize with defaults if needed
        for _, expansion in ipairs(expansions) do
            if self[expansion.id .. "_DUNGEON_IDS"] and
                self[expansion.id .. "_DUNGEON_IDS"][dungeonKey] then
                local defaults = self[expansion.id .. "_DEFAULTS"][dungeonKey]
                if defaults then
                    for key, value in pairs(defaults) do
                        self.db.profile.advanced[dungeonKey][key] = value
                    end
                end
                break
            end
        end
    end

    local options = {
        name = function()
            local mapId = self:GetDungeonIdByKey(dungeonKey)

            local name, texture
            if mapId then
                name, _, _, texture, _ = C_ChallengeMode.GetMapUIInfo(mapId)
            end

            return '|T' .. texture .. ":16:16:0:0|t " .. (name)
        end,
        type = "group",
        order = order,
        args = {
            dungeonHeader = {
                order = 0,
                type = "description",
                fontSize = "large",
                name = function()
                    local mapId = self:GetDungeonIdByKey(dungeonKey)

                    local name, texture
                    if mapId then
                        name, _, _, texture, _ =
                            C_ChallengeMode.GetMapUIInfo(mapId)
                    end

                    return "|T" .. texture .. ":20:20:0:0|t |cff40E0D0" ..
                               (name) .. "|r"
                end
            },
            dungeonSecondHeader = {type = "header", name = "", order = 1},
            reset = {
                order = 2,
                type = "execute",
                name = L["RESET_DUNGEON"],
                desc = L["RESET_DUNGEON_DESC"],
                func = function()
                    local dungeonId = self:GetDungeonIdByKey(dungeonKey)
                    if dungeonId and self.DUNGEONS[dungeonId] then
                        -- Reset all boss percentages and inform group settings for this dungeon to defaults
                        if not self.db.profile.advanced[dungeonKey] then
                            self.db.profile.advanced[dungeonKey] = {}
                        end

                        -- Get the appropriate defaults
                        local defaults
                        for _, expansion in ipairs(expansions) do
                            if self[expansion.id .. "_DUNGEON_IDS"][dungeonKey] then
                                defaults =
                                    self[expansion.id .. "_DEFAULTS"][dungeonKey]
                                break
                            end
                        end

                        if defaults then
                            for key, value in pairs(defaults) do
                                self.db.profile.advanced[dungeonKey][key] =
                                    value
                            end
                        end

                        -- Update the display
                        self:UpdateDungeonData()
                        LibStub("AceConfigRegistry-3.0"):NotifyChange(
                            "KeystonePercentageHelper")
                    end
                end,
                confirm = true,
                confirmText = L["RESET_DUNGEON_CONFIRM"]
            },
            export = {
                order = 3,
                type = "execute",
                name = L["EXPORT_DUNGEON"],
                desc = L["EXPORT_DUNGEON_DESC"],
                func = function()
                    local addon = KeystonePercentageHelper
                    local dungeonId = addon:GetDungeonIdByKey(dungeonKey)
                    if dungeonId and addon.DUNGEONS[dungeonId] and
                        addon.db.profile.advanced[dungeonKey] then
                        -- Create export string for single dungeon
                        local exportData = {
                            dungeon = dungeonKey,
                            data = addon.db.profile.advanced[dungeonKey]
                        }
                        local serialized =
                            LibStub("AceSerializer-3.0"):Serialize(exportData)
                        local compressed =
                            LibStub("LibDeflate"):CompressDeflate(serialized)
                        local encoded = LibStub("LibDeflate"):EncodeForPrint(
                                            compressed)

                        -- Show export dialog
                        StaticPopupDialogs["KPH_EXPORT_DIALOG"] = {
                            text = L["EXPORT_DIALOG_TEXT"],
                            button1 = OKAY,
                            hasEditBox = true,
                            editBoxWidth = 350,
                            maxLetters = 999999,
                            OnShow = function(dialog)
                                dialog.EditBox:SetText(encoded)
                                dialog.EditBox:HighlightText()
                                dialog.EditBox:SetFocus()
                            end,
                            EditBoxOnEscapePressed = function(editBox)
                                editBox:GetParent():Hide()
                            end,
                            timeout = 0,
                            whileDead = true,
                            hideOnEscape = true
                        }
                        StaticPopup_Show("KPH_EXPORT_DIALOG")
                    end
                end
            },
            import = {
                order = 4,
                type = "execute",
                name = L["IMPORT_DUNGEON"],
                desc = L["IMPORT_DUNGEON_DESC"],
                func = function()
                    local addon = KeystonePercentageHelper

                    -- Create filter for this specific dungeon
                    local dungeonFilter = {}
                    dungeonFilter[dungeonKey] = true

                    StaticPopupDialogs["KPH_IMPORT_DIALOG"] = {
                        text = L["IMPORT_DIALOG_TEXT"],
                        button1 = OKAY,
                        button2 = CANCEL,
                        hasEditBox = true,
                        editBoxWidth = 350,
                        maxLetters = 999999,
                        OnAccept = function(dialog)
                            local importString = dialog.EditBox:GetText()
                            addon:ImportDungeonSettings(importString, nil,
                                                        dungeonFilter)
                        end,
                        EditBoxOnEscapePressed = function(editBox)
                            editBox:GetParent():Hide()
                        end,
                        timeout = 0,
                        whileDead = true,
                        hideOnEscape = true
                    }
                    StaticPopup_Show("KPH_IMPORT_DIALOG")
                end
            },
            header = {order = 5, type = "header", name = L["TANK_GROUP_HEADER"]}
        }
    }

    for i = 1, numBosses do
        local bossNumStr = self:GetBossNumberString(i)
        local bossName = L[dungeonKey .. "_BOSS" .. i] or ("Boss " .. i)

        -- Create a group for each boss line
        options.args["boss" .. i] = {
            type = "group",
            name = bossName,
            inline = true,
            order = i + 5, -- Start boss orders at 6 (after header)
            args = {
                percent = {
                    name = L["PERCENTAGE"],
                    type = "range",
                    min = 0,
                    max = 100,
                    step = 0.01,
                    order = 1,
                    width = 1,
                    get = function()
                        return self.db.profile.advanced[dungeonKey]["Boss" ..
                                   bossNumStr]
                    end,
                    set = function(_, value)
                        self.db.profile.advanced[dungeonKey]["Boss" ..
                            bossNumStr] = value
                        self:UpdateDungeonData()
                    end
                },
                inform = {
                    name = L["INFORM_GROUP"],
                    type = "toggle",
                    order = 2,
                    width = 1,
                    get = function()
                        return self.db.profile.advanced[dungeonKey]["Boss" ..
                                   bossNumStr .. "Inform"]
                    end,
                    set = function(_, value)
                        self.db.profile.advanced[dungeonKey]["Boss" ..
                            bossNumStr .. "Inform"] = value
                        self:UpdateDungeonData()
                    end
                }
            }
        }
    end
    return options
end

function KeystonePercentageHelper:ToggleConfig()
    Settings.OpenToCategory("Keystone Percentage Helper")
end

function KeystonePercentageHelper:CreateColorString(text, db)
    local hex = db.r and db.g and db.b and self:RGBToHex(db.r, db.g, db.b) or
                    "|cffffffff"

    local string = hex .. text .. "|r"
    return string
end

function KeystonePercentageHelper:RGBToHex(r, g, b, header, ending)
    r = r <= 1 and r >= 0 and r or 1
    g = g <= 1 and g >= 0 and g or 1
    b = b <= 1 and b >= 0 and b or 1

    local hex = format('%s%02x%02x%02x%s', header or '|cff', r * 255, g * 255,
                       b * 255, ending or '')
    return hex
end

function KeystonePercentageHelper:GenerateChangelog()
    self.changelogOptions = {
        type = "group",
        childGroups = "select",
        name = L["Changelog"],
        args = {}
    }

    if not self.Changelog or type(self.Changelog) ~= "table" then return end

    local function orange(string)
        if type(string) ~= "string" then string = tostring(string) end
        string = self:CreateColorString(string,
                                        {r = 0.859, g = 0.388, b = 0.203})
        return string
    end

    local function renderChangelogLine(line)
        line = gsub(line, "%[[^%[]+%]", orange)
        return line
    end

    -- Remove the "no changelog" entry if we have actual entries
    self.changelogOptions.args.noChangelog = nil

    for version, data in pairs(self.Changelog) do
        if type(data) == "table" and data.version_string and data.release_date then
            local versionString = data.version_string
            local dateTable = {strsplit("/", data.release_date)}
            local dateString = data.release_date
            if #dateTable == 3 then
                dateString = L["%month%-%day%-%year%"]
                dateString = gsub(dateString, "%%year%%", dateTable[1])
                dateString = gsub(dateString, "%%month%%", dateTable[2])
                dateString = gsub(dateString, "%%day%%", dateTable[3])
            end

            self.changelogOptions.args[tostring(version)] = {
                order = 10000 - version,
                name = versionString,
                type = "group",
                args = {
                    version = {
                        order = 2,
                        type = "description",
                        name = L["Version"] .. " " .. orange(versionString) ..
                            " - |cffbbbbbb" .. dateString .. "|r",
                        fontSize = "large"
                    }
                }
            }

            local page = self.changelogOptions.args[tostring(version)].args

            -- Checking localized "Important" category
            local important_localized = {}
            if data.important and data.important[GetLocale()] and
                next(data.important[GetLocale()]) then
                important_localized = data.important[GetLocale()]
            elseif data.important and data.important["enUS"] then
                important_localized = data.important["enUS"]
            end

            if important_localized and #important_localized > 0 then
                page.importantHeader = {
                    order = 3,
                    type = "header",
                    name = orange(L["Important"])
                }
                page.important = {
                    order = 4,
                    type = "description",
                    name = function()
                        local text = ""
                        for index, line in ipairs(important_localized) do
                            text = text .. index .. ". " ..
                                       renderChangelogLine(line) .. "\n"
                        end
                        return text .. "\n"
                    end,
                    fontSize = "medium"
                }
            end

            -- Checking localized "New" category
            local new_localized = {}
            if data.new and data.new[GetLocale()] and
                next(data.new[GetLocale()]) then
                new_localized = data.new[GetLocale()]
            elseif data.new and data.new["enUS"] then
                new_localized = data.new["enUS"]
            end

            if new_localized and #new_localized > 0 then
                page.newHeader = {
                    order = 5,
                    type = "header",
                    name = orange(L["New"])
                }
                page.new = {
                    order = 6,
                    type = "description",
                    name = function()
                        local text = ""
                        for index, line in ipairs(new_localized) do
                            text = text .. index .. ". " ..
                                       renderChangelogLine(line) .. "\n"
                        end
                        return text .. "\n"
                    end,
                    fontSize = "medium"
                }
            end

            -- Checking localized "Bugfix" category
            local bugfix_localized = {}
            if data.bugfix and data.bugfix[GetLocale()] and
                next(data.bugfix[GetLocale()]) then
                bugfix_localized = data.bugfix[GetLocale()]
            elseif data.bugfix and data.bugfix["enUS"] then
                bugfix_localized = data.bugfix["enUS"]
            end

            if bugfix_localized and #bugfix_localized > 0 then
                page.bugfixHeader = {
                    order = 7,
                    type = "header",
                    name = orange(L["Bugfixes"])
                }
                page.bugfix = {
                    order = 8,
                    type = "description",
                    name = function()
                        local text = ""
                        for index, line in ipairs(bugfix_localized) do
                            text = text .. index .. ". " ..
                                       renderChangelogLine(line) .. "\n"
                        end
                        return text .. "\n"
                    end,
                    fontSize = "medium"
                }
            end

            -- Checking localized "Improvment" category
            local improvment_localized = {}
            if data.improvment and data.improvment[GetLocale()] and
                next(data.improvment[GetLocale()]) then
                improvment_localized = data.improvment[GetLocale()]
            elseif data.improvment and data.improvment["enUS"] then
                improvment_localized = data.improvment["enUS"]
            end

            if improvment_localized and #improvment_localized > 0 then
                page.improvmentHeader = {
                    order = 9,
                    type = "header",
                    name = orange(L["Improvment"])
                }
                page.improvment = {
                    order = 10,
                    type = "description",
                    name = function()
                        local text = ""
                        for index, line in ipairs(improvment_localized) do
                            text = text .. index .. ". " ..
                                       renderChangelogLine(line) .. "\n"
                        end
                        return text .. "\n"
                    end,
                    fontSize = "medium"
                }
            end
        end
    end
end

function KeystonePercentageHelper:GetBossNumberString(num)
    local numbers = {
        [1] = "One",
        [2] = "Two",
        [3] = "Three",
        [4] = "Four",
        [5] = "Five",
        [6] = "Six",
        [7] = "Seven",
        [8] = "Eight",
        [9] = "Nine",
        [10] = "Ten"
    }
    return numbers[num] or tostring(num)
end

function KeystonePercentageHelper:ResetAllDungeons()
    local self = KeystonePercentageHelper
    -- Reset all dungeons to their defaults
    for _, expansion in ipairs(expansions) do
        local dungeonIds = self[expansion.id .. "_DUNGEON_IDS"]
        if dungeonIds then
            for dungeonKey, _ in pairs(dungeonIds) do
                -- Get the appropriate defaults
                local defaults
                for _, expansion in ipairs(expansions) do
                    if self[expansion.id .. "_DUNGEON_IDS"][dungeonKey] then
                        defaults = self[expansion.id .. "_DEFAULTS"][dungeonKey]
                        break
                    end
                end

                if defaults then
                    if not self.db.profile.advanced[dungeonKey] then
                        self.db.profile.advanced[dungeonKey] = {}
                    end
                    for key, value in pairs(defaults) do
                        self.db.profile.advanced[dungeonKey][key] = value
                    end
                end
            end
        end
    end

    -- Update the display
    self:UpdateDungeonData()
    LibStub("AceConfigRegistry-3.0"):NotifyChange("KeystonePercentageHelper")
end

function KeystonePercentageHelper:ResetCurrentSeasonDungeons(specificDungeons)
    local self = KeystonePercentageHelper

    -- Get the current date
    local currentDate = date("%Y-%m-%d")

    -- Find the most recent season
    local mostRecentSeasonDate = nil
    local currentSeasonId = nil

    for seasonDate, _ in pairs(self.SEASON_START_DATES) do
        if seasonDate <= currentDate and
            (not mostRecentSeasonDate or seasonDate > mostRecentSeasonDate) then
            currentSeasonId = self.SEASON_START_DATES[seasonDate]
            mostRecentSeasonDate = seasonDate
        end
    end

    if currentSeasonId then
        local seasonDungeonsTabName = currentSeasonId .. "_DUNGEONS"
        local seasonDungeons = self[seasonDungeonsTabName]

        if seasonDungeons then
            -- Reset only the current season dungeons to their defaults
            for dungeonId, _ in pairs(seasonDungeons) do
                local dungeonKey = self:GetDungeonKeyById(dungeonId)
                if dungeonKey then
                    -- If specificDungeons is provided, only reset those dungeons
                    if specificDungeons and not specificDungeons[dungeonKey] then
                        -- Skip this dungeon as it's not in the list of dungeons to reset
                    else
                        -- Find the appropriate defaults for this dungeon
                        local defaults
                        for _, expansion in ipairs(expansions) do
                            if self[expansion.id .. "_DUNGEON_IDS"] and
                                self[expansion.id .. "_DUNGEON_IDS"][dungeonKey] then
                                defaults =
                                    self[expansion.id .. "_DEFAULTS"][dungeonKey]
                                break
                            end
                        end

                        if defaults then
                            if not self.db.profile.advanced[dungeonKey] then
                                self.db.profile.advanced[dungeonKey] = {}
                            end
                            for key, value in pairs(defaults) do
                                self.db.profile.advanced[dungeonKey][key] =
                                    value
                            end
                        end
                    end
                end
            end
        end
    end

    -- Update the display
    self:UpdateDungeonData()
    LibStub("AceConfigRegistry-3.0"):NotifyChange("KeystonePercentageHelper")
end

function KeystonePercentageHelper:CheckForNewSeason()
    local self = KeystonePercentageHelper
    local currentDate = date("%Y-%m-%d")

    -- If this is first load (lastSeasonCheck is empty), just set the date and don't show popup
    if not self.db.profile.lastSeasonCheck or self.db.profile.lastSeasonCheck ==
        "" then
        self.db.profile.lastSeasonCheck = currentDate
        return
    end

    -- Find the most recent season start date
    local mostRecentSeasonDate = nil
    for seasonDate, _ in pairs(self.SEASON_START_DATES) do
        if seasonDate <= currentDate and
            (not mostRecentSeasonDate or seasonDate > mostRecentSeasonDate) then
            local seasonDungeonsTabName =
                self.SEASON_START_DATES[seasonDate] .. "_DUNGEONS"
            currentSeasonDungeons = self[seasonDungeonsTabName]
            mostRecentSeasonDate = seasonDate
        end
    end

    -- If last check was before the most recent season start, show popup
    if mostRecentSeasonDate and self.db.profile.lastSeasonCheck <
        mostRecentSeasonDate and not InCombatLockdown() then
        StaticPopupDialogs["KPH_NEW_SEASON"] = {
            text = "|cffffd100Keystone Percentage Helper|r\n\n" ..
                L["NEW_SEASON_RESET_PROMPT"] .. "\n\n",
            button1 = YES,
            button2 = NO,
            OnAccept = function()
                -- Reset only current season dungeon values
                self:ResetCurrentSeasonDungeons()
                self.db.profile.lastSeasonCheck = currentDate
            end,
            OnCancel = function()
                self.db.profile.lastSeasonCheck = currentDate
            end,
            timeout = 0,
            whileDead = true,
            hideOnEscape = true,
            preferredIndex = 3,
            showAlert = true,
            title = "Keystone Percentage Helper"
        }
        StaticPopup_Show("KPH_NEW_SEASON")
    end
end

function KeystonePercentageHelper:CheckForNewRoutes()
    local currentVersion = C_AddOns.GetAddOnMetadata("KeystonePercentageHelper",
                                                     "Version")
    local lastVersionCheck = self.db.profile.general.lastVersionCheck or ""
    local lastSeasonCheck = self.db.profile.lastSeasonCheck or ""
    local lastRoutesUpdate = self.lastRoutesUpdate or ""

    -- Get the current date
    local currentDate = date("%Y-%m-%d")

    -- If it's the first version check but the user already had a previous version installed
    -- (indicated by lastSeasonCheck being populated), and we need to prompt for route reset
    if lastVersionCheck == "" and self.db.profile.general.advancedOptionsEnabled and
        currentDate > lastSeasonCheck and not InCombatLockdown() then
        local changedDungeonsText = self:GetChangedDungeonsText()

        StaticPopupDialogs["KPH_NEW_ROUTES"] = {
            text = "|cffffd100Keystone Percentage Helper|r\n\n" ..
                L["NEW_ROUTES_RESET_PROMPT"] .. "\n\n" .. changedDungeonsText,
            button1 = L["RESET_ALL"],
            button2 = L["NO"],
            button3 = (self.CHANGED_ROUTES_DUNGEONS and
                next(self.CHANGED_ROUTES_DUNGEONS)) and L["RESET_CHANGED_ONLY"] or
                nil,
            OnAccept = function()
                -- Reset all current season dungeon values
                self:ResetCurrentSeasonDungeons()
                self.db.profile.general.lastVersionCheck = currentVersion
            end,
            OnAlt = function()
                -- Reset only dungeons with changed routes
                self:ResetCurrentSeasonDungeons(self.CHANGED_ROUTES_DUNGEONS)
                self.db.profile.general.lastVersionCheck = currentVersion
            end,
            OnCancel = function()
                self.db.profile.general.lastVersionCheck = currentVersion
            end,
            timeout = 0,
            whileDead = true,
            hideOnEscape = true,
            preferredIndex = 3,
            showAlert = true,
            title = "Keystone Percentage Helper"
        }
        StaticPopup_Show("KPH_NEW_ROUTES")
        return
        -- If it's the first initialization of the addon (both checks are empty), just store the current version
    elseif lastVersionCheck == "" and lastSeasonCheck == "" then
        self.db.profile.general.lastVersionCheck = currentVersion
        return
    end

    -- If the version has changed and we need to prompt for route reset
    local prevWasBeta = (lastVersionCheck ~= "" and lastVersionCheck:lower():find("beta", 1, true) ~= nil)
    if lastVersionCheck ~= currentVersion and
        self.db.profile.general.advancedOptionsEnabled and
        not InCombatLockdown() and
        currentDate > lastSeasonCheck and
        (((lastRoutesUpdate > lastVersionCheck or lastVersionCheck == "") and currentVersion >= lastRoutesUpdate) or prevWasBeta) then

        local changedDungeonsText = self:GetChangedDungeonsText()

        StaticPopupDialogs["KPH_NEW_ROUTES"] = {
            text = "|cffffd100Keystone Percentage Helper|r\n\n" ..
                L["NEW_ROUTES_RESET_PROMPT"] .. "\n\n" .. changedDungeonsText,
            button1 = L["RESET_ALL"],
            button2 = L["NO"],
            button3 = (self.CHANGED_ROUTES_DUNGEONS and
                next(self.CHANGED_ROUTES_DUNGEONS)) and L["RESET_CHANGED_ONLY"] or
                nil,
            OnAccept = function()
                -- Reset all current season dungeon values
                self:ResetCurrentSeasonDungeons()
                self.db.profile.general.lastVersionCheck = currentVersion
            end,
            OnAlt = function()
                -- Reset only dungeons with changed routes
                self:ResetCurrentSeasonDungeons(self.CHANGED_ROUTES_DUNGEONS)
                self.db.profile.general.lastVersionCheck = currentVersion
            end,
            OnCancel = function()
                self.db.profile.general.lastVersionCheck = currentVersion
            end,
            timeout = 0,
            whileDead = true,
            hideOnEscape = true,
            preferredIndex = 3,
            showAlert = true,
            title = "Keystone Percentage Helper"
        }
        StaticPopup_Show("KPH_NEW_ROUTES")
    else
        -- Update the version check without prompting
        self.db.profile.general.lastVersionCheck = currentVersion
    end
end

function KeystonePercentageHelper:GetChangedDungeonsText()
    local self = KeystonePercentageHelper
    local changedDungeonsText = ""

    -- Vérifier si la table CHANGED_ROUTES_DUNGEONS existe et n'est pas vide
    if self.CHANGED_ROUTES_DUNGEONS and next(self.CHANGED_ROUTES_DUNGEONS) then
        changedDungeonsText = L["CHANGED_ROUTES_DUNGEONS_LIST"] .. "\n"

        for dungeonKey, _ in pairs(self.CHANGED_ROUTES_DUNGEONS) do
            local displayName = self:GetDungeonDisplayName(dungeonKey) or
                                    dungeonKey
            changedDungeonsText = changedDungeonsText .. "- " .. displayName ..
                                      "\n"
        end
        changedDungeonsText = changedDungeonsText .. "\n"
    end

    return changedDungeonsText
end

function KeystonePercentageHelper:GetDungeonDisplayName(dungeonKey)
    if not dungeonKey then return "Unknown Dungeon" end

    local mapId = self:GetDungeonIdByKey(dungeonKey)

    local name
    if mapId then
        name, _, _, _ = C_ChallengeMode.GetMapUIInfo(mapId)
        return name
    end

    -- Fallback: Try to make the key look presentable
    name = dungeonKey:gsub("_", " ")
    name = name:gsub("(%l)(%u)", "%1 %2") -- Add space between lower and upper case
    name = name:gsub("^%l", string.upper) -- Capitalize first letter
    return name
end

-- Global export function for dungeon settings
function KeystonePercentageHelper:ExportDungeonSettings(dungeonData, exportType,
                                                        sectionName)
    -- Create export string
    local exportData = {
        type = exportType,
        section = sectionName,
        data = dungeonData
    }
    local serialized = LibStub("AceSerializer-3.0"):Serialize(exportData)
    local compressed = LibStub("LibDeflate"):CompressDeflate(serialized)
    local encoded = LibStub("LibDeflate"):EncodeForPrint(compressed)

    -- Determine dialog text based on export type
    local dialogText
    if exportType == "all_dungeons" then
        dialogText = L["EXPORT_ALL_DIALOG_TEXT"]
    elseif exportType == "section" then
        dialogText = (L["EXPORT_SECTION_DIALOG_TEXT"]):format(sectionName)
    else
        dialogText = L["EXPORT_DIALOG_TEXT"]
    end

    -- Show export dialog
    StaticPopupDialogs["KPH_EXPORT_DIALOG"] = {
        text = dialogText,
        button1 = OKAY,
        hasEditBox = true,
        editBoxWidth = 350,
        maxLetters = 999999,
        OnShow = function(dialog)
            dialog.EditBox:SetText(encoded)
            dialog.EditBox:HighlightText()
            dialog.EditBox:SetFocus()
        end,
        EditBoxOnEscapePressed = function(editBox)
            editBox:GetParent():Hide()
        end,
        timeout = 0,
        whileDead = true,
        hideOnEscape = true
    }
    StaticPopup_Show("KPH_EXPORT_DIALOG")
end

-- Global import function for dungeon settings
function KeystonePercentageHelper:ImportDungeonSettings(importString,
                                                        sectionName,
                                                        dungeonFilter)
    local addon = self
    local decoded = LibStub("LibDeflate"):DecodeForPrint(importString)
    if not decoded then
        print("|cffdb6233Keystone Percentage Helper:|r " .. L["IMPORT_ERROR"])
        return false
    end

    local decompressed = LibStub("LibDeflate"):DecompressDeflate(decoded)
    if not decompressed then
        print("|cffdb6233Keystone Percentage Helper:|r " .. L["IMPORT_ERROR"])
        return false
    end

    local success, importData = LibStub("AceSerializer-3.0"):Deserialize(
                                    decompressed)
    if not success then
        print("|cffdb6233Keystone Percentage Helper:|r " .. L["IMPORT_ERROR"])
        return false
    end

    local importCount = 0

    -- Handle different import types
    if importData.type == "all_dungeons" and importData.data then
        -- Import all dungeon data (filtered by dungeonFilter if provided)
        for dungeonKey, dungeonData in pairs(importData.data) do
            if not dungeonFilter or dungeonFilter[dungeonKey] then
                local dungeonId = addon:GetDungeonIdByKey(dungeonKey)
                if dungeonId and addon.DUNGEONS[dungeonId] then
                    if not addon.db.profile.advanced[dungeonKey] then
                        addon.db.profile.advanced[dungeonKey] = {}
                    end
                    for k, v in pairs(dungeonData) do
                        addon.db.profile.advanced[dungeonKey][k] = v
                    end
                    importCount = importCount + 1
                end
            end
        end
    elseif importData.type == "section" and importData.data then
        -- Import section data (filtered by dungeonFilter if provided)
        for dungeonKey, dungeonData in pairs(importData.data) do
            if not dungeonFilter or dungeonFilter[dungeonKey] then
                local dungeonId = addon:GetDungeonIdByKey(dungeonKey)
                if dungeonId and addon.DUNGEONS[dungeonId] then
                    if not addon.db.profile.advanced[dungeonKey] then
                        addon.db.profile.advanced[dungeonKey] = {}
                    end
                    for k, v in pairs(dungeonData) do
                        addon.db.profile.advanced[dungeonKey][k] = v
                    end
                    importCount = importCount + 1
                end
            end
        end
    elseif importData.dungeon then
        -- Handle single dungeon import for backward compatibility
        local dungeonKey = importData.dungeon
        if not dungeonFilter or dungeonFilter[dungeonKey] then
            local dungeonId = addon:GetDungeonIdByKey(dungeonKey)
            if dungeonId and addon.DUNGEONS[dungeonId] then
                if not addon.db.profile.advanced[dungeonKey] then
                    addon.db.profile.advanced[dungeonKey] = {}
                end
                for k, v in pairs(importData.data) do
                    addon.db.profile.advanced[dungeonKey][k] = v
                end
                addon:UpdateDungeonData()
                LibStub("AceConfigRegistry-3.0"):NotifyChange(
                    "KeystonePercentageHelper")
                print("|cffdb6233Keystone Percentage Helper:|r " ..
                          L["IMPORT_SUCCESS"]:format(
                              addon:GetDungeonDisplayName(dungeonKey)))
                return true
            end
        end
        print("|cffdb6233Keystone Percentage Helper:|r " .. L["IMPORT_ERROR"])
        return false
    else
        print("|cffdb6233Keystone Percentage Helper:|r " .. L["IMPORT_ERROR"])
        return false
    end

    -- Update data and notify of changes
    if importCount > 0 then
        addon:UpdateDungeonData()
        LibStub("AceConfigRegistry-3.0"):NotifyChange("KeystonePercentageHelper")

        -- Determine success message based on import type
        if importData.type == "all_dungeons" then
            print("|cffdb6233Keystone Percentage Helper:|r " ..
                      (L["IMPORT_ALL_SUCCESS"]))
        elseif importData.type == "section" then
            print("|cffdb6233Keystone Percentage Helper:|r " ..
                      (L["IMPORT_SUCCESS"]):format(sectionName))
        end
        return true
    else
        print("|cffdb6233Keystone Percentage Helper:|r " .. (L["IMPORT_ERROR"]))
        return false
    end
end

-- Global function to create import dialog
function KeystonePercentageHelper:ShowImportDialog(sectionName, dungeonFilter)
    local addon = self
    local dialogText

    if not sectionName then
        dialogText = L["IMPORT_ALL_DIALOG_TEXT"]
    else
        dialogText = (L["IMPORT_SECTION_DIALOG_TEXT"]):format(sectionName)
    end

    StaticPopupDialogs["KPH_IMPORT_DIALOG"] = {
        text = dialogText,
        button1 = OKAY,
        button2 = CANCEL,
        hasEditBox = true,
        editBoxWidth = 350,
        maxLetters = 999999,
        OnAccept = function(dialog)
            local importString = dialog.EditBox:GetText()
            addon:ImportDungeonSettings(importString, sectionName, dungeonFilter)
        end,
        EditBoxOnEscapePressed = function(editBox)
            editBox:GetParent():Hide()
        end,
        timeout = 0,
        whileDead = true,
        hideOnEscape = true
    }
    StaticPopup_Show("KPH_IMPORT_DIALOG")
end

function KeystonePercentageHelper:GenerateExpansionTables(expansionId,
                                                          dungeonData)
    -- Initialize the tables if they don't exist
    self[expansionId .. "_DUNGEONS"] = self[expansionId .. "_DUNGEONS"] or {}
    self[expansionId .. "_DEFAULTS"] = self[expansionId .. "_DEFAULTS"] or {}
    self[expansionId .. "_DUNGEON_IDS"] =
        self[expansionId .. "_DUNGEON_IDS"] or {}

    -- Clear existing data if any
    wipe(self[expansionId .. "_DUNGEONS"])
    wipe(self[expansionId .. "_DEFAULTS"])
    wipe(self[expansionId .. "_DUNGEON_IDS"])

    for shortName, dungeonData in pairs(dungeonData) do
        -- Generate DUNGEONS table
        local dungeonBosses = {}
        for i, bossData in ipairs(dungeonData.bosses) do
            -- Add haveInformed = false to each boss entry
            dungeonBosses[i] = {bossData[1], bossData[2], bossData[3], false}
        end
        self[expansionId .. "_DUNGEONS"][dungeonData.id] = dungeonBosses

        -- Generate DEFAULTS table
        local defaults = {}
        for i, bossData in ipairs(dungeonData.bosses) do
            local bossNumber = "Boss" .. self:GetBossNumberString(i)
            defaults[bossNumber] = bossData[2]
            defaults[bossNumber .. "Inform"] = bossData[3]
        end
        self[expansionId .. "_DEFAULTS"][shortName] = defaults

        -- Generate DUNGEON_IDS table
        self[expansionId .. "_DUNGEON_IDS"][shortName] = dungeonData.id
    end
end
