local ADDON_NAME, WDIGI = ...
WDIGI.Tooltip = WDIGI.Tooltip or {}

local VT = WDIGI.Data.VENDOR_TYPE

------------------------------------------------------------
-- CATEGORY DEFINITIONS
------------------------------------------------------------
WDIGI.Tooltip.CATEGORIES = {
    { vendorType = VT.DROPPED_BY,        header = "|cff00ff00What Drops This?|r",       setting = "WDIGI_Limit_DroppedBy" },
    { vendorType = VT.SOLD_BY,           header = "|cffffff00Who Sells This?|r",        setting = "WDIGI_Limit_SoldBy" },
    { vendorType = VT.CONTAINED_IN,      header = "|cff00ffffContained In?|r",          setting = "WDIGI_Limit_ContainedIn" },
    { vendorType = VT.DISENCHANTED_FROM, header = "|cffc080ffDisenchanted From?|r",     setting = "WDIGI_Limit_Disenchanted" },
    { vendorType = VT.GATHERED_FROM,     header = "|cffff8000Gathered From?|r",         setting = "WDIGI_Limit_GatheredFrom" },
    { vendorType = VT.CRAFTED_BY,        header = "|cffeda55fCrafted By?|r",            setting = "WDIGI_Limit_CraftedBy" },
    { vendorType = VT.LEARNED_FROM,      header = "|cffabd473Learned From?|r",          setting = "WDIGI_Limit_LearnedFrom" },
    { vendorType = VT.QUEST_REWARD,      header = "|cffffcc00Quest Reward?|r",          setting = "WDIGI_Limit_QuestReward" },    
    { vendorType = VT.UNKNOWN,           header = "|cffaaaaaaOther Sources?|r",         setting = "WDIGI_Limit_Other" }
}

------------------------------------------------------------
-- MAIN TOOLTIP UPDATE
------------------------------------------------------------
function WDIGI.Tooltip.Update(tooltip)
    if tooltip ~= GameTooltip and tooltip ~= ItemRefTooltip then return end
    if not tooltip or tooltip:IsForbidden() then return end

    local _, itemLink = tooltip:GetItem()
    if not itemLink then return end

    local itemID = GetItemInfoFromHyperlink(itemLink)
    if not itemID or not ITEMLOCATIONSLIST[itemID] then return end

    if WDIGI.Settings.Get("WDIGI_ALTKey_Toggle") and not IsAltKeyDown() then return end

    local itemName, _, _, _, _, _, _, _, _, itemIcon = GetItemInfo(itemLink)
    if not itemName then return end

    WDIGI.Tooltip.lastItemName = itemName
    WDIGI.Tooltip.lastItemIcon = itemIcon
    WDIGI.Tooltip.bestLocation = nil
    
    local linesAdded = false
    local firstCategory = true

    for _, cat in ipairs(WDIGI.Tooltip.CATEGORIES) do
        local best = WDIGI.Tooltip.AddCategory(tooltip, itemID, cat.vendorType, cat.header, cat.setting, firstCategory)
        if best then
            linesAdded = true
            if (not WDIGI.Tooltip.bestLocation or best.dist < WDIGI.Tooltip.bestLocation.dist) then
                WDIGI.Tooltip.bestLocation = best
                WDIGI.Tooltip.bestLocation.header = cat.header
            end
        end
        firstCategory = false
    end

    if linesAdded then tooltip:Show() end
end

------------------------------------------------------------
-- CATEGORY RENDERING
------------------------------------------------------------
function WDIGI.Tooltip.AddCategory(tooltip, itemID, vendorType, header, setting, firstCategory)
    local entries = WDIGI.Data.ParseItemData(itemID)
    if #entries == 0 then return nil end

    local myMapID, px, py = WDIGI.MapUtils.GetCurrentPlayerData()
    local results = {}

    for _, e in ipairs(entries) do
        if e.vendorType == vendorType then
            local matchLevel = WDIGI.MapUtils.GetZoneMatchLevel(myMapID, e.mapID)
            
            -- Standardize local detection (Strictly on the same map)
            local isLocal = (matchLevel == 0)
            local dist = 999999 -- Default to nearly infinite

            -- 🌟 THE SPATIAL PROTECTION GATES:
            -- ONLY calculate real physical distance if matchLevel is EXACTLY 0 (Same Map ID).
            -- If matchLevel is 1+ (Parent continent, macro zone, or foreign land),
            -- coordinates do not share the same 2D scale grid and will result in ghost yardage.
            if isLocal and px and py and e.tx > 0 and e.ty > 0 then
                local dx = (e.tx / 100) - px
                local dy = (e.ty / 100) - py
                
                local mult = WDIGI.MapUtils.GetZoneMultiplier(e.mapID) or 1000
                dist = math.sqrt(dx * dx + dy * dy) * mult
            else
                -- If it's a loose parent relationship (matchLevel 1) or completely foreign (2 or 3),
                -- calculate a massive distance penalty to push it to the bottom of the tooltips list.
                dist = 1000000 * (matchLevel + 1)
            end

            table.insert(results, {
                dist       = dist,
                onMap      = isLocal,
                matchLevel = matchLevel,
                zID        = e.mapID,
                parentID   = e.parentMapID,
                tx         = e.tx,
                ty         = e.ty,
                vendorName = e.vendorName,
                vendorType = e.vendorType,
                cost       = e.cost,
                npcID      = e.npcID,      
                sType      = e.sourceType, 
                era        = e.clientVer   
            })
        end
    end

    if #results == 0 then return nil end

    -- Smart Filtering: Ensure local city vendors aren't filtered out by sub-zone mismatches
    local bestLevel = 3
    for _, r in ipairs(results) do
        if r.matchLevel < bestLevel then bestLevel = r.matchLevel end
    end

    local filterLevel = (bestLevel == 0) and 1 or bestLevel
    local filtered = {}
    for _, r in ipairs(results) do
        if r.matchLevel <= filterLevel then table.insert(filtered, r) end
    end
    results = filtered

    -- Sort: Absolute distance priority
    table.sort(results, function(a, b)
        if a.dist ~= b.dist then return a.dist < b.dist end
        return a.matchLevel < b.matchLevel
    end)

    if WDIGI.Settings.Get("WDIGI_ShowItemID_Toggle") and firstCategory then
        tooltip:AddLine("|cffff0000Item ID:|r " .. itemID)
    end

    tooltip:AddLine("\n" .. header)

    local limit = WDIGI.Settings.Get(setting) or 5
    for i = 1, math.min(limit, #results) do
        local r = results[i]
        local mapInfo = C_Map.GetMapInfo(r.zID or 0) or (r.parentID and C_Map.GetMapInfo(r.parentID))
        local zoneName = mapInfo and mapInfo.name or (r.vendorType == VT.DROPPED_BY and "World Drop" or "Unknown")
        
        -- Rich Icon Logic
        local icon = WDIGI.Data.VENDOR_ICONS[r.vendorType]
        if r.sType == "creature" or (r.npcID and r.npcID > 0) then
            icon = 135911 -- Portrait
        elseif r.sType == "gameobject" then
            icon = 132594 -- Chest
        end
        
        -- Apply the crop texture to clean up the portrait borders
        local iconTag = icon and ("|T" .. icon .. ":14:14:0:0:64:64:8:56:8:56|t ") or ""
        local zoneColor = not mapInfo and "|cff9d9d9d" or "|cff80ff80"

        -- Remove era tag for now in tooltip
        --local eraTag = (r.era and r.era ~= "") and (" |cff808080["..r.era.."]|r") or ""
        --local line = string.format("  %s|cffffffff%s|r%s - %s%s|r", iconTag, r.vendorName, eraTag, zoneColor, zoneName)
        local line = string.format("  %s|cffffffff%s|r - %s%s|r", iconTag, r.vendorName, zoneColor, zoneName)
        
        if r.tx > 0 then
            line = line .. string.format(" (|cffffff00%.1f, %.1f|r)", r.tx, r.ty)
        end

        -- 🌟 SHOW ZERO OR UNCALCULATED PERCENTAGES BETTER:
        -- 🌟 COLOR-CODED PERCENTAGE & COST ASSEMBLY
        if r.cost and r.cost ~= "" then
            local displayCost = r.cost
            
            if r.vendorType == VT.DROPPED_BY then
                local percentNum = 0
                
                if displayCost == "0" then
                    displayCost = "<0.1%"
                    percentNum = 0.05 -- Give uncalculated/ultra-rare a near-zero calculation weight
                else
                    -- Strip out any pre-existing '%' signs if they accidentally slipped into the string
                    local sanitizedCost = displayCost:gsub("%%", "")
                    percentNum = tonumber(sanitizedCost) or 0
                    
                    -- Re-append clean string percent suffix
                    if not displayCost:find("%%") then
                        displayCost = displayCost .. "%"
                    end
                end

                -- Color Scale for Drop Rates
                -- (GLOWING AMETHYST VARIANT): Low Drop % is Bright Neon Purple (Maximum Legibility)
                local factor = math.max(0, math.min(100, percentNum)) / 100
                
                -- 0% (Ultra Rare)   = Glowing Electric Violet  (|cffcf7aff)
                -- 100% (Guaranteed) = Crisp Ice Diamond Blue   (|cff00daff)
                
                -- High-Illumination Linear Interpolation:
                local r_col = math.floor(207 - (207 * factor))
                local g_col = math.floor(122 + (96 * factor))
                local b_col = 255 -- Locked at max to ensure high contrast

                local colorTag = string.format("|cff%02x%02x%02x", r_col, g_col, b_col)
                line = line .. " " .. colorTag .. "[" .. displayCost .. "]|r"
            
            -- Keep standard gold-yellow formatting for store/vendor items
            elseif displayCost ~= "0" and not displayCost:find("%%") then
                displayCost = WDIGI.Data.FormatMoney(displayCost)
                local color = "|cffffd100" -- Classic WoW Vendor Gold color
                line = line .. " " .. color .. "[" .. displayCost .. "]|r"
            end
        end
        
        if r.onMap and r.dist < 5000 and r.tx > 0 then
            line = line .. " |cff32ff32(" .. math.floor(r.dist) .. "yd)|r"
        end

        tooltip:AddLine(line)
    end

    return results[1]
end