-- ============================================================================
-- Vamoose's Companion - Init
-- Addon initialization, lifecycle, and slash commands
-- ============================================================================

VC = VC or {}
_G.VamoosesCompanion = VC

VC.frame = CreateFrame("Frame")
VC.frame:RegisterEvent("ADDON_LOADED")
VC.frame:RegisterEvent("PLAYER_LOGIN")
VC.frame:RegisterEvent("PLAYER_LOGOUT")

-- ============================================================================
-- LIFECYCLE
-- ============================================================================

function VC:OnInitialize()
    VC_DB = VC_DB or {}
    VC.Store:LoadFromSavedVariables()
    VC.Constants:ApplyTheme()

    if VC.Theme and VC.Theme.Initialize then
        VC.Theme:Initialize()
    end

    local version = C_AddOns.GetAddOnMetadata("VamoosesCompanion", "Version") or "Dev"
    print("|cFFA0522D[VC]|r Vamoose's Companion v" .. version .. " loaded. Type /vc for help.")
end

function VC:OnEnable()
    VC._sessionStart = GetTime()
    VC.EventBus:Trigger("VC_ADDON_ENABLED")

    -- Initialize modules
    if VC.Collectors and VC.Collectors.Initialize then
        VC.Collectors:Initialize()
    end
    if VC.Memory and VC.Memory.Initialize then
        VC.Memory:Initialize()
    end
    if VC.Engine and VC.Engine.Initialize then
        VC.Engine:Initialize()
    end
    if VC.Mood and VC.Mood.Initialize then
        VC.Mood:Initialize()
    end
    if VC.Bonding and VC.Bonding.Initialize then
        VC.Bonding:Initialize()
    end

    -- Initialize UI
    if VC.Display and VC.Display.Initialize then
        VC.Display:Initialize()
    end
    if VC.Portrait and VC.Portrait.Initialize then
        VC.Portrait:Initialize()
    end
    if VC.Settings and VC.Settings.Initialize then
        VC.Settings:Initialize()
    end
    if VC.Mascot and VC.Mascot.Initialize then
        VC.Mascot:Initialize()
    end
end

-- Event Handler
VC.frame:SetScript("OnEvent", function(self, event, arg1)
    if event == "ADDON_LOADED" and arg1 == "VamoosesCompanion" then
        VC:OnInitialize()
        self:UnregisterEvent("ADDON_LOADED")
    elseif event == "PLAYER_LOGIN" then
        self:UnregisterEvent("PLAYER_LOGIN")
        C_Timer.After(5, function() VC:OnEnable() end)
    elseif event == "PLAYER_LOGOUT" then
        VC.Store:Flush()
    end
end)

-- ============================================================================
-- SLASH COMMANDS
-- ============================================================================

SLASH_VC1 = "/vc"
SLASH_VC2 = "/companion"
SlashCmdList["VC"] = function(msg)
    local command = msg:lower():match("^(%S*)")
    local arg = msg:lower():match("^%S+%s+(.*)")

    if command == "" or command == "help" then
        print("|cFFA0522D[VC]|r Commands:")
        print("  /vc mute - Toggle mute")
        print("  /vc chattiness [1-4] - Set chattiness (1=minimal, 4=maximum)")
        print("  /vc mode [bubble|chat] - Display mode")
        print("  /vc toggle <type> - Toggle event type (farming/gold/achieve/death/ambient/quest/boss/levelup/rep/zone/login)")
        print("  /vc test [type] - Force a test quote")
        print("  /vc status - Show current settings")
        print("  /vc companion <name> - Switch companion (vamoose/scurry/gazlowe/patches)")
        print("  /vc portrait - Toggle portrait")
        print("  /vc reset - Reset portrait position")
        print("  /vc mood - Show current mood")
        print("  /vc bond - Show bonding level")
        print("  /vc settings - Open settings panel")
        print("  /vc theme - Cycle themes")
        print("  /vc debug - Toggle debug mode")

    elseif command == "settings" then
        if VC.Settings and VC.Settings.Toggle then
            VC.Settings:Toggle()
        end

    elseif command == "mute" then
        local state = VC.Store:GetState()
        local newMuted = not state.config.muted
        VC.Store:Dispatch("SET_MUTED", { muted = newMuted })
        print("|cFFA0522D[VC]|r " .. (newMuted and "Muted" or "Unmuted"))

    elseif command == "chattiness" then
        local level = tonumber(arg)
        if level and level >= 1 and level <= 4 then
            VC.Store:Dispatch("SET_CHATTINESS", { level = level })
            local tier = VC.Constants.CHATTINESS[level]
            print("|cFFA0522D[VC]|r Chattiness: " .. tier.label)
        else
            local current = VC.Store:GetState().config.chattiness
            print("|cFFA0522D[VC]|r Chattiness: " .. VC.Constants.CHATTINESS[current].label .. " (" .. current .. "/4)")
            print("  Usage: /vc chattiness <1-4>")
        end

    elseif command == "mode" then
        if arg == "bubble" or arg == "chat" then
            VC.Store:Dispatch("TOGGLE_DISPLAY_MODE", { mode = arg })
            local modes = VC.Store:GetState().config.displayModes
            print("|cFFA0522D[VC]|r Mode " .. arg .. ": " .. (modes[arg] and "ON" or "OFF"))
        else
            local modes = VC.Store:GetState().config.displayModes or {}
            local active = {}
            if modes.bubble then active[#active + 1] = "bubble" end
            if modes.chat then active[#active + 1] = "chat" end
            print("|cFFA0522D[VC]|r Display modes: " .. (#active > 0 and table.concat(active, " + ") or "none"))
            print("  Usage: /vc mode [bubble|chat]")
        end

    elseif command == "toggle" then
        if arg and VC.Constants.CATEGORY_COOLDOWNS[arg] then
            local state = VC.Store:GetState()
            local current = state.config.eventToggles[arg]
            VC.Store:Dispatch("SET_EVENT_TOGGLE", { eventType = arg, enabled = not current })
            print("|cFFA0522D[VC]|r " .. arg .. " quotes: " .. (not current and "ON" or "OFF"))
        else
            print("|cFFA0522D[VC]|r Usage: /vc toggle <farming|gold|achieve|death|ambient>")
        end

    elseif command == "test" then
        local eventType = arg or "ambient"
        if VC.Engine and VC.Engine.ProcessEvent then
            VC.Engine:ProcessEvent({
                eventType = eventType,
                intensity = VC.Constants.INTENSITY.HIGH,
                context = {},
                timestamp = GetTime(),
                source = "SLASH_TEST",
            })
        else
            print("|cFFA0522D[VC]|r Engine not loaded")
        end

    elseif command == "status" then
        local s = VC.Store:GetState()
        local tier = VC.Constants.CHATTINESS[s.config.chattiness]
        local comp = VC_CompanionProfiles and VC_CompanionProfiles[s.config.activeCompanion]
        local dm = s.config.displayModes or {}
        local dmParts = {}
        if dm.bubble then dmParts[#dmParts + 1] = "bubble" end
        if dm.chat then dmParts[#dmParts + 1] = "chat" end
        local bondInfo = VC.Bonding and VC.Bonding:GetLevelInfo() or {}
        local moodStr = VC.Mood and VC.Mood:GetMood() or "N/A"

        print("|cFFA0522D[VC]|r Status:")
        print(format("  Companion: %s | %s | %s | History: %d/%d",
            comp and comp.name or s.config.activeCompanion,
            s.config.muted and "MUTED" or tier.label,
            #dmParts > 0 and table.concat(dmParts, "+") or "none",
            #s.quoteHistory, VC.Constants.HISTORY_MAX))
        print(format("  Mood: %s | Bond: %s (%d) | Streak: %dd",
            moodStr, bondInfo.name or "?", bondInfo.rapport or 0, bondInfo.streakDays or 0))

        -- Lifetime counts
        local c = s.memory and s.memory.lifetimeCounts or {}
        print(format("  Counts: %d boss, %d death, %d quest, %d achieve, %d M+",
            c.bossKills or 0, c.deaths or 0, c.questsCompleted or 0,
            c.achievementsEarned or 0, c.mythicPlusCompleted or 0))
        print(format("          %d fish, %d crits, %d zones, %d sessions, %sg earned",
            c.fishCaught or 0, c.craftingCrits or 0, c.zonesVisited or 0,
            c.sessionCount or 0,
            c.goldEarned and format("%.1fk", c.goldEarned / 10000) or "0"))

        -- Milestones fired
        local fired = s.memory and s.memory.milestonesFired or {}
        local streakFired = s.memory and s.memory.streakMilestonesFired or {}
        local msList = {}
        for k in pairs(fired) do msList[#msList + 1] = k end
        for k in pairs(streakFired) do msList[#msList + 1] = k end
        if #msList > 0 then
            table.sort(msList)
            print("  Milestones: " .. table.concat(msList, ", "))
        end

        -- Event toggles (compact: only show OFF ones)
        local off = {}
        for k, v in pairs(s.config.eventToggles) do
            if not v then off[#off + 1] = k end
        end
        if #off > 0 then
            table.sort(off)
            print("  Disabled: " .. table.concat(off, ", "))
        end

    elseif command == "companion" then
        if arg and VC_CompanionProfiles and VC_CompanionProfiles[arg] and VC_QuoteDB and VC_QuoteDB[arg] then
            VC.Store:Dispatch("SET_CONFIG", { key = "activeCompanion", value = arg })
            if VC.Portrait and VC.Portrait.UpdateModel then
                VC.Portrait:UpdateModel()
            end
            local profile = VC_CompanionProfiles[arg]
            print("|cFFA0522D[VC]|r Companion: " .. profile.name .. " - " .. profile.title)
        else
            local current = VC.Store:GetState().config.activeCompanion
            local names = {}
            for k in pairs(VC_CompanionProfiles or {}) do
                if VC_QuoteDB and VC_QuoteDB[k] then table.insert(names, k) end
            end
            print("|cFFA0522D[VC]|r Companion: " .. current)
            print("  Available: " .. table.concat(names, ", "))
        end

    elseif command == "portrait" then
        local s = VC.Store:GetState()
        local newShown = not s.ui.portraitShown
        VC.Store:Dispatch("SET_PORTRAIT_SHOWN", { shown = newShown })
        if VC.Portrait and VC.Portrait.frame then
            VC.Portrait.frame:SetShown(newShown)
        end
        print("|cFFA0522D[VC]|r Portrait " .. (newShown and "shown" or "hidden"))

    elseif command == "reset" then
        VC_DB = {}
        VC.Store:ResetToDefaults()
        if VC.Portrait and VC.Portrait.frame then
            VC.Portrait.frame:ClearAllPoints()
            VC.Portrait.frame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 20, -200)
            VC.Portrait:UpdateModel(true)
        end
        print("|cFFA0522D[VC]|r All saved variables reset. /reload recommended.")

    elseif command == "theme" then
        local newTheme = VC.Constants:ToggleTheme()
        local displayName = VC.Constants.ThemeDisplayNames[newTheme] or newTheme
        VC.EventBus:Trigger("VC_THEME_UPDATE", {
            themeName = VC.Constants.ThemeNames[newTheme]
        })
        print("|cFFA0522D[VC]|r Theme: " .. displayName)

    elseif command == "mood" then
        local mood = VC.Mood and VC.Mood:GetMood() or "N/A"
        local intensity = VC.Mood and VC.Mood:GetIntensity() or 0
        local mc = VC.Constants.MOOD_COLORS[mood] or VC.Constants.MOOD_COLORS.NEUTRAL
        local hex = format("%02x%02x%02x", mc.r * 255, mc.g * 255, mc.b * 255)
        print(format("|cFFA0522D[VC]|r Mood: |cFF%s%s|r (%.2f)", hex, mood, intensity))

    elseif command == "bond" then
        local info = VC.Bonding and VC.Bonding:GetLevelInfo()
        if info then
            local next = info.nextThreshold and tostring(info.nextThreshold) or "Max"
            print(format("|cFFA0522D[VC]|r Bond: %s (%d/%s)", info.name, info.rapport, next))
            if info.streakDays > 1 then
                print(format("  Login streak: %d days", info.streakDays))
            end
        else
            print("|cFFA0522D[VC]|r Bonding not initialized")
        end

    elseif command == "models" then
        if VC.ModelViewer then VC.ModelViewer:Toggle() end

    elseif command == "anim" then
        local animID = tonumber(arg)
        if animID then
            -- Try on model viewer selected model first, then portrait
            local target = VC.ModelViewer and VC.ModelViewer._selectedModel
            if target then
                target:SetAnimation(animID)
                print("|cFFA0522D[VC]|r Playing anim " .. animID .. " on model viewer selection")
            elseif VC.Portrait and VC.Portrait.frame and VC.Portrait.frame.model then
                VC.Portrait.frame.model:SetAnimation(animID)
                print("|cFFA0522D[VC]|r Playing anim " .. animID .. " on portrait")
            end
        else
            print("|cFFA0522D[VC]|r Usage: /vc anim <id> (e.g. /vc anim 135)")
        end

    elseif command == "scene" then
        -- Test ModelScene rendering with shared helpers
        local displayID = tonumber(arg)
        if not displayID then
            local comp = VC_CompanionProfiles[VC.Store:GetState().config.activeCompanion]
            displayID = comp and comp.displayID or 36894
        end
        if not VC._testScene then
            local f = CreateFrame("Frame", "VC_SceneTest", UIParent, "BackdropTemplate")
            f:SetSize(300, 300)
            f:SetPoint("CENTER")
            f:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = 1 })
            f:SetBackdropColor(0.1, 0.1, 0.1, 1)
            f:SetBackdropBorderColor(1, 1, 1, 0.5)
            f:SetFrameStrata("DIALOG")
            f:EnableMouse(true)
            f:SetMovable(true)
            f:RegisterForDrag("LeftButton")
            f:SetScript("OnDragStart", f.StartMoving)
            f:SetScript("OnDragStop", f.StopMovingOrSizing)
            f.scene = VC.UI:CreateModelScene(f, 0)
            f.scene:SetAllPoints(f)
            f.scene:SetFrameLevel(f:GetFrameLevel() + 1)
            local dbg = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            dbg:SetPoint("TOPLEFT", 5, -5)
            f.dbg = dbg
            local close = CreateFrame("Button", nil, f, "UIPanelCloseButton")
            close:SetPoint("TOPRIGHT", 2, 2)
            VC._testScene = f
        end
        local f = VC._testScene
        f:Show()
        local did = displayID
        VC.UI:SetCreatureOnScene(f.scene, displayID, {
            scale = 1.0,
            onLoaded = function(a)
                local ba, bb, bc, bd, be, bf = a:GetActiveBoundingBox()
                if ba then
                    f.dbg:SetText(format("ID:%d h:%.2f w:%.2f d:%.2f\nscale:%.2f frame:%dx%d",
                        did, bf - bc, be - bb, bd - ba, a:GetScale(), f.scene:GetSize()))
                else
                    f.dbg:SetText(format("ID:%d NO BBOX", did))
                end
            end,
        })
        print(format("|cFFA0522D[VC]|r Scene test: displayID %d", displayID))

    elseif command == "debug" then
        local state = VC.Store:GetState()
        VC.Store:Dispatch("SET_CONFIG", { key = "debug", value = not state.config.debug })
        local newDebug = VC.Store:GetState().config.debug
        print("|cFFA0522D[VC]|r Debug: " .. (newDebug and "ON" or "OFF"))
        if VC.Portrait and VC.Portrait.frame and VC.Portrait.frame.model then
            VC.Portrait:UpdateDebugText(VC.Portrait.frame.model, nil, "Debug")
        end

    else
        print("|cFFA0522D[VC]|r Unknown command. Type /vc for help.")
    end
end
