local addonName, ZL = ...

ZL.EventsFrame = CreateFrame("Frame")
local watchedEvents = {
    "PLAYER_ENTERING_WORLD", "ZONE_CHANGED_NEW_AREA", "ZONE_CHANGED",
    "QUEST_TURNED_IN", "ACHIEVEMENT_EARNED", "NEW_MOUNT_ADDED",
    "NEW_PET_ADDED", "PET_JOURNAL_LIST_UPDATE",
    "HOUSE_DECOR_ADDED_TO_CHEST",
    "TRANSMOG_COLLECTION_UPDATED", "TRANSMOG_COLLECTION_SOURCE_ADDED",
    "LOOT_READY", "LOOT_SLOT_CLEARED", "LOOT_CLOSED", "BAG_UPDATE_DELAYED",
    "ITEM_DATA_LOAD_RESULT", "QUEST_DATA_LOAD_RESULT",
}
for _, event in ipairs(watchedEvents) do ZL.EventsFrame:RegisterEvent(event) end

local pendingLoot = {}
local decorEventsReady = false
local decorStartupScheduled = false
local function ScanLoot()
    if not GetNumLootItems then return end
    pendingLoot = {}
    for slot = 1, GetNumLootItems() do
        local link = GetLootSlotLink(slot)
        local itemID = link and C_Item.GetItemInfoInstant(link)
        if itemID then pendingLoot[slot] = { itemID = itemID, link = link } end
    end
end

local function ScanBagsForTrackedItems()
    if ZL.ATT then return end
    for _, definition in pairs(ZL.Catalog) do
        for _, rare in ipairs(definition.rares or {}) do
            if rare.itemID and C_Item.GetItemCount(rare.itemID, true) > 0 then
                ZL:MarkTrackedItemCollected(rare.itemID)
            end
        end
    end
end

function ZL:ScheduleRefresh(delay)
    if self.refreshPending then return end
    self.refreshPending = true
    C_Timer.After(delay or 0.2, function()
        self.refreshPending = false
        self:ScanAllRouteZones()
        self:CheckZoneState()
        self:RefreshUI()
    end)
end

ZL.EventsFrame:SetScript("OnEvent", function(_, event, ...)
    if not ZL_Saved or not ZL_Saved.route then return end

    local arg1 = ...
    if event == "QUEST_TURNED_IN" then
        ZL:RecordQuestTurnIn(arg1)
    elseif event == "TRANSMOG_COLLECTION_SOURCE_ADDED" then
        ZL:RecordTransmogSource(arg1)
    elseif event == "HOUSE_DECOR_ADDED_TO_CHEST" and decorEventsReady then
        ZL:RecordDecorUnlock(...)
    end

    if event == "LOOT_READY" then
        ScanLoot()
    elseif event == "LOOT_SLOT_CLEARED" then
        local loot = pendingLoot[arg1]
        if loot then
            ZL:RecordObtainedItem(loot.itemID, loot.link)
            ZL:MarkTrackedItemCollected(loot.itemID)
            pendingLoot[arg1] = nil
        end
    elseif event == "LOOT_CLOSED" then
        pendingLoot = {}
    elseif event == "BAG_UPDATE_DELAYED" then
        ScanBagsForTrackedItems()
    end

    if event == "LOOT_READY" or event == "LOOT_CLOSED" then return end

    if event == "PLAYER_ENTERING_WORLD" or event == "ZONE_CHANGED_NEW_AREA" or event == "ZONE_CHANGED" then
        if event == "PLAYER_ENTERING_WORLD" and not decorStartupScheduled then
            decorStartupScheduled = true
            -- Housing fires chest synchronization events while the character's
            -- collection initializes. They are not new acquisitions.
            C_Timer.After(8, function() decorEventsReady = true end)
        end
        ZL:CheckZoneState()
        if event == "PLAYER_ENTERING_WORLD" then ZL:ScheduleRefresh(0.15) else ZL:RefreshUI() end
    elseif event == "ITEM_DATA_LOAD_RESULT" or event == "QUEST_DATA_LOAD_RESULT" then
        ZL:ScheduleRefresh(0.01)
    else
        -- Capture direct Blizzard API transitions before ATT rebuilds its
        -- groups, then synchronize ATT and rebuild the route on completion.
        ZL:DetectLiveCompletionChanges()
        ZL:ScheduleRefresh(0.15)
    end
end)
