local addonName, addon = ...

addon.name = addonName
addon.version = 120001
addon.isInitialized = false
addon.debug = false

addon.MODE_BINDINGS = "BINDINGS"

local function debugPrint(msg)
    if addon.debug then
        print("|cFF00FF00[MountBinder]|r " .. tostring(msg))
    end
end

addon.Debug = debugPrint

local function copyActionRef(actionRef)
    if type(actionRef) ~= "table" then
        return nil
    end
    local copy = {}
    for k, v in pairs(actionRef) do
        if type(v) == "table" then
            local t = {}
            for tk, tv in pairs(v) do
                t[tk] = tv
            end
            copy[k] = t
        else
            copy[k] = v
        end
    end
    return copy
end

local function getSpellNameSafe(spellID)
    if type(spellID) ~= "number" or spellID <= 0 then
        return nil
    end
    if C_Spell and C_Spell.GetSpellName then
        return C_Spell.GetSpellName(spellID)
    end
    if type(GetSpellInfo) == "function" then
        return GetSpellInfo(spellID)
    end
    return nil
end

local function defaultGlobalDB()
    return {
        version = addon.version,
        mode = addon.MODE_BINDINGS,
        bindings = {
            key = nil,
            usePressAndHold = false,
            holdThresholdMs = 150,
        },
        indicator = {
            enabled = false,
            scale = 1.0,
            locked = false,
        },
        library = {},
    }
end

local function defaultCharDB()
    return {
        version = addon.version,
        bindings = {
            advancedModifiers = true,
            slots = {},
        },
        indicator = {
            point = "CENTER",
            relativePoint = "CENTER",
            x = 0,
            y = -140,
        },
    }
end

local function ensureTable(tbl, key, fallback)
    if type(tbl[key]) ~= "table" then
        tbl[key] = fallback
    end
    return tbl[key]
end

function addon:MigrateLegacyData()
    if type(MountBinderDB) ~= "table" then
        return
    end

    local playerName = UnitName("player")
    local realmName = GetRealmName()
    local fullName = (playerName or "") .. "-" .. (realmName or "")
    local legacy = MountBinderDB[fullName]
    if type(legacy) ~= "table" then
        return
    end

    local slotOrder = {
        "NONE",
        "SHIFT",
        "CTRL",
        "ALT",
        "SHIFT_CTRL",
        "SHIFT_ALT",
        "CTRL_ALT",
        "SHIFT_CTRL_ALT",
    }

    if type(legacy.mounts) == "table" then
        for i, mountID in ipairs(legacy.mounts) do
            local slotKey = slotOrder[i]
            if slotKey and mountID and not addon.charDB.bindings.slots[slotKey] then
                local actionRef
                if mountID < 0 then
                    local spellID = -mountID
                    local spellName = getSpellNameSafe(spellID)
                    actionRef = {
                        type = "SPELL",
                        id = spellID,
                        name = spellName or ("Spell " .. spellID),
                        icon = C_Spell and C_Spell.GetSpellTexture and C_Spell.GetSpellTexture(spellID) or nil,
                    }
                else
                    local name, spellID, icon = C_MountJournal.GetMountInfoByID(mountID)
                    actionRef = {
                        type = "MOUNT",
                        id = mountID,
                        name = name or ("Mount " .. mountID),
                        icon = icon,
                        payload = { spellID = spellID },
                    }
                end
                addon.charDB.bindings.slots[slotKey] = actionRef
            end
        end
    end

    if type(legacy.advancedMode) == "boolean" then
        addon.charDB.bindings.advancedModifiers = legacy.advancedMode
    end
end

function addon:RunMigrations()
    if type(self.globalDB.version) ~= "number" or self.globalDB.version < self.version then
        self.globalDB.version = self.version
    end
    if type(self.charDB.version) ~= "number" or self.charDB.version < self.version then
        self.charDB.version = self.version
    end

    if self.globalDB.keybind and not self.globalDB.bindings.key then
        self.globalDB.bindings.key = self.globalDB.keybind
        self.globalDB.keybind = nil
    end
    self:MigrateLegacyData()
end

function addon:InitDatabases()
    MountBinderGlobalDB = MountBinderGlobalDB or defaultGlobalDB()
    MountBinderCharDB = MountBinderCharDB or defaultCharDB()
    self.globalDB = MountBinderGlobalDB
    self.charDB = MountBinderCharDB

    local g = self.globalDB
    local c = self.charDB

    g.version = g.version or self.version
    g.mode = g.mode or self.MODE_BINDINGS
    g.bindings = ensureTable(g, "bindings", defaultGlobalDB().bindings)
    g.bindings.usePressAndHold = g.bindings.usePressAndHold == true
    g.bindings.holdThresholdMs = tonumber(g.bindings.holdThresholdMs) or 150
    g.indicator = ensureTable(g, "indicator", defaultGlobalDB().indicator)
    g.indicator.enabled = g.indicator.enabled == true
    g.indicator.locked = g.indicator.locked == true
    g.indicator.scale = tonumber(g.indicator.scale) or 1.0
    g.library = ensureTable(g, "library", {})

    c.version = c.version or self.version
    c.bindings = ensureTable(c, "bindings", defaultCharDB().bindings)
    c.bindings.slots = c.bindings.slots or {}
    c.bindings.advancedModifiers = true
    c.indicator = ensureTable(c, "indicator", defaultCharDB().indicator)
    c.indicator.point = c.indicator.point or "CENTER"
    c.indicator.relativePoint = c.indicator.relativePoint or "CENTER"
    c.indicator.x = tonumber(c.indicator.x) or 0
    c.indicator.y = tonumber(c.indicator.y) or -140
    self:RunMigrations()
end

function addon:GetMode()
    return self.globalDB and self.globalDB.mode or self.MODE_BINDINGS
end

function addon:SetMode(mode)
    if mode ~= self.MODE_BINDINGS then
        return
    end
    self.globalDB.mode = mode
    if self.Bindings then
        self.Bindings:ApplyActiveBinding()
    end
end

function addon:GetBindingSlotAction(slotKey)
    return copyActionRef(self.charDB.bindings.slots[slotKey])
end

function addon:SetBindingSlotAction(slotKey, actionRef)
    self.charDB.bindings.slots[slotKey] = copyActionRef(actionRef)
    if self.Bindings and self.Bindings.RefreshSlotButton then
        self.Bindings:RefreshSlotButton(slotKey)
    end
end

function addon:InitializeModules()
    if self.Actions and self.Actions.Initialize then
        self.Actions:Initialize()
    end
    if self.Bindings and self.Bindings.Initialize then
        self.Bindings:Initialize()
    end
    if self.Indicator and self.Indicator.Initialize then
        self.Indicator:Initialize()
    end
    if self.Settings and self.Settings.Initialize then
        self.Settings:Initialize()
    end
end

local function onEvent(_, event, arg1)
    if event == "ADDON_LOADED" and arg1 == addonName then
        if addon.isInitialized then
            return
        end
        addon:InitDatabases()
        addon:InitializeModules()
        addon.isInitialized = true
        debugPrint("Initialized")
    end
end

local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:SetScript("OnEvent", onEvent)

SLASH_MOUNTBINDER1 = "/mountbinder"
SlashCmdList.MOUNTBINDER = function(msg)
    if msg == "debug" then
        addon.debug = not addon.debug
        print("MountBinder debug: " .. (addon.debug and "ON" or "OFF"))
        return
    end
    if addon.Settings and addon.Settings.OpenCategory then
        addon.Settings:OpenCategory()
    end
end
