local addonName, ns = ...

local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:RegisterEvent("PLAYER_LOGIN")

eventFrame:SetScript("OnEvent", function(self, event, arg1)
    if event == "ADDON_LOADED" and arg1 == addonName then
        if not BlitzFramesTargetsDB then BlitzFramesTargetsDB = {} end
        ns.db = BlitzFramesTargetsDB

        -- Both removed: role assignment is gone, and pairing is keyed on names
        -- rather than an honor-based composite, so there is no sync work left
        -- to survive a /reload. Dropped from saved vars rather than migrated.
        ns.db.roleCache  = nil
        ns.db.honorCache = nil

        -- The Hide Minimap Button option was declared and never built; the
        -- feature is no longer wanted, so the key goes with it. Dropped rather
        -- than migrated -- nothing ever read it.
        ns.db.hideMinimapButton = nil

        -- classArtLegacy (boolean) grew into classArtStyle (legacy | sharp |
        -- polygon). Migrated rather than dropped: a user who chose Blizzard's
        -- icons keeps them.
        if ns.db.classArtLegacy ~= nil then
            if ns.db.classArtStyle == nil and ns.db.classArtLegacy then
                ns.db.classArtStyle = "legacy"
            end
            ns.db.classArtLegacy = nil
        end

        -- One-time migration: flat saved vars → profile-based structure
        if not ns.db.profiles then
            local p = {}
            for k, v in pairs(ns.defaults) do
                local saved = ns.db[k]
                if ns.SHARED_KEYS[k] then
                    -- Keep shared keys at DB root; seed from defaults if missing
                    if saved == nil then
                        ns.db[k] = (type(v) == "table") and ns.DeepCopy(v) or v
                    end
                else
                    p[k] = (saved ~= nil)
                        and ((type(saved) == "table") and ns.DeepCopy(saved) or saved)
                        or  ((type(v)     == "table") and ns.DeepCopy(v)     or v)
                    ns.db[k] = nil
                end
            end
            ns.db.profiles      = { ["Default"] = p }
            ns.db.activeProfile = "Default"
        end

        -- Seed any shared keys added by addon updates
        for k in pairs(ns.SHARED_KEYS) do
            if ns.db[k] == nil and ns.defaults[k] ~= nil then
                local v = ns.defaults[k]
                ns.db[k] = (type(v) == "table") and ns.DeepCopy(v) or v
            end
        end

        -- Migrate *PowerBarMode (string "none"/"healers"/"all") → *PowerBarEnabled
        -- (boolean). "healers" no longer exists as a mode — role assignment was
        -- removed — so anything that wasn't "none" becomes on.
        local powerMigration = {
            normalEnemyPowerBarMode    = "normalEnemyPowerBarEnabled",
            normalFriendlyPowerBarMode = "normalFriendlyPowerBarEnabled",
            epicEnemyPowerBarMode      = "epicEnemyPowerBarEnabled",
            epicFriendlyPowerBarMode   = "epicFriendlyPowerBarEnabled",
        }
        if ns.db.profiles then
            for _, profile in pairs(ns.db.profiles) do
                for oldKey, newKey in pairs(powerMigration) do
                    if profile[oldKey] ~= nil then
                        profile[newKey] = (profile[oldKey] ~= "none")
                        profile[oldKey] = nil
                    end
                end
                -- Range checking was removed entirely, pending a ground-up
                -- rebuild; drop its keys rather than migrate them.
                for _, side in ipairs({ "normalEnemy", "normalFriendly", "epicEnemy", "epicFriendly" }) do
                    profile[side .. "RangeCheckMode"]   = nil
                    profile[side .. "RangeFadeEnabled"] = nil
                    profile[side .. "OutOfRangeAlpha"]  = nil
                end

                -- Removed with role assignment; drop so it can't linger in profiles.
                profile.normalEnemyAssistedSortByRoles    = nil
                profile.normalFriendlyAssistedSortByRoles = nil

                -- *NameDisplayMode → *TextDisplayMode. The old pair showed two
                -- values at once ("nameAndSpec"/"specOnly"); the new one picks
                -- a single source, with the peek key revealing the other.
                for _, side in ipairs({ "normalEnemy", "normalFriendly", "epicEnemy", "epicFriendly" }) do
                    local oldKey = side .. "NameDisplayMode"
                    local old = profile[oldKey]
                    if old ~= nil then
                        profile[side .. "TextDisplayMode"] = (old == "specOnly") and "spec" or "name"
                        profile[oldKey] = nil
                    end
                end
            end
        end

        -- Activate the stored profile, falling back to the first available
        local active = ns.db.activeProfile
        if not active or not ns.db.profiles[active] then
            active = next(ns.db.profiles) or "Default"
        end
        ns.ActivateProfile(active)

        -- After activation, so a profile is guaranteed to exist and to have been
        -- topped up from ns.defaults first. Pruning before that would race the
        -- fill-in and could drop a key that was about to be restored.
        ns.PruneStaleKeys()

        self:UnregisterEvent("ADDON_LOADED")

    elseif event == "PLAYER_LOGIN" then
        ns.settingsPanel = ns.CreateSettingsPanel()
        -- Not stored: nothing reads it. The button parents itself to Minimap
        -- and manages its own angle, so it needs no owner.
        ns.CreateMinimapButton()
        self:UnregisterEvent("PLAYER_LOGIN")
    end
end)

-- Key binding support. Bindings.xml lives at the addon root and is loaded
-- automatically (it is NOT listed in the .toc). Its script runs in the global
-- environment, so both the handler and the Key Bindings panel display names
-- have to be globals.
BINDING_HEADER_BLITZFRAMESTARGETS     = "BlitzFramesTargets"
BINDING_NAME_BLITZFRAMESTARGETS_PEEK  = "Peek (hold to swap bar text)"

function BlitzFramesTargets_SetPeek(down)
    if ns.SetPeek then ns.SetPeek(down) end
end

SLASH_BLITZFRAMESTARGETS1 = "/bft"
SLASH_BLITZFRAMESTARGETS2 = "/blitzframestargets"
SlashCmdList["BLITZFRAMESTARGETS"] = function(msg)
    -- /bft layout -- prints where the tab rows actually are. See
    -- ns.DebugTabLayout: measure, do not model.
    -- /bft flag -- toggle the flag-clock trace and dump its state.
    if msg and msg:lower():match("^%s*flag%s*$") then
        if ns.DebugFlag then ns.DebugFlag() end
        return
    end

    -- /bft watch [name] -- per-tick trace of one enemy's tracker entry.
    local wname = msg and msg:lower():match("^%s*watch%s*(.-)%s*$")
    if wname then
        if ns.DebugWatch then ns.DebugWatch(wname) end
        return
    end

    -- /bft state -- dump what the intro decision is seeing. See ns.DebugState.
    if msg and msg:lower():match("^%s*state%s*$") then
        if ns.DebugState then ns.DebugState() end
        return
    end

    -- /bft reveal [name] [CLASS] -- see the stealth reveal without waiting for
    -- its real trigger, which is narrow enough to look broken. See
    -- ns.DebugFireReveal.
    local rname, rclass = msg and msg:lower():match("^%s*reveal%s*(%S*)%s*(%S*)%s*$")
    if rname then
        if ns.DebugFireReveal then
            ns.DebugFireReveal(rname ~= "" and rname or nil,
                               rclass ~= "" and rclass:upper() or nil)
        end
        return
    end
    if msg and msg:lower():match("^%s*layout%s*$") then
        if ns.DebugTabLayout then ns.DebugTabLayout() end
        return
    end
    if InCombatLockdown() then
        print("|cffff0000BlitzFramesTargets:|r Cannot open settings in combat.")
        return
    end
    ns.ToggleSettingsPanel()
end
