local GC = select(2, ...)

local Events = {}
GC.Events = Events

-- Wow APIs
local GetUnitName, UnitGUID = GetUnitName, UnitGUID

-- Lua APIs
local smatch, time, unpack, tostring = string.match, time, unpack, tostring
local tinsert = table.insert
local LibParse = LibStub:GetLibrary("LibParse")

-- Loot patterns
local LOOT_ITEM_SELF, LOOT_ITEM_SELF_MULTIPLE, INSTANCE_RESET_SUCCESS =
    LOOT_ITEM_SELF, LOOT_ITEM_SELF_MULTIPLE, INSTANCE_RESET_SUCCESS

local PATTERN_LOOT_ITEM_SELF = LOOT_ITEM_SELF:gsub("%%s", "(.+)")
local PATTERN_LOOT_ITEM_SELF_MULTIPLE = LOOT_ITEM_SELF_MULTIPLE:gsub("%%s",
                                                                     "(.+)")
                                            :gsub("%%d", "(%%d+)")

-- Instance reset pattern
local resetmsg = INSTANCE_RESET_SUCCESS:gsub("%%s", ".+")

--[[------------------------------------------------------------------------
    CHAT_MSG_LOOT - Self loot events
--------------------------------------------------------------------------]]
function Events.OnChatMsgLoot(event, msg)
    -- If session is not running, only proceed if alwaysOnNotifications is enabled
    if not GC.Session.IsRunning() and not GC.GetFromDb("notification", "alwaysOnNotifications") then return end

    if event == "CHAT_MSG_LOOT" then
        -- Retail 12.0+: piggyback on loot event to track NPC kills
        -- (CLEU is blocked, but CHAT_MSG_LOOT always fires when looting)
        if GC.Util.IsModern and GC.KillTracker then
            GC.KillTracker.TryTrackFromLoot()
        end

        if type(msg) ~= "string" then return end

        local loottype, itemLink, quantity

        -- Robust regex: Find "|Hitem:..." followed by optional " x..."
        local itemLinkMatch = msg:match("(|Hitem:[^|]+|h%[.-%]|h)")
        if itemLinkMatch then
            itemLink = itemLinkMatch
            -- Try to find quantity: either " x%d" or "%d x " (some locales)
            local qtyMatch = msg:match("x(%d+)") or msg:match("(%d+)x") or msg:match("(%d+) x")
            quantity = tonumber(qtyMatch) or 1
            loottype = "## robust parse ##"
        end

        if loottype then
            GC.Debug.Log("#### type=%s; itemLink=%s; quantity=%s", loottype,
                         tostring(itemLink), tostring(quantity))

            if not itemLink or not quantity then
                GC.Debug.Log("#### ignore event! msg: " .. msg .. ", type=" ..
                                 tostring(loottype))
                GC.Debug.Log("   itemLink=" .. tostring(itemLink) ..
                                 "; quantity=" .. tostring(quantity))
                return
            end

            local itemID = GC.Util.ToItemID(itemLink)
            GC.LootProcessing.HandleItemLooted(itemLink, itemID, quantity)
        end
    end
end

--[[------------------------------------------------------------------------
    TRADE_SKILL_ITEM_CRAFTED_RESULT - Crafted item tracking
--------------------------------------------------------------------------]]
function Events.OnTradeSkillCrafted(event, data)
    -- If session is not running, only proceed if alwaysOnNotifications is enabled
    if not GC.Session.IsRunning() and not GC.GetFromDb("notification", "alwaysOnNotifications") then return end
    if GC.Session.IsPaused() then return end
    if GC.GetFromDb("notification", "trackCrafts") == false then return end

    local loottype, itemLink, quantity, source
    itemLink = data.hyperlink
    quantity = data.quantity
    source = 'Profession'

    if data.quantity == 1 then
        loottype = "## self (single) ##"
    else
        loottype = "## self (multi) ##"
    end

    if loottype then
        GC.Debug.Log("#### type=%s; itemLink=%s; quantity=%s", loottype,
                     tostring(itemLink), tostring(quantity))
        GC.Debug.Log("----source: " .. tostring(source))

        if not itemLink or not quantity then
            GC.Debug.Log("#### ignore event! data: " .. data .. ", type=" ..
                             tostring(loottype))
            GC.Debug.Log(
                "   itemLink=" .. tostring(itemLink) .. "; quantity=" ..
                    tostring(quantity) .. "; source=" .. tostring(source) .. ")")
            return
        end

        local itemID = GC.Util.ToItemID(itemLink)
        GC.LootProcessing.HandleItemLooted(itemLink, itemID, quantity, source)
    end
end

--[[------------------------------------------------------------------------
    CHAT_MSG_ADDON - Group loot addon messages
--------------------------------------------------------------------------]]
function Events.OnChatMsgAddon(event, prefix, msg, type, sender)
    if not GC.Session.IsRunning() then return end

    if prefix ~= GC.CONST.PARTYLOOT_MSGPREFIX then return end

    GC.Debug.Log("sender vs. player: %s vs. %s", sender,
                 GetUnitName("player", true))
    if sender == GetUnitName("player", true) then
        GC.Debug.Log("#### OnChatMsgAddon: ignore message")
        return
    end

    local tokens = GC.Util.split(msg, "\001")
    local v = {}
    for i = 1, #tokens do tinsert(v, (LibParse:JSONDecode(tokens[i]))) end

    local _, itemLink, itemID, quantity, senderUnitGUID = true, unpack(v)

    GC.Debug.Log("senderGUID vs. playerGUID: %s vs. %s", senderUnitGUID,
                 UnitGUID("player"))
    if senderUnitGUID == UnitGUID("player") then
        GC.Debug.Log("OnChatMsgAddon: ignore message")
        return
    end

    GC.Debug.Log("OnChatMsgAddon: prefix=%s, msg=%s, type=%s, sender=%s",
                 prefix, msg, type, senderUnitGUID)
    GC.LootProcessing.HandleItemLooted(itemLink, itemID, quantity, sender)
end

--[[------------------------------------------------------------------------
    CHAT_MSG_MONEY - Currency loot events
--------------------------------------------------------------------------]]
function Events.OnChatMsgMoney(event, msg)
    if not GC.Session.IsRunning() then return end

    if type(msg) ~= "string" then return end

    GC.Debug.Log("  OnChatMsgMoney: msg=%s", tostring(msg))

    local ok, lootedCopper = pcall(GC.Util.StringToMoney, msg)
    if not ok then return end
    if msg == "Free Trial money cap reached." then
        GC.Debug.Log("Ignoring looted copper.")
    else
        GC.Debug.Log("    lootedCopper=%s", tostring(lootedCopper))
        GC.LootProcessing.HandleCurrencyLooted(lootedCopper)
    end
end

--[[------------------------------------------------------------------------
    CHAT_MSG_SYSTEM - Instance reset detection
--------------------------------------------------------------------------]]
function Events.OnResetInfoEvent(event, msg)
    if event == "CHAT_MSG_SYSTEM" then
        if type(msg) ~= "string" then return end
        local ok, resetMatch = pcall(smatch, msg, "^" .. resetmsg .. "$")
        if not ok then return end
        if resetMatch then
            GC.Debug.Log("  match: " .. tostring(resetMatch))

            local _, instanceName = pcall(smatch, msg, INSTANCE_RESET_SUCCESS:gsub("%%s",
                                                                                    "(.+)"))

            local data = {
                ["endTime"] = time() + 60 * 60,
                ["instanceName"] = instanceName
            }

            GC.UI.AddToResetInfo(data)
        end
    end
end

