local addonName, ZL = ...

_G.ZoneLocked = ZL
_G.ZL = ZL
ZL.frame = CreateFrame("Frame")

local defaults = {
    schemaVersion = 5,
    route = {},
    collectedItems = {},
    settings = {
        blackout = true,
        alerts = true,
        mapOverlay = true,
        theme = "gilded",
        categories = {
            achievements = true,
            decor = true,
            instances = true,
            quests = true,
            mounts = true,
            pets = true,
            transmogs = true,
            rares = true,
        },
        filters = {
            view = "all",
            sort = "default",
            search = "",
            transmogSource = "all",
        },
        expansions = {
            vanilla = true,
            tbc = true,
            wrath = true,
            cataclysm = true,
            mists = true,
            warlords = true,
            legion = true,
            bfa = true,
            shadowlands = true,
            dragonflight = true,
            warwithin = true,
        },
        minilist = {
            enabled = true,
            maxItems = 6,
            showMissing = true,
            categories = {
                achievements = true,
                decor = true,
                instances = true,
                mounts = true,
                pets = true,
                quests = true,
                rares = true,
                transmogs = true,
            },
        },
        history = {
            enabled = true,
            filter = "all",
            search = "",
            categories = {
                achievements = true,
                decor = true,
                journeys = true,
                mounts = true,
                pets = true,
                quests = true,
                rares = true,
                transmogs = true,
                zones = true,
            },
        },
    },
    ui = {
        collapsed = {},
        historyCollapsed = { recent = false, journeys = false },
        minilist = { point = "RIGHT", relativePoint = "RIGHT", x = -40, y = 0, width = 370, height = 540,
            compact = false, compactWidth = 300, compactHeight = 92 },
        alert = { point = "TOP", relativePoint = "TOP", x = 0, y = -170 },
        minimap = { minimapPos = 210, hide = false },
    },
    rolledZones = {},
    history = {},
    historyKnown = {},
    historyEventKeys = {},
    completedZones = {},
    zoneSummaries = {},
    journeys = {},
    journeyArchiveKeys = {},
    currentJourneyStartIndex = 1,
}

ZL.ThemeDefinitions = {
    gilded = {
        name = "Gilded Journal", description = "Obsidian, brass, and explorer-blue accents.",
        window = { 0.035, 0.045, 0.052, 0.99 }, header = { 0.025, 0.075, 0.105, 0.98 },
        panel = { 0.025, 0.040, 0.050, 0.96 }, border = { 0.82, 0.68, 0.34, 0.95 },
        accent = { 0.92, 0.70, 0.25, 0.95 }, secondary = { 0.40, 0.82, 1.00, 1 },
    },
    parchment = {
        name = "Explorer's Parchment", description = "Warm walnut, parchment, and antique bronze.",
        window = { 0.090, 0.060, 0.035, 0.99 }, header = { 0.145, 0.085, 0.040, 0.98 },
        panel = { 0.105, 0.072, 0.040, 0.97 }, border = { 0.70, 0.46, 0.20, 0.98 },
        accent = { 0.95, 0.62, 0.20, 0.98 }, secondary = { 0.94, 0.82, 0.60, 1 },
    },
    arcane = {
        name = "Arcane Ledger", description = "Deep indigo, violet trim, and luminous cyan.",
        window = { 0.025, 0.025, 0.075, 0.99 }, header = { 0.045, 0.045, 0.145, 0.98 },
        panel = { 0.035, 0.040, 0.105, 0.97 }, border = { 0.42, 0.35, 0.82, 0.98 },
        accent = { 0.58, 0.40, 1.00, 0.98 }, secondary = { 0.30, 0.88, 1.00, 1 },
    },
    emerald = {
        name = "Emerald Expedition", description = "Forest green, weathered gold, and jade highlights.",
        window = { 0.025, 0.065, 0.045, 0.99 }, header = { 0.035, 0.125, 0.075, 0.98 },
        panel = { 0.035, 0.090, 0.060, 0.97 }, border = { 0.30, 0.64, 0.38, 0.98 },
        accent = { 0.82, 0.66, 0.24, 0.98 }, secondary = { 0.30, 0.92, 0.58, 1 },
    },
    crimson = {
        name = "Crimson Chronicle", description = "Burgundy leather, ember-red trim, and warm ivory.",
        window = { 0.075, 0.025, 0.028, 0.99 }, header = { 0.145, 0.035, 0.040, 0.98 },
        panel = { 0.105, 0.035, 0.040, 0.97 }, border = { 0.72, 0.26, 0.24, 0.98 },
        accent = { 0.95, 0.34, 0.22, 0.98 }, secondary = { 0.96, 0.84, 0.62, 1 },
    },
    frost = {
        name = "Frostbound Atlas", description = "Glacial blue, silver trim, and crisp white-blue light.",
        window = { 0.025, 0.055, 0.075, 0.99 }, header = { 0.035, 0.105, 0.145, 0.98 },
        panel = { 0.040, 0.080, 0.105, 0.97 }, border = { 0.45, 0.70, 0.82, 0.98 },
        accent = { 0.48, 0.82, 1.00, 0.98 }, secondary = { 0.82, 0.94, 1.00, 1 },
    },
    midnight = {
        name = "Midnight Cartographer", description = "Near-black navy, moonlit steel, and royal blue.",
        window = { 0.012, 0.020, 0.038, 0.99 }, header = { 0.020, 0.040, 0.085, 0.98 },
        panel = { 0.020, 0.032, 0.060, 0.97 }, border = { 0.25, 0.38, 0.62, 0.98 },
        accent = { 0.25, 0.48, 0.95, 0.98 }, secondary = { 0.52, 0.72, 1.00, 1 },
    },
    rosewood = {
        name = "Rosewood Reliquary", description = "Rosewood, muted copper, and soft magenta accents.",
        window = { 0.070, 0.035, 0.050, 0.99 }, header = { 0.120, 0.050, 0.075, 0.98 },
        panel = { 0.095, 0.045, 0.065, 0.97 }, border = { 0.68, 0.36, 0.42, 0.98 },
        accent = { 0.86, 0.46, 0.42, 0.98 }, secondary = { 0.94, 0.54, 0.78, 1 },
    },
    monochrome = {
        name = "Monochrome Archivist", description = "Charcoal, polished steel, and restrained white accents.",
        window = { 0.035, 0.038, 0.042, 0.99 }, header = { 0.065, 0.070, 0.078, 0.98 },
        panel = { 0.050, 0.054, 0.060, 0.97 }, border = { 0.48, 0.52, 0.58, 0.98 },
        accent = { 0.72, 0.76, 0.82, 0.98 }, secondary = { 0.92, 0.94, 0.98, 1 },
    },
}

function ZL:GetTheme()
    return self.ThemeDefinitions[(ZL_Saved and ZL_Saved.settings and ZL_Saved.settings.theme) or "gilded"] or
        self.ThemeDefinitions.gilded
end

-- Settings and window positions are shared by the account. The route,
-- collection baseline, history and archived journeys belong to one character.
-- ZL_Saved remains a compatibility facade so the rest of the addon can access
-- both stores without accidentally turning character progress account-wide.
local accountKeys = { schemaVersion = true, settings = true, ui = true }

local function CopyDefaults(source, target)
    for key, value in pairs(source) do
        if type(value) == "table" then
            target[key] = type(target[key]) == "table" and target[key] or {}
            CopyDefaults(value, target[key])
        elseif target[key] == nil then
            target[key] = value
        end
    end
end

local function CopyTable(source)
    if type(source) ~= "table" then return source end
    local result = {}
    for key, value in pairs(source) do result[key] = CopyTable(value) end
    return result
end

local function CreateSavedFacade()
    return setmetatable({}, {
        __index = function(_, key)
            return accountKeys[key] and ZL_Account[key] or ZL_Character[key]
        end,
        __newindex = function(_, key, value)
            if accountKeys[key] then ZL_Account[key] = value else ZL_Character[key] = value end
        end,
    })
end

function ZL:Print(message)
    DEFAULT_CHAT_FRAME:AddMessage("|cff65d1ffZone Locked:|r " .. tostring(message))
end

function ZL:Init()
    local legacy = type(ZL_Saved) == "table" and ZL_Saved or nil
    ZL_Account = type(ZL_Account) == "table" and ZL_Account or {}
    ZL_Character = type(ZL_Character) == "table" and ZL_Character or {}

    -- The first character loaded by this version claims the old account-wide
    -- journey. Other characters begin with an independent, clean challenge.
    if not ZL_Account.legacyCharacterClaimed and legacy and
        (legacy.route or legacy.history or legacy.settings) then
        if legacy.settings then ZL_Account.settings = CopyTable(legacy.settings) end
        if legacy.ui then ZL_Account.ui = CopyTable(legacy.ui) end
        if legacy.schemaVersion then ZL_Account.schemaVersion = legacy.schemaVersion end
        for key, value in pairs(legacy) do
            if not accountKeys[key] then ZL_Character[key] = CopyTable(value) end
        end
        ZL_Account.legacyCharacterClaimed = UnitGUID("player") or true
    end

    ZL_Saved = CreateSavedFacade()
    local previousSchema = tonumber(ZL_Saved.schemaVersion) or 0
    local previousMinimapAngle = ZL_Saved.ui and ZL_Saved.ui.minimap and ZL_Saved.ui.minimap.angle
    CopyDefaults(defaults, ZL_Saved)
    if previousSchema < 3 then
        for _, expansion in ipairs(self.Expansions or {}) do
            ZL_Saved.settings.expansions[expansion.key] = true
        end
        -- Older builds could leave removed roll results in this secondary
        -- index, permanently excluding them from future candidate pools.
        ZL_Saved.rolledZones = {}
        for _, mapID in ipairs(ZL_Saved.route or {}) do ZL_Saved.rolledZones[mapID] = true end
        ZL_Saved.transition = nil
    end
    if previousSchema < 4 and previousMinimapAngle then
        ZL_Saved.ui.minimap.minimapPos = previousMinimapAngle
    end
    ZL_Saved.ui.minimap.angle = nil
    ZL_Saved.schemaVersion = 5
    ZL_Character.characterVersion = 1
    if #(ZL_Saved.history or {}) == 0 then ZL_Saved.historyEventKeys = {} end
    if self.RepairHistoryData then self:RepairHistoryData() end
    -- Keep diagnostics available even if a visual component fails to build.
    self:RefreshExpansionMaps()
    self:RegisterSlashCommands()
    self:CreateSettingsPanel()
    self:CreateMainWindow()
    self:CreateMinimapButton()
    self:CreateWowheadDialog()
    self:CreateRollFrame()
    self:CreateMiniList()
    self:CreateLockOverlay()
    self:CreateCollectionAlert()
    self:CreateWorldMapOverlay()
    self:InitATTProvider()
    self:ScanAllRouteZones()
    self:ApplyTheme()
    self:CheckZoneState()
    self:RefreshMiniList()
end

ZL.frame:RegisterEvent("ADDON_LOADED")
ZL.frame:SetScript("OnEvent", function(_, event, loadedAddon)
    if event == "ADDON_LOADED" and loadedAddon == addonName then
        ZL:Init()
    end
end)
