local ns = _G.WoWTranslate_UK_NS

ns.BaseTooltipTranslator = ns.BaseTooltipTranslator or {}

local tooltipPatterns = {
    {"^Level (%d+)$", "Рівень %1"},
    {"^Level (%d+) (.+)$", "Рівень %1 %2"},
    {"^(%d+) yd range$", "%1 м дальність"},
    {"(%d+) yd range", "%1 м дальність"},
    {"(%d+) yd$", "%1 м"},
    {"(%d+) yd", "%1 м"},
    {"^(%d+) sec recharge$", "%1 с перезарядка"},
    {"(%d+) sec recharge", "%1 с перезарядка"},
    {"(%d+) sec cooldown$", "%1 с перезарядка"},
    {"(%d+) sec cooldown", "%1 с перезарядка"},
    {"(%d+) sec duration", "%1 с тривалість"},
    {"(%d+) min cooldown", "%1 хв перезарядка"},
    {"(%d+) min duration", "%1 хв тривалість"},
    {"(%d+) sec cast", "%1 с застосування"},
    {"^Instant$", "Миттєвий"},
    {"dealing (%d+) Physical damage", "завдаючи %1 фізичної шкоди"},
    {"dealing (%d+) Holy damage", "завдаючи %1 святої шкоди"},
    {"dealing (%d+) Fire damage", "завдаючи %1 вогняної шкоди"},
    {"dealing (%d+) Frost damage", "завдаючи %1 крижаної шкоди"},
    {"dealing (%d+) Nature damage", "завдаючи %1 природної шкоди"},
    {"dealing (%d+) Shadow damage", "завдаючи %1 тіньової шкоди"},
    {"dealing (%d+) Arcane damage", "завдаючи %1 тайної шкоди"},
    {"dealing (%d+) Elemental damage", "завдаючи %1 стихійної шкоди"},
    {"dealing (%d+) Chaotic damage", "завдаючи %1 хаотичної шкоди"},
    {"dealing (%d+) damage", "завдаючи %1 шкоди"},
    {"(%d+) Physical damage", "%1 фізичної шкоди"},
    {"(%d+) Holy damage", "%1 святої шкоди"},
    {"(%d+) Fire damage", "%1 вогняної шкоди"},
    {"(%d+) Frost damage", "%1 крижаної шкоди"},
    {"(%d+) Nature damage", "%1 природної шкоди"},
    {"(%d+) Shadow damage", "%1 тіньової шкоди"},
    {"(%d+) Arcane damage", "%1 тайної шкоди"},
    {"(%d+) Elemental damage", "%1 стихійної шкоди"},
    {"(%d+) Chaotic damage", "%1 хаотичної шкоди"},
    {"for (%d+) damage", "на %1 шкоди"},
    {"over (%d+) sec", "протягом %1 с"},
    {"every (%d+) sec", "кожні %1 с"},
    {"within (%d+) yd", "в радіусі %1 м"},
    {"up to (%d+) yd", "до %1 м"},
    {"(%d+) yard radius", "%1 м радіус"},
    {"(%d+) yard range", "%1 м дальність"},
    {"^%+(%d+) (.+)$", "+%1 %2"},
    {"^%-(%d+) (.+)$", "-%1 %2"},
    {"heals? (%w+) for (%d+)", "зцілює %1 на %2"},
    {"healing for (%d+)", "зцілює на %1"},
    {"restoring (%d+) health", "відновлює %1 здоров'я"},
    {"restoring (%d+)", "відновлює %1"},
    {"absorbing (%d+) damage", "поглинає %1 шкоди"},
    {"gain (%d+) (%w+)", "отримує %1 %2"},
    {"increases? your (%w+) by (%d+)%%$", "збільшує ваш %1 на %2%%"},
    {"decreases? your (%w+) by (%d+)%%$", "зменшує ваш %1 на %2%%"},
    {"increases? (%w+) by (%d+)%%$", "збільшує %1 на %2%%"},
    {"reduces? (%w+) by (%d+)%%$", "зменшує %1 на %2%%"},
    {"reduces? the cooldown of", "зменшує перезарядку"},
    {"increases? the duration of", "збільшує тривалість"},
    {"reduces? the cast time of", "зменшує час застосування"},
    {"(%d+) damage per sec", "%1 шкоди за с"},
    {"(%d+) per sec", "%1 за с"},
    {"(%d+) per min", "%1 за хв"},
    {"lasts (%d+) sec", "триває %1 с"},
    {"lasts (%d+) min", "триває %1 хв"},
    {"for (%d+) sec", "на %1 с"},
    {"for (%d+) min", "на %1 хв"},
    {"increased by (%d+)%%$", "збільшено на %1%%"},
    {"reduced by (%d+)%%$", "зменшено на %1%%"},
    {"chance to deal (%d+)", "шанс завдати %1"},
    {"(%d+)%% chance", "%1%% шанс"},
    {"critical strike chance", "шанс критичного удару"},
    {"haste by (%d+)%%$", "швидкість на %1%%"},
    {"mastery by (%d+)%%$", "майстерність на %1%%"},
    {"versatility by (%d+)%%$", "універсальність на %1%%"},
    {"movement speed by (%d+)%%$", "швидкість руху на %1%%"},
    {"attack speed by (%d+)%%$", "швидкість атаки на %1%%"},
    {"damage and healing by (%d+)%%$", "шкоду та зцілення на %1%%"},
    {"damage by (%d+)%%$", "шкоду на %1%%"},
    {"healing by (%d+)%%$", "зцілення на %1%%"},
    {"stamina by (%d+)%%$", "витривалість на %1%%"},
    {"armor by (%d+)%%$", "броню на %1%%"},
    {"maximum health by (%d+)%%$", "макс. здоров'я на %1%%"},
    {"maximum mana by (%d+)%%$", "макс. ману на %1%%"},
    {"^%+(%d+) Stamina$", "+%1 Витривалість"},
    {"^%+(%d+) Strength$", "+%1 Сила"},
    {"^%+(%d+) Agility$", "+%1 Спритність"},
    {"^%+(%d+) Intellect$", "+%1 Інтелект"},
    {"^%+(%d+) Spirit$", "+%1 Дух"},
    {"^%+(%d+) Critical Strike$", "+%1 Критичний удар"},
    {"^%+(%d+) Haste$", "+%1 Швидкість"},
    {"^%+(%d+) Mastery$", "+%1 Майстерність"},
    {"^%+(%d+) Versatility$", "+%1 Універсальність"},
    {"^%+(%d+) Leech$", "+%1 Вампіризм"},
    {"^%+(%d+) Avoidance$", "+%1 Уникнення"},
    {"^%+(%d+) Speed$", "+%1 Швидкість"},
    {"^%+(%d+) Armor$", "+%1 Броня"},
    {"^%+(%d+) Damage$", "+%1 Урон"},
    {"^%+(%d+) Healing$", "+%1 Зцілення"},
    {"^%+(%d+) Attack Power$", "+%1 Сила атаки"},
    {"^%+(%d+) Spell Power$", "+%1 Сила закляття"},
    {"^%+(%d+) PvP Power$", "+%1 Сила PvP"},
    {"^%+(%d+) Resilience$", "+%1 Стійкість"},
    {"^%+(%d+) Block$", "+%1 Блокування"},
    {"^%-(%d+) Stamina$", "-%1 Витривалість"},
    {"^%-(%d+) Strength$", "-%1 Сила"},
    {"^%-(%d+) Agility$", "-%1 Спритність"},
    {"^%-(%d+) Intellect$", "-%1 Інтелект"},
    {"^%+(%d+) .+$", "+%1 %2"},
    {"^%-(%d+) .+$", "-%1 %2"},
    {"^Armor: (%d+)$", "Броня: %1"},
    {"^Block: (%d+)$", "Блокування: %1"},
    {"^Damage: (%d+)$", "Урон: %1"},
    {"^Healing: (%d+)$", "Зцілення: %1"},
    {"^Speed: (%d+)$", "Швидкість: %1"},
    {"^DPS: (%d+)$", "УЗС: %1"},
    {"^Power: (%d+)$", "Сила: %1"},
    {"^Stamina: (%d+)$", "Витривалість: %1"},
    {"^Strength: (%d+)$", "Сила: %1"},
    {"^Agility: (%d+)$", "Спритність: %1"},
    {"^Intellect: (%d+)$", "Інтелект: %1"},
    {"^Spirit: (%d+)$", "Дух: %1"},
    {"^Critical Strike: (%d+)$", "Критичний удар: %1"},
    {"^Haste: (%d+)$", "Швидкість: %1"},
    {"^Mastery: (%d+)$", "Майстерність: %1"},
    {"^Versatility: (%d+)$", "Універсальність: %1"},
    {"^Leech: (%d+)$", "Вампіризм: %1"},
    {"^Avoidance: (%d+)$", "Уникнення: %1"},
    {"^%.%.%. and (.+) more$", "...та ще %1"},
    {"^Damage Done$", "Шкода завдана"},
    {"^Damage Taken$", "Шкода отримана"},
    {"^Healing Done$", "Зцілення завдане"},
    {"^Killing Blows$", "Летальні удари"},
    {"^Deaths$", "Смерті"},
    {"^Duration$", "Тривалість"},
    {"^Cooldown$", "Перезарядка"},
    {"^Category: (.+)$", "Категорія: %1"},
    {"^Contribution: (.+)$", "Внесок: %1"},
}

local tooltipCache = {}
local TOOLTIP_CACHE_MAX = 4096
local tooltipCacheCount = 0

local function sanitizeTooltipText(rawText)
    if type(rawText) ~= "string" or rawText == "" then
        return rawText, "", "", false
    end

    local colorPrefix = rawText:match("^(|c%x%x%x%x%x%x%x%x)") or ""
    local colorSuffix = rawText:match("(|r)$") or ""

    local clean = rawText:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "")

    local isTitle = false
    if clean:match("^<.+>$") then
        isTitle = true
        clean = clean:sub(2, -2)
    end

    return clean, colorPrefix, colorSuffix, isTitle
end

local function reassembleTooltip(translated, colorPrefix, colorSuffix, isTitle)
    if not translated then return nil end
    if isTitle then
        translated = "<" .. translated .. ">"
    end
    if colorPrefix ~= "" or colorSuffix ~= "" then
        translated = colorPrefix .. translated .. colorSuffix
    end
    return translated
end

local function postProcessTooltipLine(text)
    if type(text) ~= "string" or text == "" then return text end
    if #text > 60 then return text end
    for _, rule in ipairs(tooltipPatterns) do
        text = text:gsub(rule[1], rule[2])
    end
    return text
end

local function processLine(fontString)
    if not fontString then return end
    pcall(function()
        if InCombatLockdown and InCombatLockdown() then return end
        if ns.isProtectedFrame and ns.isProtectedFrame(fontString) then return end
        local ok_gt, text = pcall(fontString.GetText, fontString)
        if not ok_gt or type(text) ~= "string" or text == "" then return end

        local ok_cmp_tr, already = pcall(function() return fontString._wt_tr == text end)
        if ok_cmp_tr and already then return end

        local ok_cmp_orig, orig_match = pcall(function() return fontString._wt_orig == text end)
        if ok_cmp_orig and orig_match and fontString._wt_tr then
            fontString._wt_updating = true
            fontString:SetText(fontString._wt_tr)
            fontString._wt_updating = nil
            return
        end

        local cacheHit = tooltipCache[text]
        if cacheHit ~= nil then
            if cacheHit and cacheHit ~= text then
                fontString._wt_updating = true
                fontString:SetText(cacheHit)
                fontString._wt_updating = nil
                fontString._wt_tr = cacheHit
                fontString._wt_orig = text
            end
            return
        end

        local cleanText, colorPrefix, colorSuffix, isTitle = sanitizeTooltipText(text)

        local translated = nil

        translated = ns.GetTranslation and ns.GetTranslation(cleanText)

        if not translated then
            local processed = postProcessTooltipLine(cleanText)
            if processed ~= cleanText then
                translated = processed
            end
        end

        if not translated then
            translated = ns.GetTranslation and ns.GetTranslation(text)
        end

        if translated and translated ~= cleanText then
            if cleanText ~= text then
                translated = reassembleTooltip(translated, colorPrefix, colorSuffix, isTitle)
            end
            if ns.resolvePlaceholders then
                translated = ns.resolvePlaceholders(translated)
            end
            if tooltipCacheCount >= TOOLTIP_CACHE_MAX then wipe(tooltipCache); tooltipCacheCount = 0 end
            tooltipCache[text] = translated; tooltipCacheCount = tooltipCacheCount + 1

            fontString._wt_updating = true
            fontString:SetText(translated)
            fontString._wt_updating = nil
            fontString._wt_tr = translated
            fontString._wt_orig = text
        else
            if tooltipCacheCount >= TOOLTIP_CACHE_MAX then wipe(tooltipCache); tooltipCacheCount = 0 end
            tooltipCache[text] = false; tooltipCacheCount = tooltipCacheCount + 1
        end
    end)
end

function ns.ClearTooltipCache()
    wipe(tooltipCache)
    tooltipCacheCount = 0
end

local function translateTooltipLines(tooltip)
    if not tooltip then return end
    local name = tooltip.GetName and tooltip:GetName()
    if not name then return end
    for i = 1, tooltip:NumLines() do
        processLine(_G[name .. "TextLeft" .. i])
        processLine(_G[name .. "TextRight" .. i])
    end
end
ns.TranslateTooltipLines = translateTooltipLines

function ns.BaseTooltipTranslator:Init()
    if not self.tooltipDataType then return end
    if not TooltipDataProcessor or not Enum or not Enum.TooltipDataType then return end
    TooltipDataProcessor.AddTooltipPostCall(self.tooltipDataType, function(tooltip)
        translateTooltipLines(tooltip)
    end)
end

pcall(function()
    if TooltipDataProcessor and Enum and Enum.TooltipDataType then
        local extraTypes = {
            "Macro", "Recipe", "EquipmentSet", "PetAction", "Currency",
            "Achievement", "TraitNode", "TraitEntry", "AzeriteEssence",
            "AzeritePower", "Corruption", "RuneforgeLegendaryPower",
            "Transmog", "Mount", "Pet", "Toy", "BattlePet",
            "BattlePetAbility", "Conduit", "CovenantAbility",
            "ProfessionCrafting", "ProfessionEquipment",
        }
        for _, typeName in ipairs(extraTypes) do
            local dt = Enum.TooltipDataType[typeName]
            if dt then
                TooltipDataProcessor.AddTooltipPostCall(dt, function(tooltip)
                    translateTooltipLines(tooltip)
                end)
            end
        end
    end
end)

pcall(function()
    if ClassTalentTooltip then
        pcall(hooksecurefunc, ClassTalentTooltip, "Show", function(self)
            C_Timer.After(0.01, function()
                if not self then return end
                local ok, regions = pcall(function()
                    local t = {self:GetRegions()}
                    return t
                end)
                if ok and type(regions) == "table" then
                    for _, region in ipairs(regions) do
                        local ok_ot, ot = pcall(region.GetObjectType, region)
                        if ok_ot and ot == "FontString" then
                            ns.TranslateTextObject(region)
                        end
                    end
                end
            end)
        end)
    end
end)
