---@class AddonPrivate
local Private = select(2, ...)

---@class TranslationUtils
local translationUtils = {
    debug = false
}
Private.TranslationUtils = translationUtils

local const = Private.constants

---@param input string|table
---@return string translatedText
function translationUtils:TranslateText(input)
    if issecretvalue(input) then return input end
    if not input or input == "" then return input end

    for k, v in pairs(const.DICT.WORDS) do
        local pattern = "%f[%a]" .. k .. "%f[%A]"
        if self.debug then
            -- Insert safe placeholders instead of color codes
            input = input:gsub(pattern, const.DICT.MARK_START .. k .. const.DICT.MARK_MID .. v .. const.DICT.MARK_END)
        else
            input = input:gsub(pattern, v)
        end
    end

    for k, v in pairs(const.DICT.PARTIALS) do
        if self.debug then
            input = input:gsub(k, const.DICT.MARK_START .. k .. const.DICT.MARK_MID .. v .. const.DICT.MARK_END)
        else
            input = input:gsub(k, v)
        end
    end

    -- After all loops finish, convert the placeholders into the actual UI color codes
    if self.debug then
        input = input:gsub(const.DICT.MARK_START, "|cFFe74c3c[")
        input = input:gsub(const.DICT.MARK_MID, "]|r->|cFF1abc9c")
        input = input:gsub(const.DICT.MARK_END, "|r")
    end

    return input
end

---@param fontstring FontString
function translationUtils:TranslateFontstring(fontstring)
    if not fontstring or not fontstring.GetText then return end

    local originalText = fontstring:GetText()
    if not originalText or originalText == "" then return end

    local translatedText = self:TranslateText(originalText)
    if translatedText ~= originalText then
        fontstring:SetText(translatedText)
    end
end

---@param addon DeTrollify
---@param event WowEvent
---@param ... any
function translationUtils:OnEvent(addon, event, ...)
    local frames = const.EVENTS_FRAMES[event]
    if not frames then return end
    for _, frameName in ipairs(frames) do
        local frame = _G[frameName]
        if frame and frame.GetText then
            self:TranslateFontstring(frame)
        end
    end

    if event == "GOSSIP_SHOW" then
        local gfTarget = GossipFrame.GreetingPanel.ScrollBox.ScrollTarget
        if gfTarget then
            for _, child in ipairs({ gfTarget:GetChildren() }) do
                if child and child.GreetingText then
                    self:TranslateFontstring(child.GreetingText)
                end
            end
        end
    end
end

function translationUtils:ApplyChatFilter()
    for i = 1, 10 do
        local chatFrame = _G["ChatFrame" .. i]
        if chatFrame and chatFrame.AddMessage then
            local originalAddMessage = chatFrame.AddMessage
            chatFrame.AddMessage = function(cf, text, ...)
                local translatedText = translationUtils:TranslateText(text)
                return originalAddMessage(cf, translatedText, ...)
            end
        end
    end
end

function translationUtils:Init()
    local addon = Private.Addon

    for event in pairs(const.EVENTS_FRAMES) do
        addon:RegisterEvent(event, "TranslationUtils_On" .. event, self.OnEvent, { self })
    end

    hooksecurefunc(_G, "QuestMapFrame_ShowQuestDetails", function()
        self:TranslateFontstring(QuestInfoDescriptionText)
    end)

    hooksecurefunc(TalkingHeadFrame.TextFrame.Text, "SetText", function(fSelf, text)
        if fSelf.isTranslating then return end
        fSelf.isTranslating = true

        self:TranslateFontstring(fSelf)

        fSelf.isTranslating = false
    end)

    addon:RegisterCommand({
        "dtdebug",
    }, function()
        self.debug = not self.debug
        print(("DeTrollify debug mode %s"):format(self.debug and "|cFF1abc9cenabled|r" or "|cFFe74c3cdisabled|r"))
    end)

    self:ApplyChatFilter()
end
