local addonName, privateDB = ...
local HDG = _G.HousingDecorGuide
local Log = privateDB.Log
local LOG_LEVEL = privateDB.LOG_LEVEL

-- ============================================================================
-- MAIN ADDON FILE
-- Event Handling and Entry Point
-- ============================================================================

-- ============================================================================
-- STORE HELPERS
-- ============================================================================

local function GetStore()
    local hdg = _G.HousingDecorGuide
    return hdg and hdg.Store
end

local function GetState()
    local store = GetStore()
    return store and store:GetState()
end

local function GetUIState(key)
    local state = GetState()
    return state and state.ui and state.ui[key]
end

-- Craft-quote chattiness gate moved to HDG_Vamoose.RegisterCraftQuoteHandler.

-- Initialize Database
local initialized = HDG_Data.InitializeDatabase()
if not initialized then
    print("|cFFFF0000[Housing Decor Guide]|r Failed to initialize database! Addon will not work.")
    return
end

-- Slash command
-- /hdg is the user-facing slash. Dev/diagnostic commands live exclusively on
-- /hdgdebug. Old /hdg dev names (featuredtest, costtest, tsm, etc.) no longer
-- delegate -- they fall through to the window toggle. Use /hdgdebug for those.
SLASH_HDG1 = "/hdg"
SlashCmdList["HDG"] = function(msg)
    local cmd = msg and msg:lower():trim() or ""

    -- /hdg help -- list user-facing commands. Dev commands listed under /hdgdebug.
    if cmd == "help" or cmd == "?" then
        print("|cFF14b8a6[Housing Decor Guide]|r commands:")
        print("  |cFFfcd34d/hdg|r              -- toggle main window")
        print("  |cFFfcd34d/hdg projects|r     -- open Projects tab")
        print("  |cFFfcd34d/hdg dump|r         -- copy current HouseTab layout config")
        print("  |cFFfcd34d/hdg decor|r        -- filter open profession window to housing recipes")
        print("  |cFFfcd34d/hdg dyes|r         -- open Vamoose's Dye Studio")
        print("  |cFFfcd34d/hdg hud|r          -- toggle lumber compass HUD")
        print("  |cFFfcd34d/hdg reset|r        -- emergency window-position reset")
        print("  |cFFfcd34d/hdgdebug|r         -- developer/diagnostic commands (separate menu)")
        return
    end

    -- /hdg dump (and aliases): copy dialog for HouseTab LAYOUT_CONFIG so
    -- runtime picker tweaks can be pasted back into source.
    if cmd == "dump" or cmd == "layout dump" or cmd == "layoutdump" or cmd == "decordump" then
        local HDG_HT = privateDB and privateDB.HDG_HT
        if HDG_HT and HDG_HT.LayoutDump and HDG_HT.LayoutDump.Dump then
            HDG_HT.LayoutDump.Dump()
        else
            print("|cFFFF0000[HDG]|r Layout dump not loaded.")
        end
        return
    end

    -- /hdg projects: open HDG with the Projects tab active.
    if cmd == "projects" or cmd == "proj" then
        if HDG_UI and HDG_UI.Show then HDG_UI.Show() end
        if HDG_UI and HDG_UI.SwitchTab then HDG_UI.SwitchTab("projects") end
        return
    end

    if cmd == "decor" then
        if HDG_PowerCrafting and HDG_PowerCrafting.FilterProfessionWindowToHouseDecor then
            HDG_PowerCrafting.FilterProfessionWindowToHouseDecor()
        end

    elseif cmd == "dyes" or cmd == "dye" then
        if VamoosesDyeStudio and VamoosesDyeStudio.Toggle then
            VamoosesDyeStudio.Toggle()
        else
            print("|cFF00CED1Vamoose's Dye Studio|r is a standalone addon. Get it on CurseForge or Wago!")
        end

    elseif cmd == "hud" then
        -- Toggle lumber compass HUD
        if privateDB.HDG_LumberHUD then
            privateDB.HDG_LumberHUD.Toggle()
        else
            print("|cFFFF0000[Housing Decor Guide]|r Lumber HUD not available")
        end

    elseif cmd == "reset" then
        -- Emergency window reset: clear saved position and force to center
        local store = GetStore()
        if store then
            local state = store:GetState()
            if state and state.layout then state.layout.MainFrame = nil end
            if state and state.ui then state.ui.framePosition = nil end
        end
        local f = _G["HDG_MainFrame"]
        if f then
            f:ClearAllPoints()
            f:SetPoint("CENTER")
            f:Show()
            HDG_UI.RefreshUI()
            print("|cFF14b8a6[Housing Decor Guide]|r Window reset to center.")
        else
            -- Frame doesn't exist yet, create it fresh
            HDG_UI.CreateUI()
            f = _G["HDG_MainFrame"]
            if f then
                f:ClearAllPoints()
                f:SetPoint("CENTER")
                f:Show()
                HDG_UI.RefreshUI()
                print("|cFF14b8a6[Housing Decor Guide]|r Window created and reset to center.")
            else
                print("|cFFFF0000[Housing Decor Guide]|r Window reset failed. Try /reload then /hdg reset")
            end
        end

    else
        HDG_UI.Toggle()
    end
end


-- QueueInventoryUpdate / QueueRecipeUpdate moved to HDG_UI; main file calls
-- them via privateDB.QueueInventoryUpdate from the BAG_UPDATE handler below.

-- Set to true in PLAYER_ENTERING_WORLD (on initial login / reload) and cleared
-- on first BAG_UPDATE_DELAYED. Used to defer restoring pinned UI windows until
-- bag contents are guaranteed loaded, replacing timer-based guesses.
local loginRestorePending = false
local loginRestoreFallbackTimer = nil

local function RunPinnedRestore()
    if not loginRestorePending then return end
    loginRestorePending = false
    if loginRestoreFallbackTimer then loginRestoreFallbackTimer:Cancel(); loginRestoreFallbackTimer = nil end
    if GetUIState("lumberPinned") and HDG_LumberTracker and HDG_LumberTracker.RestorePinnedState then
        HDG_LumberTracker.RestorePinnedState()
    end
    if GetUIState("vendorListPinned") and HDG_VendorShoppingList and HDG_VendorShoppingList.Show then
        HDG_VendorShoppingList.Show()
    end
    if GetUIState("materialsListPinned") and HDG_MaterialsList and HDG_MaterialsList.Show then
        HDG_MaterialsList.Show()
    end
end

-- Event Handling
local eventFrame = CreateFrame("Frame")
-- Main file owns only lifecycle + cross-module coordination events.
-- Per-domain Blizzard events are owned by their module's RegisterEvents().
eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
eventFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")  -- main file fans out to LumberTracker / LumberHUD / ZoneMode (debounced 0.5s)
eventFrame:RegisterEvent("BAG_UPDATE_DELAYED")     -- triggers QueueInventoryUpdate + login-restore on first burst
eventFrame:RegisterEvent("MAIL_INBOX_UPDATE")
eventFrame:RegisterEvent("PLAYER_MONEY")
eventFrame:RegisterEvent("PLAYER_LOGOUT")          -- Store flush (HDG_LumberTracker saves its sessions on its own frame)

eventFrame:SetScript("OnEvent", function(self, event, arg1, ...)
    if event == "ADDON_LOADED" and arg1 == addonName then
        -- Initialize Store (run pre-load migration, then load from HDG_DB)
        local storeOk, storeErr = pcall(function()
            -- Initialise HDG_DB before passing to migration. Without this,
            -- `_G.HDG_DB or {}` on a brand-new install passes a transient
            -- table that the migration mutates but is then discarded -- the
            -- schemaVersion stamp + scalar captures would be lost on first
            -- LoadFromSavedVariables (which would reinit HDG_DB to {}).
            _G.HDG_DB = _G.HDG_DB or {}
            local Migration = privateDB and privateDB.HDG_Migration
            if Migration and Migration.RunPreLoad then
                -- HDG_Settings stays in TOC indefinitely so never-migrated accounts
                -- (users updating from v2.40 or earlier after a long pause) can still
                -- read their fallthrough preferences (recentActivity.sessionCap,
                -- altsViewMode, localeOverride). Vestigial empty table post-migration.
                Migration.RunPreLoad(_G.HDG_DB, _G.HDG_Settings or {})
            end
            HDG.Store:LoadFromSavedVariables()
        end)
        if not storeOk then
            Log(LOG_LEVEL.ERROR, "Store initialization failed: %s", storeErr)
        end

        -- Phase 3: Initialize Theme Engine
        local HDG = _G.HousingDecorGuide
        local themeSuccess, themeErr = pcall(function() HDG.Theme:Initialize() end)
        if not themeSuccess then
            Log(LOG_LEVEL.ERROR, "Theme Engine initialization failed: %s", themeErr)
        end

        -- Apply locale override if set (after SavedVariables loaded)
        if HDG_L and HDG_L.ApplyOverride then
            HDG_L:ApplyOverride()
        end

        -- Initialize minimap button after settings are loaded
        if privateDB.HDG_Minimap then
            privateDB.HDG_Minimap.Initialize()
        end

        -- Register Projects topology-capture event hooks
        if privateDB.HDG_TopologyCapture and privateDB.HDG_TopologyCapture.RegisterEvents then
            privateDB.HDG_TopologyCapture.RegisterEvents()
        end

        -- Initialize Recent Activity tracker
        if HDG.RecentActivity and HDG.RecentActivity.Initialize then
            HDG.RecentActivity:Initialize()
        end

        -- Module event wiring -- each module owns its own Blizzard hooks.
        -- Main file is just the orchestrator that calls each module's
        -- RegisterEvents() once on ADDON_LOADED.
        if HDG_VendorShoppingList and HDG_VendorShoppingList.RegisterEvents then
            HDG_VendorShoppingList.RegisterEvents()
        end
        if HDG_LumberTracker and HDG_LumberTracker.RegisterEvents then
            HDG_LumberTracker.RegisterEvents()
        end
        if HDG_PowerCrafting and HDG_PowerCrafting.RegisterTooltipDecorator then
            HDG_PowerCrafting.RegisterTooltipDecorator()
        end
        if HDG_PowerCrafting and HDG_PowerCrafting.RegisterCraftAutoDecrement then
            HDG_PowerCrafting.RegisterCraftAutoDecrement()
        end
        if HDG_Data and HDG_Data.RegisterEvents then
            HDG_Data.RegisterEvents()
        end
        if HDG_UI and HDG_UI.RegisterEvents then
            HDG_UI.RegisterEvents()
        end
        if privateDB.HDG_DataTab and privateDB.HDG_DataTab.RegisterEvents then
            privateDB.HDG_DataTab.RegisterEvents()
        end
        if privateDB.HDG_Vamoose and privateDB.HDG_Vamoose.RegisterCraftQuoteHandler then
            privateDB.HDG_Vamoose.RegisterCraftQuoteHandler()
        end

        -- Load persisted direct AH price cache
        HDG_PriceIntegration.LoadCache()

        -- Initialize waypoint map pins (deferred until WorldMapFrame loads)
        C_Timer.After(2, function() HDG.Waypoints:InitMapPins() end)

        -- v2.0: Collect character profession data for multi-character tracking
        C_Timer.After(1, function()
            HDG_Data.CollectCharacterProfessions()
            Log(LOG_LEVEL.DEBUG, "Character profession data collected")
        end)

        Log(LOG_LEVEL.INFO, "Addon loaded successfully")
        if HDG.Store and HDG.Store:GetState().config.debug then
            print(string.format("|cFF00FF00Vamoose's Housing Decor Helper v%s|r loaded! Type |cFFFFFF00/hdg|r to open.", privateDB.ADDON_VERSION))
        end

    elseif event == "PLAYER_ENTERING_WORLD" then
        local isInitialLogin, isReloadingUi = arg1, ...
        -- Lumber session init + char-lumber-inventory save moved to
        -- HDG_LumberTracker.RegisterEvents (its own PEW listener).
        -- Collection search runs lazily on main-window open via HDG_UI.RefreshAll
        -- (mirroring the Refresh button). Eager warm at PEW+1s was removed
        -- because the housing catalog is not yet synced that early on cold
        -- login -- it returned 0 results and locked the cache into a falsely
        -- warmed state.

        -- Auto-restore pinned floating windows on login/reload (not zone transitions).
        -- Deferred until BAG_UPDATE_DELAYED so counts render correctly; 5s fallback
        -- timer runs the restore anyway if BAG_UPDATE_DELAYED never fires.
        if isInitialLogin or isReloadingUi then
            loginRestorePending = true
            if loginRestoreFallbackTimer then loginRestoreFallbackTimer:Cancel() end
            loginRestoreFallbackTimer = C_Timer.NewTimer(5, function()
                if loginRestorePending then
                    Log(LOG_LEVEL.DEBUG, "Login restore fallback fired (BAG_UPDATE_DELAYED did not fire)")
                    RunPinnedRestore()
                end
            end)
        end

        -- Login/reload zone-change broadcast (ZONE_CHANGED_NEW_AREA doesn't
        -- fire on /reload). Modules subscribe via HDG.EventBus:Register
        -- ("HDG_ZONE_CHANGED"); ZoneMode picks this up to scan the current
        -- zone for vendor alerts. Store ownership is loaded by PEW so the
        -- scanner's IsItemCollected reads fall back to Store cleanly even
        -- when the module-local cache hasn't been warmed yet.
        if (isInitialLogin or isReloadingUi) and HDG and HDG.EventBus then
            local mapID = C_Map.GetBestMapForUnit("player")
            if mapID then HDG.EventBus:Trigger("HDG_ZONE_CHANGED", mapID) end
        end

    elseif event == "ZONE_CHANGED_NEW_AREA" then
        -- Debounce rapid zone transitions (the map API can return nil briefly
        -- during the transition itself), then broadcast HDG_ZONE_CHANGED on
        -- the EventBus. Modules that care (LumberTracker, LumberHUD,
        -- ZoneMode) subscribe themselves; main file is just the debouncer.
        if privateDB._zoneChangeTimer then privateDB._zoneChangeTimer:Cancel() end
        privateDB._zoneChangeTimer = C_Timer.NewTimer(0.5, function()
            privateDB._zoneChangeTimer = nil
            local mapID = C_Map.GetBestMapForUnit("player")
            if mapID and HDG and HDG.EventBus then
                HDG.EventBus:Trigger("HDG_ZONE_CHANGED", mapID)
                Log(LOG_LEVEL.DEBUG, "HDG_ZONE_CHANGED fired (mapID: %d)", mapID)
            end
        end)

    -- HOUSE_DECOR_ADDED_TO_CHEST       -> HDG_DataTab.RegisterEvents
    -- HOUSING_STORAGE_ENTRY_UPDATED    -> HDG_UI.RegisterEvents
    -- TRADE_SKILL_LIST_UPDATE / NEW_RECIPE_LEARNED / TRADE_SKILL_SHOW
    --                                  -> HDG_Data.RegisterEvents

    elseif event == "BAG_UPDATE_DELAYED" or
           event == "MAIL_INBOX_UPDATE" or
           event == "PLAYER_MONEY" then
        if event == "BAG_UPDATE_DELAYED" and loginRestorePending then
            -- First bag-update burst after login/reload has settled; pinned
            -- floating windows can now restore with accurate counts.
            RunPinnedRestore()
        end
        if privateDB.QueueInventoryUpdate then privateDB.QueueInventoryUpdate() end

    -- TRADE_SKILL_ITEM_CRAFTED_RESULT  -> HDG_Data (log) + HDG_Vamoose (quote)
    --                                     + HDG_PowerCrafting (queue auto-decrement)
    -- ACHIEVEMENT_EARNED               -> HDG_DataTab (housing) + HDG_LumberTracker (lumber)

    elseif event == "PLAYER_LOGOUT" then
        -- Lumber session save moved to HDG_LumberTracker.RegisterEvents.
        -- Phase 2: Flush Store to SavedVariables on logout
        HDG.Store:Flush()
    end
end)

-- ============================================================================
-- ADDON COMPARTMENT FUNCTIONS (Referenced by TOC metadata)
-- These global functions are called by Blizzard's addon compartment system
-- ============================================================================

function HousingDecorGuide_OnAddonCompartmentClick(addonName, buttonName)
    HDG_UI.Toggle()
end

function HousingDecorGuide_OnAddonCompartmentEnter(addonName, menuItem)
    GameTooltip:SetOwner(menuItem, "ANCHOR_RIGHT")
    GameTooltip:AddLine("|cFFfcd34dHousing Decor Guide|r", 1, 1, 1)
    GameTooltip:AddLine("Track and craft housing decor items", 0.7, 0.7, 0.7)
    GameTooltip:AddLine(" ")
    GameTooltip:AddLine("|cFFFFFFFFClick:|r Toggle addon window", 0.7, 0.7, 0.7)
    GameTooltip:Show()
end

function HousingDecorGuide_OnAddonCompartmentLeave(addonName, menuItem)
    GameTooltip:Hide()
end

-- Debug accessor: HousingDecorGuide.PrivateDB.HDG_ProjectsStore
HousingDecorGuide.PrivateDB = privateDB
