local _, addon = ...

local ENCOUNTER_TAB_ID = 9

local CURRENT_TAB_ID = 0
local PREVIOUS_TAB_ID = 0

local ENCOUNTER_ID = 0
local DIFFICULTY = 0

local TAG_TO_ICON = {
    tank = 0,
    dps = 1,
    healer = 2,
    important = 5,
    mythic = 12,
    interruptible = 6,
    magic = 7,
    curse = 8,
    poison = 9,
    heroic = 3,
    disease = 10,
    deadly = 4,
    enrage = 11
}

local ORIGINALS = {}

local function HideOtherContent()
    local frames = { "overviewScroll", "LootContainer", 'detailsScroll', 'model' }
    for _, frame in ipairs(frames) do
        EncounterJournal.encounter.info[frame]:Hide();
    end

    local tabs = { "overviewTab", "lootTab", "bossTab", "modelTab" }
    for _, tab in ipairs(tabs) do
        EncounterJournal.encounter.info[tab].selected:Hide();
        EncounterJournal.encounter.info[tab].unselected:Show();
        EncounterJournal.encounter.info[tab]:UnlockHighlight();
    end

    if EncounterJournal.encounter.info.creatureButtons then
        for _, button in pairs(EncounterJournal.encounter.info.creatureButtons) do
            button:Hide()
        end
    end

    addon.EncounterFrame:ClearHeaders()
end

local function SetAbilityTagIcon(header, tags)
    local result = {}
    for part in string.gmatch(tags, "([^,]+)") do
        table.insert(result, part)
    end

    for i, tag in pairs(result) do
        local tex = header.button:CreateTexture()
        if i == 1 then
            tex:SetAllPoints(header.button.icon1.icon)
        elseif i == 2 then
            tex:SetAllPoints(header.button.icon2.icon)
        elseif i == 3 then
            tex:SetAllPoints(header.button.icon3.icon)
        end
        tex:SetTexture("Interface/EncounterJournal/UI-EJ-Icons")
        local index = TAG_TO_ICON[string.lower(tag)] or nil
        if index ~= nil then
            EncounterJournal_SetFlagIcon(tex, index)
        end
    end
end

local function SetAbilityIcon(header, name)
    if ORIGINALS[name] == nil then
        return
    end

    local abilityIcon = ORIGINALS[name].abilityIcon or nil
    if abilityIcon then
        header.button.abilityIcon:SetTexture(abilityIcon)
        header.button.abilityIcon:Show()
        header.button.title:SetPoint("TOPLEFT", header, "TOPLEFT", 45, -7);
    end
end

local function SetEncounterPortraitIcon(header, name)
    if ORIGINALS[name] == nil then
        return
    end

    local creatureDisplayID = ORIGINALS[name].creatureDisplayID or 0
    local uiModelSceneID = ORIGINALS[name].uiModelSceneID or 0

    if creatureDisplayID ~= 0 and uiModelSceneID ~= 0 then
        header.button.portrait.displayInfo = creatureDisplayID;
        header.button.portrait.uiModelSceneID = uiModelSceneID;
        SetPortraitTextureFromCreatureDisplayID(header.button.portrait.icon, creatureDisplayID);
        header.button.portrait:Show()
        header.button.title:SetPoint("TOPLEFT", header, "TOPLEFT", 50, -7);
    end
end

local function RenderBossAbilities(data, parent, layer)
    local frame = addon.EncounterFrame

    if not parent.children then
        parent.children = {}
    end

    for _, node in ipairs(data) do
        local name = node.name
        local description = node.description

        if name ~= "" and name ~= "Stage ??" then
            local header = frame:CreateHeader()
            header:SetWidth(frame:GetWidth() - (layer * 20))
            header.button.title:SetText(name)

            SetAbilityIcon(header, name)
            SetEncounterPortraitIcon(header, name)

            local original = ORIGINALS[name]
            if original and original.description then
                header.description:SetText(
                    addon.API.FormatEncounterDescription(description, original.description)
                )
            else
                header.description:SetText(description)
            end

            header.description:SetWidth(header:GetWidth() - 20)

            if description == "" then
                header.empty = true
            end

            table.insert(parent.children, header)

            if node.children and #node.children > 0 then
                RenderBossAbilities(node.children, header, layer + 1)
            end
        else
            -- Skip empty name nodes (usually grouping nodes) but process their children
            if node.children and #node.children > 0 then
                RenderBossAbilities(node.children, parent, layer)
            end
        end
    end
end

local function RenderBossEncounter(bossKey, encounterName)
    local frame = addon.EncounterFrame
    HideOtherContent()

    local bossData = CzechQuestsAddon:GetData('encounter', bossKey)

    frame.summary:SetText(
        addon.API.FormatEncounterDescription(
            bossData.overview,
            ORIGINALS['Overview'] and ORIGINALS['Overview'].description or ""
        )
    )

    local tankHeader = frame:CreateHeader()
    tankHeader.button.title:SetText("Tank")
    local originalTank = ORIGINALS['Tanks'] or ORIGINALS['Tank'] or { description = "" }
    local tankDescription = addon.API.FormatEncounterDescription(bossData.tank, originalTank.description)
    tankHeader.description:SetText(tankDescription)
    tankHeader.description:SetWidth(tankHeader:GetWidth() - 20)
    table.insert(frame.headers, tankHeader)
    SetAbilityTagIcon(tankHeader, 'tank')

    local healHeader = frame:CreateHeader()
    healHeader.button.title:SetText("Healer")
    local originalHealer = ORIGINALS['Healers'] or ORIGINALS['Healer'] or { description = "" }
    local healerDescription = addon.API.FormatEncounterDescription(bossData.healer, originalHealer.description)
    healHeader.description:SetText(healerDescription)
    healHeader.description:SetWidth(healHeader:GetWidth() - 20)
    table.insert(frame.headers, healHeader)
    SetAbilityTagIcon(healHeader, 'healer')

    local dpsHeader = frame:CreateHeader()
    dpsHeader.button.title:SetText("Damage Dealer")
    local originalDps = ORIGINALS['Damage Dealers'] or { description = "" }
    local dpsDescription = addon.API.FormatEncounterDescription(bossData.dps, originalDps.description)
    dpsHeader.description:SetText(dpsDescription)
    dpsHeader.description:SetWidth(dpsHeader:GetWidth() - 20)
    table.insert(frame.headers, dpsHeader)
    SetAbilityTagIcon(dpsHeader, 'dps')

    local bossHeader = frame:CreateHeader()
    bossHeader.button.title:SetText(encounterName)
    bossHeader.empty = true
    table.insert(frame.headers, bossHeader)
    RenderBossAbilities(bossData.abilities, bossHeader, 1)

    frame:GetParent():Show()
    frame:UpdateHeaderPositions()
end

local function StoreBossAbilities()
    ORIGINALS = {}

    local stack, _, _, _, curSectionID = {}, EJ_GetEncounterInfo(ENCOUNTER_ID)
    repeat
        local info = C_EncounterJournal.GetSectionInfo(curSectionID)
        if not info.filteredByDifficulty then
            ORIGINALS[info.title] = {}
            ORIGINALS[info.title].description = info.description
            ORIGINALS[info.title].creatureDisplayID = info.creatureDisplayID
            ORIGINALS[info.title].uiModelSceneID = info.uiModelSceneID
            ORIGINALS[info.title].abilityIcon = info.abilityIcon
        end
        table.insert(stack, info.siblingSectionID)

        if not info.filteredByDifficulty then
            table.insert(stack, info.firstChildSectionID)
        end

        curSectionID = table.remove(stack)
    until not curSectionID
end

local function DetectBossToRender()
    local frame = addon.EncounterFrame

    local encounterName = EJ_GetEncounterInfo(ENCOUNTER_ID)

    local difficulty = 'LFG_RAID' -- 17
    if DIFFICULTY == 14 then
        difficulty = 'NORMAL_RAID'
    elseif DIFFICULTY == 15 then
        difficulty = 'HEROIC_RAID'
    elseif DIFFICULTY == 16 then
        difficulty = 'MYTHIC_RAID'
    elseif DIFFICULTY == 1 then
        difficulty = 'NORMAL_DUNGEON'
    elseif DIFFICULTY == 2 then
        difficulty = 'HEROIC_DUNGEON'
    elseif DIFFICULTY == 23 then
        difficulty = 'MYTHIC_DUNGEON'
    end

    local bossKey = nil
    for i = 1, 10 do
        local id, name = EJ_GetCreatureInfo(i);
        if id then
            local key = name .. "_" .. difficulty
            if addon.data.encounter[key] then
                bossKey = key
                break
            end
        end
    end

    if bossKey then
        StoreBossAbilities()
        RenderBossEncounter(bossKey, encounterName)
    end

    if bossKey == nil then
        frame.summary:SetText("Pro souboj " .. encounterName .. " není vytvořen překlad.")
        frame:GetParent():Show()
    end
end

local function HideEncounterContent()
    addon.EncounterFrame:GetParent():Hide()
end

local function ShowEncounterContent()
    CURRENT_TAB_ID = ENCOUNTER_TAB_ID
    HideOtherContent()

    local frame = addon.EncounterFrame

    frame.tab:SetHighlight(true);

    EncounterJournal.encounter.info.rightShadow:Show()
    EncounterJournal.encounter.info.difficulty:Show()

    DetectBossToRender()
end

local function SetupCustomTab()
    addon.EncounterFrame.tab:SetScript("OnClick", function()
        ShowEncounterContent()
    end)

    hooksecurefunc("EncounterJournal_DisplayEncounter", function(encounterID)
        ENCOUNTER_ID = encounterID
        addon.EncounterFrame.tab:SetActive(true);

        if CURRENT_TAB_ID == ENCOUNTER_TAB_ID then
            ShowEncounterContent()
        end
    end)

    hooksecurefunc("EncounterJournal_DisplayInstance", function()
        addon.EncounterFrame.tab:SetActive(false);
    end)

    hooksecurefunc("EncounterJournal_SetTab", function(tabId)
        if CURRENT_TAB_ID ~= tabId then
            addon.EncounterFrame.tab:SetHighlight(false);
        end

        PREVIOUS_TAB_ID = CURRENT_TAB_ID
        CURRENT_TAB_ID = tabId
        HideEncounterContent()
    end)

    hooksecurefunc("EncounterJournalBossButton_OnClick", function(encounterID)
        if PREVIOUS_TAB_ID == ENCOUNTER_TAB_ID then
            ShowEncounterContent()
        end
    end)

    hooksecurefunc("EncounterJournal_UpdateDifficulty", function(difficulty)
        DIFFICULTY = difficulty
        if PREVIOUS_TAB_ID == ENCOUNTER_TAB_ID and ENCOUNTER_ID then
            ShowEncounterContent()
        end
    end)
end

local function InitEncounters()
    local frame = addon.EncounterFrame

    frame:RegisterEvent("ADDON_LOADED")

    frame:SetScript("OnEvent", function(self, event, addonName)
        if not CzechQuestsAddon_Store.config.ENCOUNTER_ENABLED then
            return
        end

        if addonName == 'Blizzard_EncounterJournal' then
            addon.EncounterFrame:Init()
            SetupCustomTab()
        end
    end)
end
addon.API.InitEncounters = InitEncounters