local ns = _G.WoWTranslate_UK_NS

local translator = setmetatable({}, { __index = ns.BaseTranslator })
translator.IsEnabled = translator.IsEnabled or function() return true end
ns.TranslationsManager:Add(translator)

local function TranslateUnitName(self)
    if InCombatLockdown and InCombatLockdown() then return end
    if not self.name or not self.unit then return end
    if ns.isProtectedFrame and ns.isProtectedFrame(self.name) then return end

    local ok, unitName = pcall(UnitName, self.unit)
    if not ok or not unitName or type(unitName) ~= "string" then return end

    local translated = ns.GetTranslation and ns.GetTranslation(unitName)
    if translated and translated ~= unitName then
        self.name._wt_updating = true
        pcall(self.name.SetText, self.name, translated)
        self.name._wt_updating = nil
        self.name._wt_tr = translated
        self.name._wt_orig = unitName
        if ns.hasCyrillic and ns.hasCyrillic(translated) and self.name.SetFont then
            if InCombatLockdown and InCombatLockdown() then return end
            local ok_f, fontFile, height, flags = pcall(self.name.GetFont, self.name)
            if ok_f and fontFile and ns.needsCyrillicFont(fontFile) then
                local chosen = ns.selectFontForContext and ns.selectFontForContext(fontFile) or ns.PreferredFont
                pcall(self.name.SetFont, self.name, chosen, height or 13, flags or "")
            end
        end
    end
end

local function TranslateCompactUnitName(frame)
    if InCombatLockdown and InCombatLockdown() then return end
    if not frame or not frame.unit then return end
    if ns.isProtectedFrame and ns.isProtectedFrame(frame) then return end

    local ok, unitName = pcall(UnitName, frame.unit)
    if not ok or not unitName or type(unitName) ~= "string" then return end

    local translated = ns.GetTranslation and ns.GetTranslation(unitName)
    if not translated then return end

    if frame.name then
        pcall(function()
            local ok_t, cur = pcall(frame.name.GetText, frame.name)
            if ok_t and cur ~= translated then
                frame.name._wt_updating = true
                pcall(frame.name.SetText, frame.name, translated)
                frame.name._wt_updating = nil
                frame.name._wt_tr = translated
                frame.name._wt_orig = unitName
                if ns.hasCyrillic and ns.hasCyrillic(translated) and frame.name.SetFont then
                    if InCombatLockdown and InCombatLockdown() then return end
                    local ok_f, fontFile, height, flags = pcall(frame.name.GetFont, frame.name)
                    if ok_f and fontFile and ns.needsCyrillicFont(fontFile) then
                        local chosen = ns.selectFontForContext and ns.selectFontForContext(fontFile) or ns.PreferredFont
                        pcall(frame.name.SetFont, frame.name, chosen, height or 12, flags or "")
                    end
                end
            end
        end)
    end

    if frame.Name then
        pcall(function()
            local ok_t, cur = pcall(frame.Name.GetText, frame.Name)
            if ok_t and cur ~= translated then
                frame.Name._wt_updating = true
                pcall(frame.Name.SetText, frame.Name, translated)
                frame.Name._wt_updating = nil
                frame.Name._wt_tr = translated
                frame.Name._wt_orig = unitName
                if ns.hasCyrillic and ns.hasCyrillic(translated) and frame.Name.SetFont then
                    if InCombatLockdown and InCombatLockdown() then return end
                    local ok_f, fontFile, height, flags = pcall(frame.Name.GetFont, frame.Name)
                    if ok_f and fontFile and ns.needsCyrillicFont(fontFile) then
                        local chosen = ns.selectFontForContext and ns.selectFontForContext(fontFile) or ns.PreferredFont
                        pcall(frame.Name.SetFont, frame.Name, chosen, height or 12, flags or "")
                    end
                end
            end
        end)
    end
end

local function TranslateTargetOfTarget()
    if InCombatLockdown and InCombatLockdown() then return end

    if TargetFrame and TargetFrame.totFrame then
        TranslateUnitName(TargetFrame.totFrame)
    end
    if FocusFrame and FocusFrame.totFrame then
        TranslateUnitName(FocusFrame.totFrame)
    end
end

function translator:Init()
    pcall(function()
        if UnitFrame_Update then
            hooksecurefunc("UnitFrame_Update", TranslateUnitName)
        end
    end)

    pcall(function()
        if CompactUnitFrame_UpdateName then
            hooksecurefunc("CompactUnitFrame_UpdateName", TranslateCompactUnitName)
        end
    end)

    pcall(function()
        if CompactUnitFrame_UpdateAll then
            hooksecurefunc("CompactUnitFrame_UpdateAll", function(frame)
                TranslateCompactUnitName(frame)
            end)
        end
    end)

    local UFEventCatcher = CreateFrame("Frame")
    UFEventCatcher:RegisterEvent("PLAYER_TARGET_CHANGED")
    UFEventCatcher:RegisterEvent("PLAYER_FOCUS_CHANGED")
    UFEventCatcher:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT")
    UFEventCatcher:SetScript("OnEvent", function()
        if InCombatLockdown and InCombatLockdown() then return end

        C_Timer.After(0.05, function()
            if TargetFrame then TranslateUnitName(TargetFrame) end
            if FocusFrame then TranslateUnitName(FocusFrame) end

            for i = 1, 5 do
                local bossFrame = _G["Boss" .. i .. "TargetFrame"]
                if bossFrame then TranslateUnitName(bossFrame) end
            end

            for i = 1, 4 do
                local partyFrame = _G["PartyMemberFrame" .. i]
                if partyFrame then TranslateUnitName(partyFrame) end
            end

            TranslateTargetOfTarget()
        end)
    end)

    C_Timer.After(3, function()
        if TargetFrame then TranslateUnitName(TargetFrame) end
        if FocusFrame then TranslateUnitName(FocusFrame) end
    end)
end
