local _, ns = ...
local L = ns.L or {}

local FEATURE_ID = "item_id_tooltip"

local Runtime = {
    enabled = false,
    hooksReady = false,
}
ns.ItemIDTooltipRuntime = Runtime

local function applySmallerFont(fontString)
    if not fontString or type(fontString.GetFont) ~= "function" or type(fontString.SetFont) ~= "function" then
        return nil
    end

    local fontFile, fontHeight, fontFlags = fontString:GetFont()
    fontHeight = tonumber(fontHeight)
    if not fontFile or not fontHeight then
        return nil
    end

    fontString:SetFont(fontFile, math.max(8, fontHeight - 2), fontFlags)
    return {
        fontFile = fontFile,
        fontHeight = fontHeight,
        fontFlags = fontFlags,
    }
end

local function restoreFont(fontString, fontInfo)
    if not fontString or type(fontString.SetFont) ~= "function" or type(fontInfo) ~= "table" then
        return
    end

    if fontInfo.fontFile and fontInfo.fontHeight then
        fontString:SetFont(fontInfo.fontFile, fontInfo.fontHeight, fontInfo.fontFlags)
    end
end

local function parseItemID(value)
    local ok, itemID = pcall(function()
        if type(value) == "number" then
            return value
        end
        if type(value) ~= "string" or value == "" then
            return nil
        end

        if C_Item and type(C_Item.GetItemInfoInstant) == "function" then
            local resolvedID = C_Item.GetItemInfoInstant(value)
            if tonumber(resolvedID) then
                return tonumber(resolvedID)
            end
        end

        return tonumber(value:match("item:(%d+)"))
    end)

    if ok and tonumber(itemID) and tonumber(itemID) > 0 then
        return math.floor(tonumber(itemID))
    end
    return nil
end

local function getTooltipItemID(tooltip, data)
    if type(data) == "table" then
        local itemID = parseItemID(data.id or data.hyperlink or data.guid)
        if itemID then
            return itemID
        end
    end

    if tooltip and type(tooltip.GetItem) == "function" then
        local okItem, _, itemLink = pcall(tooltip.GetItem, tooltip)
        if okItem then
            return parseItemID(itemLink)
        end
    end

    return nil
end

local function getTooltipRightLineOne(tooltip)
    if not tooltip or type(tooltip.GetName) ~= "function" then
        return nil
    end

    local name = tooltip:GetName()
    if type(name) ~= "string" or name == "" then
        return nil
    end

    return _G[name .. "TextRight1"]
end

local function ensureTooltipResetHook(tooltip)
    if not tooltip or tooltip.VaultloomItemIDTooltipClearHook then
        return
    end

    if tooltip.HookScript then
        tooltip:HookScript("OnTooltipCleared", function(selfTooltip)
            restoreFont(getTooltipRightLineOne(selfTooltip), selfTooltip.VaultloomItemIDTooltipOriginalRight1Font)
            selfTooltip.VaultloomItemIDTooltipItemID = nil
            selfTooltip.VaultloomItemIDTooltipOriginalRight1 = nil
            selfTooltip.VaultloomItemIDTooltipOriginalRight1Font = nil
        end)
        tooltip.VaultloomItemIDTooltipClearHook = true
    end
end

function Runtime:ClearTooltip(tooltip)
    local rightLine = getTooltipRightLineOne(tooltip)
    if not rightLine then
        return
    end

    if tooltip and tooltip.VaultloomItemIDTooltipItemID then
        local originalText = tooltip.VaultloomItemIDTooltipOriginalRight1
        rightLine:SetText(type(originalText) == "string" and originalText or "")
        restoreFont(rightLine, tooltip.VaultloomItemIDTooltipOriginalRight1Font)
        tooltip.VaultloomItemIDTooltipItemID = nil
        tooltip.VaultloomItemIDTooltipOriginalRight1 = nil
        tooltip.VaultloomItemIDTooltipOriginalRight1Font = nil
        if tooltip.Show then
            tooltip:Show()
        end
    end
end

function Runtime:ApplyTooltip(tooltip, data)
    if self.enabled ~= true or not tooltip then
        return
    end

    local itemID = getTooltipItemID(tooltip, data)
    if not itemID then
        return
    end

    local rightLine = getTooltipRightLineOne(tooltip)
    if not rightLine then
        return
    end

    if tooltip.VaultloomItemIDTooltipItemID == itemID then
        return
    end

    ensureTooltipResetHook(tooltip)

    local originalText = rightLine:GetText()
    tooltip.VaultloomItemIDTooltipOriginalRight1 = type(originalText) == "string" and originalText or ""
    tooltip.VaultloomItemIDTooltipOriginalRight1Font = applySmallerFont(rightLine)
    tooltip.VaultloomItemIDTooltipItemID = itemID

    local idText = string.format("|cffdbb85cID %d|r", itemID)
    if tooltip.VaultloomItemIDTooltipOriginalRight1 ~= "" then
        rightLine:SetText(tooltip.VaultloomItemIDTooltipOriginalRight1 .. "  " .. idText)
    else
        rightLine:SetText(idText)
    end
    rightLine:Show()

    if tooltip.Show then
        tooltip:Show()
    end
end

function Runtime:EnsureHooks()
    if self.hooksReady then
        return
    end
    self.hooksReady = true

    if TooltipDataProcessor and TooltipDataProcessor.AddTooltipPostCall and Enum and Enum.TooltipDataType then
        TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Item, function(tooltip, data)
            Runtime:ApplyTooltip(tooltip, data)
        end)
    elseif GameTooltip and GameTooltip.HookScript then
        GameTooltip:HookScript("OnTooltipSetItem", function(tooltip)
            Runtime:ApplyTooltip(tooltip, nil)
        end)
    end
end

function Runtime:SetEnabled(enabled)
    self.enabled = enabled == true
    self:EnsureHooks()

    if not self.enabled and GameTooltip then
        self:ClearTooltip(GameTooltip)
    end
end

ns:RegisterFeatureDefinition(FEATURE_ID, {
    id = FEATURE_ID,
    order = 23,
    category = "inventory",
    title = function() return L.FEATURE_ITEM_ID_TOOLTIP_TITLE or "Item-ID anzeigen" end,
    description = function() return L.FEATURE_ITEM_ID_TOOLTIP_DESCRIPTION or "Zeigt die Item-ID oben rechts im Gegenstands-Tooltip." end,
    note = function() return L.FEATURE_ITEM_ID_TOOLTIP_NOTE or "Praktisch zum Suchen, Debuggen und Teilen von Items." end,
    previewLabel = function() return L.FEATURE_ITEM_ID_TOOLTIP_PREVIEW_LABEL or "Item-Tooltip" end,
    previewNote = function() return L.FEATURE_ITEM_ID_TOOLTIP_PREVIEW_NOTE or "Die ID steht direkt neben dem Itemnamen." end,
    requiresReload = false,
    apply = function(isEnabled)
        Runtime:SetEnabled(isEnabled == true)
    end,
})
