--[[
ETB ContainerTooltip — lists the collectible contents (mounts / pets) of
openable "bag" items on their hover tooltip, with collected/uncollected marks
and an X/Y owned count per group.

Driven by ETB.ContainerLoot (Data/ContainerLoot.lua). Collected state and names
reuse the same resolvers the Zone Scan uses: NS.EMT.MountAPI / NS.EPT.PetAPI,
with GetItemInfo as a quality-coloured name fallback.
]]--
local ADDON_NAME, NS = ...
NS.ETB = NS.ETB or {}
local ETB = NS.ETB

ETB.ContainerTooltip = {}
local CT = ETB.ContainerTooltip
CT.enabled = true

local MARK_OWNED   = "|TInterface\\RaidFrame\\ReadyCheck-Ready:14:14:0:0|t"
local MARK_MISSING = "|TInterface\\RaidFrame\\ReadyCheck-NotReady:14:14:0:0|t"
local HEADER  = "|cff66ccff"   -- cyan section header
local GREEN   = "|cff00ff00"
local RED     = "|cffff6666"
local GREY    = "|cff888888"
local WHITE   = "|cffffffff"

local function mark(owned)
    if owned == true then return MARK_OWNED end
    if owned == false then return MARK_MISSING end
    return ""  -- unknown: no mark
end

-- Quality-coloured name from the teaching/caging item, falling back to a
-- resolver-supplied name, then a stable placeholder.
local function nameFor(itemID, apiName)
    if itemID then
        local n, link, quality = GetItemInfo(itemID)
        if n then
            local hex
            if quality and ITEM_QUALITY_COLORS and ITEM_QUALITY_COLORS[quality] then
                hex = ITEM_QUALITY_COLORS[quality].hex
            end
            return (hex or WHITE) .. n .. "|r"
        end
    end
    if apiName then return WHITE .. apiName .. "|r" end
    return GREY .. "item " .. tostring(itemID or "?") .. "|r"
end

local function mountState(spellID, itemID)
    local API = NS.EMT and NS.EMT.MountAPI
    if API then
        local ok1, owned = pcall(API.IsCollected, API, spellID)
        local ok2, nm    = pcall(API.GetName, API, spellID, itemID)
        return (ok1 and owned), (ok2 and nm) or nil
    end
    return nil, nil
end

local function petState(speciesID, itemID)
    local API = NS.EPT and NS.EPT.PetAPI
    if API then
        local ok1, owned = pcall(API.IsCollected, API, speciesID)
        local ok2, nm    = pcall(API.GetName, API, speciesID, itemID)
        return (ok1 and owned), (ok2 and nm) or nil
    end
    return nil, nil
end

-- Append one collectible group (mounts or pets) to the tooltip; returns
-- owned/total so the caller can build the header counts.
local function addGroup(tooltip, label, entries, stateFn)
    if not entries or #entries == 0 then return 0, 0 end
    local owned, total = 0, #entries
    local lines = {}
    for _, e in ipairs(entries) do
        local isOwned, apiName = stateFn(e.s, e.i)
        if isOwned == true then owned = owned + 1 end
        local line = "  " .. mark(isOwned) .. " " .. nameFor(e.i, apiName)
        if e.rep then line = line .. " " .. GREY .. "(rep)|r" end
        lines[#lines + 1] = line
    end
    tooltip:AddLine(string.format("%s%s (%d/%d)|r", HEADER, label, owned, total))
    for _, l in ipairs(lines) do tooltip:AddLine(l, 1, 1, 1) end
    return owned, total
end

local function OnTooltipSetItem(tooltip)
    if not CT.enabled then return end
    if not ETB.ContainerLoot then return end
    local _, link = tooltip:GetItem()
    if not link then return end
    local itemID = tonumber(link:match("item:(%d+)"))
    if not itemID then return end
    local data = ETB.ContainerLoot[itemID]
    if not data then return end

    -- Guard against the multiple OnTooltipSetItem fires for one render.
    if tooltip.__etbContainerShown == itemID then return end
    tooltip.__etbContainerShown = itemID

    tooltip:AddLine(" ")
    tooltip:AddLine(HEADER .. "Possible collectibles|r")
    local mo, mt = addGroup(tooltip, "Mounts", data.mounts, mountState)
    local po, pt = addGroup(tooltip, "Pets",   data.pets,   petState)

    local totalOwned, total = mo + po, mt + pt
    if total > 0 then
        local col = (totalOwned >= total) and GREEN or GREY
        tooltip:AddLine(string.format("%sCollected %d of %d|r", col, totalOwned, total))
    end
    if data.mounts and #data.mounts > 0 then
        for _, e in ipairs(data.mounts) do
            if e.rep then
                tooltip:AddLine(GREY .. "(rep) = also requires a reputation level|r")
                break
            end
        end
    end
    tooltip:Show()
end

function CT:Initialize()
    if not GameTooltip then return end
    -- The guard below stops a double-append when OnTooltipSetItem fires twice
    -- for a single populate. It MUST be reset whenever the tooltip is cleared,
    -- because the game clears + re-populates merchant/bag tooltips repeatedly
    -- per hover — without this reset, only the first (later wiped) populate
    -- carries our lines and the visible tooltip ends up blank. (v15.82.0)
    local function resetGuard(self) self.__etbContainerShown = nil end
    GameTooltip:HookScript("OnTooltipSetItem", OnTooltipSetItem)
    GameTooltip:HookScript("OnTooltipCleared", resetGuard)
    GameTooltip:HookScript("OnHide", resetGuard)
    if ItemRefTooltip then
        ItemRefTooltip:HookScript("OnTooltipSetItem", OnTooltipSetItem)
        ItemRefTooltip:HookScript("OnTooltipCleared", resetGuard)
        ItemRefTooltip:HookScript("OnHide", resetGuard)
    end
    if ETB.Debug then ETB:Debug("ContainerTooltip", "Container loot tooltip installed") end
end
