local addonName, ns = ...

local C_Timer = C_Timer
local floor = math.floor

-- SavedVariables defaults kept in a separate table (validated on load).
ns.defaults = {
    useAuto = true,     -- follow the current spec's stat priority automatically
    shown = {},         -- key -> true; only used when useAuto is false
    showLegend = true,  -- draw the legend under the ring
    showChrome = true,  -- panel background and border
    embed = false,      -- true = integrated as a character-frame sidebar tab
    freeMove = false,   -- false = anchored to the character window
    panelWidth = nil,   -- nil = default width
    pos = nil,          -- { point, relPoint, x, y } relative to UIParent
    theme = "auto",     -- "auto" | "classic" | "elvui" | "metal"
    chartLayout = "circle", -- "circle" | "bar"
}

-- Allowed panel themes (validated on load).
ns.THEMES = { auto = true, classic = true, elvui = true, metal = true }

-- Allowed chart layouts (validated on load).
ns.CHART_LAYOUTS = { circle = true, bar = true }

-- Validates loaded SavedVariables, filling in any missing/invalid fields.
local function ValidateDB()
    -- One-time migrate from the former addon name if present.
    if type(StatOrbDB) ~= "table" then
        if type(iStatsDB) == "table" then
            StatOrbDB = iStatsDB
        else
            StatOrbDB = {}
        end
    end
    local db = StatOrbDB
    local d = ns.defaults

    if type(db.useAuto) ~= "boolean" then db.useAuto = d.useAuto end
    if type(db.showLegend) ~= "boolean" then db.showLegend = d.showLegend end
    if type(db.showChrome) ~= "boolean" then db.showChrome = d.showChrome end
    if type(db.embed) ~= "boolean" then db.embed = d.embed end

    if type(db.theme) ~= "string" or not ns.THEMES[db.theme] then
        if db.theme == "book" then
            db.theme = "metal"
        else
            db.theme = d.theme
        end
    end

    if type(db.chartLayout) ~= "string" or not ns.CHART_LAYOUTS[db.chartLayout] then
        db.chartLayout = d.chartLayout
    end

    if type(db.freeMove) ~= "boolean" then
        db.freeMove = db.pos ~= nil and true or d.freeMove
    end

    if type(db.panelWidth) == "number" and db.panelWidth > 0 then
        local pw = floor(db.panelWidth + 0.5)
        if pw >= 228 and pw <= 500 then
            db.panelWidth = pw
        else
            db.panelWidth = nil
        end
    else
        db.panelWidth = nil
    end

    if type(db.shown) ~= "table" then
        db.shown = {}
    else
        -- Drop unknown keys so corrupt data cannot leak into the chart.
        for key in pairs(db.shown) do
            if not ns.STAT_BY_KEY[key] then
                db.shown[key] = nil
            end
        end
    end

    if type(db.pos) == "table" then
        local p = db.pos
        if type(p.point) ~= "string" or type(p.relPoint) ~= "string"
            or type(p.x) ~= "number" or type(p.y) ~= "number" then
            db.pos = nil
        end
    else
        db.pos = nil
    end

    ns.db = db
end

-- Single event frame for the whole addon (dispatch table).
local eventFrame = CreateFrame("Frame")
local handlers = {}

handlers.ADDON_LOADED = function(loaded)
    if loaded ~= addonName then return end
    ValidateDB()
    eventFrame:UnregisterEvent("ADDON_LOADED")
end

handlers.PLAYER_LOGIN = function()
    if ns.Chart and ns.Chart.Init then
        ns.Chart:Init()
    end
    if ns.Integration and ns.Integration.ApplyMode then
        ns.Integration:ApplyMode()
    end
end

-- Throttled refresh so bursty stat events do not rebuild the chart repeatedly.
local refreshPending = false
local function RequestRefresh()
    if refreshPending then return end
    refreshPending = true
    C_Timer.After(0.1, function()
        refreshPending = false
        if ns.Chart and ns.Chart.Refresh then
            ns.Chart:Refresh()
        end
    end)
end
ns.RequestRefresh = RequestRefresh

local statEvents = {
    "PLAYER_EQUIPMENT_CHANGED",
    "COMBAT_RATING_UPDATE",
    "PLAYER_SPECIALIZATION_CHANGED",
    "ACTIVE_TALENT_GROUP_CHANGED",
    "UNIT_STATS",
}
for _, event in ipairs(statEvents) do
    handlers[event] = function()
        -- Only rebuild while the chart is actually visible.
        if ns.Chart and ns.Chart.IsShown and ns.Chart:IsShown() then
            RequestRefresh()
        end
    end
end

eventFrame:SetScript("OnEvent", function(_, event, ...)
    local handler = handlers[event]
    if handler then
        handler(...)
    end
end)

eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:RegisterEvent("PLAYER_LOGIN")
for _, event in ipairs(statEvents) do
    eventFrame:RegisterEvent(event)
end
