-- MARK: Mythic+ Dungeon Tab Integration
local ADDON_NAME, NS = ...
local L = LibStub("AceLocale-3.0"):GetLocale("MDungeonTeleports")

local createdButtons = {}
local verticalButtons = {}
local verticalFrame = nil
local pendingVerticalVisibility = nil
local pendingVerticalRebuild = false

local function SetVerticalFrameVisibility(shouldShow)
    if not verticalFrame then return end
    if InCombatLockdown() then
        pendingVerticalVisibility = shouldShow and "show" or "hide"
        return
    end
    if shouldShow then
        verticalFrame:Show()
    else
        verticalFrame:Hide()
    end
    pendingVerticalVisibility = nil
end

-- MARK: Update Tooltip with spell info
local function UpdateGameTooltip(parent, spellID, initialize)
    if not initialize and not GameTooltip:IsOwned(parent) then return end
    
    local onEnter = parent:GetScript("OnEnter")
    if onEnter then
        onEnter(parent)
    end
    
    local spellInfo = C_Spell.GetSpellInfo(spellID)
    local spellName = spellInfo and spellInfo.name
    
    GameTooltip:AddLine(" ")
    GameTooltip:AddLine(spellName or "Teleport to Dungeon", 1, 1, 1)
    
    if InCombatLockdown() then
        GameTooltip:Show()
        return
    end
    if C_SpellBook.IsSpellInSpellBook(spellID) then
        local cd = C_Spell.GetSpellCooldown(spellID)
        if cd and type(cd.duration) == "number" and type(cd.startTime) == "number" then
            if not issecretvalue(cd.duration) and not issecretvalue(cd.startTime) then
                if cd.duration == 0 then
                    GameTooltip:AddLine(L["READY"], 0, 1, 0)
                else
                    local remaining = ceil(cd.startTime + cd.duration - GetTime())
                    GameTooltip:AddLine(SecondsToTime(remaining), 1, 0, 0)
                end
            end
        end
    else
        GameTooltip:AddLine(L["SPELL_NOT_LEARNED"], 1, 0, 0)
    end
    
    GameTooltip:Show()
end

-- MARK: Create Dungeon Button
local function CreateDungeonButton(parent, spellID)
    if not spellID or not parent then return end
    
    local btn = createdButtons[parent]
    if not btn then
        btn = CreateFrame("Button", nil, parent, "InsecureActionButtonTemplate")
        btn:SetAllPoints(parent)
        btn:RegisterForClicks("AnyDown", "AnyUp")
        btn:SetAttribute("type", "spell")
        
        -- Create hover overlay
        local hoverOverlay = btn:CreateTexture(nil, "HIGHLIGHT")
        hoverOverlay:SetAllPoints(btn)
        hoverOverlay:SetColorTexture(0, 0, 0, 0.5)

        -- Dungeon atlas icon (bottom-left)
        local dungeonIcon = btn:CreateTexture(nil, "OVERLAY")
        dungeonIcon:SetAtlas("Dungeon", true)
        dungeonIcon:SetPoint("BOTTOMLEFT", btn, "BOTTOMLEFT", -5, -5)
        dungeonIcon:SetSize(32, 32)
        btn.dungeonIcon = dungeonIcon
        
        createdButtons[parent] = btn
    end
    
    -- Update spell ID
    btn:SetAttribute("spell", spellID)
    
    btn:SetScript("OnEnter", function(self)
        UpdateGameTooltip(parent, spellID, true)
    end)
    
    btn:SetScript("OnLeave", function(self)
        if GameTooltip:IsOwned(parent) then
            GameTooltip:Hide()
        end
    end)
end

-- MARK: Create vertical spell button
local function CreateVerticalSpellButton(parent, data, yOffset)
    local buttonSize = 36
    local button = CreateFrame("Button", nil, parent, "SecureActionButtonTemplate")
    button:SetSize(buttonSize, buttonSize)
    button:SetPoint("TOP", parent, "TOP", 0, yOffset)
    
    button.data = data
    
    local buttonTexture = button:CreateTexture(nil, "BACKGROUND")
    buttonTexture:SetAllPoints(button)
    buttonTexture:SetTexture(data.icon)
    buttonTexture:SetTexCoord(0.07, 0.93, 0.07, 0.93)
    button.buttonTexture = buttonTexture
    
    local cooldownOverlay = button:CreateTexture(nil, "ARTWORK")
    cooldownOverlay:SetAllPoints(button)
    cooldownOverlay:SetTexture("Interface\\Tooltips\\UI-Tooltip-Background")
    cooldownOverlay:SetVertexColor(0, 0, 0, 0.6)
    cooldownOverlay:Hide()
    button.cooldownOverlay = cooldownOverlay
    
    local hoverOverlay = button:CreateTexture(nil, "OVERLAY")
    hoverOverlay:SetAllPoints(button)
    hoverOverlay:SetColorTexture(0, 0, 0, 0.6)
    hoverOverlay:SetDrawLayer("OVERLAY", 0)
    hoverOverlay:Hide()
    button.hoverOverlay = hoverOverlay

    local dungeonIcon = button:CreateTexture(nil, "OVERLAY")
    dungeonIcon:SetAtlas("Dungeon", true)
    dungeonIcon:SetPoint("BOTTOMLEFT", button, "BOTTOMLEFT", 2, 2)
    dungeonIcon:SetSize(14, 14)
    button.dungeonIcon = dungeonIcon
    
    local buttonBorderThickness = 2
    
    local borderTop = button:CreateTexture(nil, "OVERLAY")
    borderTop:SetDrawLayer("OVERLAY", 1)
    borderTop:SetColorTexture(0.05, 0.05, 0.05, 0.8)
    borderTop:SetPoint("TOPLEFT", button, "TOPLEFT", buttonBorderThickness, 0)
    borderTop:SetPoint("TOPRIGHT", button, "TOPRIGHT", -buttonBorderThickness, 0)
    borderTop:SetHeight(buttonBorderThickness)
    button.borderTop = borderTop
    
    local borderBottom = button:CreateTexture(nil, "OVERLAY")
    borderBottom:SetDrawLayer("OVERLAY", 1)
    borderBottom:SetColorTexture(0.05, 0.05, 0.05, 0.8)
    borderBottom:SetPoint("BOTTOMLEFT", button, "BOTTOMLEFT", buttonBorderThickness, 0)
    borderBottom:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -buttonBorderThickness, 0)
    borderBottom:SetHeight(buttonBorderThickness)
    button.borderBottom = borderBottom
    
    local borderLeft = button:CreateTexture(nil, "OVERLAY")
    borderLeft:SetDrawLayer("OVERLAY", 1)
    borderLeft:SetColorTexture(0.05, 0.05, 0.05, 0.8)
    borderLeft:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0)
    borderLeft:SetPoint("BOTTOMLEFT", button, "BOTTOMLEFT", 0, 0)
    borderLeft:SetWidth(buttonBorderThickness)
    button.borderLeft = borderLeft
    
    local borderRight = button:CreateTexture(nil, "OVERLAY")
    borderRight:SetDrawLayer("OVERLAY", 1)
    borderRight:SetColorTexture(0.05, 0.05, 0.05, 0.8)
    borderRight:SetPoint("TOPRIGHT", button, "TOPRIGHT", 0, 0)
    borderRight:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 0, 0)
    borderRight:SetWidth(buttonBorderThickness)
    button.borderRight = borderRight
    
    local buttonText = button:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    buttonText:SetPoint("RIGHT", button, "LEFT", -2, 0)
    buttonText:SetFont(MDungeonTeleports.customFont, 11, "OUTLINE")
    buttonText:SetTextColor(1, 1, 1)
    buttonText:SetText(data.name)
    button.buttonText = buttonText
    
    local cooldownText = button:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    cooldownText:SetPoint("CENTER", button, "CENTER", 0, 0)
    cooldownText:SetTextColor(1, 1, 1)
    cooldownText:SetFont(MDungeonTeleports.customFont, 14, "OUTLINE")
    button.cooldownText = cooldownText
    
    button:SetAttribute("type", "spell")
    button:SetAttribute("spell", data.spellID)
    
    local function UpdateButtonTexture()
        if C_SpellBook.IsSpellInSpellBook(data.spellID) then
            buttonTexture:SetTexture(data.icon)
            buttonTexture:SetTexCoord(0.07, 0.93, 0.07, 0.93)
            buttonTexture:SetDesaturated(false)
        else
            buttonTexture:SetTexture(data.icon)
            buttonTexture:SetTexCoord(0.07, 0.93, 0.07, 0.93)
            buttonTexture:SetDesaturated(true)
        end
    end
    
    button.UpdateButtonTexture = UpdateButtonTexture
    button.UpdateCooldownText = UpdateCooldownText
    UpdateButtonTexture()
    
    local function UpdateCooldownText(self, spellID)
        if InCombatLockdown() then return end
        if not spellID or not C_SpellBook.IsSpellInSpellBook(spellID) then
            cooldownText:SetText("")
            cooldownOverlay:Hide()
            return
        end
        local cd = C_Spell.GetSpellCooldown(spellID)
        if not cd then
            cooldownText:SetText("")
            cooldownOverlay:Hide()
            return
        end
        
        -- Skip if values are secret
        if issecretvalue(cd.duration) or issecretvalue(cd.startTime) then
            return
        end
        
        if cd.duration and cd.startTime and cd.duration > 5 then
            local remaining = ceil(cd.startTime + cd.duration - GetTime())
            if remaining > 5 then
                if remaining >= 3600 then
                    cooldownText:SetText(string.format("%dh", ceil(remaining / 3600)))
                elseif remaining >= 60 then
                    cooldownText:SetText(string.format("%dm", ceil(remaining / 60)))
                else
                    cooldownText:SetText(string.format("%d", remaining))
                end
                cooldownOverlay:Show()
            else
                cooldownText:SetText("")
                cooldownOverlay:Hide()
            end
        else
            cooldownText:SetText("")
            cooldownOverlay:Hide()
        end
    end
    
    local function OnEvent(self, event)
        if event == "SPELLS_CHANGED" or event == "PLAYER_ENTERING_WORLD" or event == "CHALLENGE_MODE_COMPLETED" then
            UpdateButtonTexture()
            UpdateCooldownText(self, data.spellID)
        end
    end
    
    button:SetScript("OnEnter", function(self)
        hoverOverlay:Show()
    end)
    
    button:SetScript("OnLeave", function(self)
        hoverOverlay:Hide()
    end)
    
    button:RegisterEvent("CHALLENGE_MODE_COMPLETED")
    button:RegisterEvent("PLAYER_ENTERING_WORLD")
    button:RegisterEvent("SPELLS_CHANGED")
    button:RegisterForClicks("AnyUp", "AnyDown")
    button:SetScript("OnEvent", OnEvent)
    
    button.cooldownTicker = C_Timer.NewTicker(1, function()
        UpdateCooldownText(button, data.spellID)
    end)
    
    return button
end

-- MARK: Create vertical button frame
local function CreateVerticalButtonFrame()
    if not ChallengesFrame then return end
    if InCombatLockdown() then
        pendingVerticalRebuild = true
        pendingVerticalVisibility = MDungeonTeleports.mythicTabVertical and "show" or "hide"
        return
    end
    if not MDungeonTeleports.mythicTabVertical then
        if verticalFrame then
            SetVerticalFrameVisibility(false)
        end
        return
    end
    
    if not verticalFrame then
        verticalFrame = CreateFrame("Frame", "MDT_MythicVerticalButtons", ChallengesFrame)
        verticalFrame:SetSize(40, 320)
        verticalFrame:SetPoint("TOPRIGHT", ChallengesFrame, "TOPRIGHT", -10, -20)
    end
    
    for _, btn in ipairs(verticalButtons) do
        btn:Hide()
        btn:SetParent(nil)
    end
    wipe(verticalButtons)
    
    local yOffset = -10
    local spacing = -38
    
    if MDT_Season1Row1 then
        for i, data in ipairs(MDT_Season1Row1) do
            local btn = CreateVerticalSpellButton(verticalFrame, data, yOffset)
            table.insert(verticalButtons, btn)
            yOffset = yOffset + spacing
        end
    end
    
    if MDT_Season1Row2 then
        for i, data in ipairs(MDT_Season1Row2) do
            local btn = CreateVerticalSpellButton(verticalFrame, data, yOffset)
            table.insert(verticalButtons, btn)
            yOffset = yOffset + spacing
        end
    end

    SetVerticalFrameVisibility(true)
end

-- MARK: Button Toggles
function MDTToggleMythicVerticalButtons()
    if MDungeonTeleports.mythicTabVertical then
        CreateVerticalButtonFrame()
    else
        if verticalFrame then
            SetVerticalFrameVisibility(false)
        end
    end
end

-- Toggle dungeon icon buttons visibility
function MDTToggleMythicIconButtons()
    if not ChallengesFrame or not ChallengesFrame.DungeonIcons then return end
    
    if MDungeonTeleports.mythicTabButtons then
        for _, icon in pairs(ChallengesFrame.DungeonIcons) do
            local mapID = icon.mapID
            local spellID = MDT_MYTHIC_TAB[mapID]
            
            if spellID then
                CreateDungeonButton(icon, spellID)
                local btn = createdButtons[icon]
                if btn then
                    btn:Show()
                end
            end
        end
    else
        for _, icon in pairs(ChallengesFrame.DungeonIcons) do
            local btn = createdButtons[icon]
            if btn then
                btn:Hide()
            end
        end
    end
end

-- MARK: Vertical Font Update
function MDTUpdateMythicVerticalFont()
    local customFont = MDungeonTeleports.customFont
    
    for _, button in ipairs(verticalButtons) do
        if button.buttonText then
            button.buttonText:SetFont(customFont, 11, "OUTLINE")
        end
        if button.cooldownText then
            button.cooldownText:SetFont(customFont, 14, "OUTLINE")
        end
    end
end

-- MARK: Create all dungeon buttons
local function CreateDungeonButtons()
    if InCombatLockdown() then return end
    if not ChallengesFrame or not ChallengesFrame.DungeonIcons then return end
    if not MDungeonTeleports.mythicTabButtons then return end
    
    for _, icon in pairs(ChallengesFrame.DungeonIcons) do
        local mapID = icon.mapID
        local spellID = MDT_MYTHIC_TAB[mapID]
        
        if spellID then
            CreateDungeonButton(icon, spellID)
        end
    end
    
    if MDungeonTeleports.mythicTabVertical then
        CreateVerticalButtonFrame()
    end
end

-- MARK: Initialize
local function Initialize()
    if not C_AddOns.IsAddOnLoaded("Blizzard_ChallengesUI") then
        return false
    end

    if not ChallengesFrame then
        return false
    end

    if type(ChallengesFrame.Update) == "function" then
        hooksecurefunc(ChallengesFrame, "Update", function()
            CreateDungeonButtons()
            -- Always enforce visibility state after update
            if not MDungeonTeleports.mythicTabVertical and verticalFrame then
                SetVerticalFrameVisibility(false)
            end
            if not MDungeonTeleports.mythicTabButtons and ChallengesFrame.DungeonIcons then
                for _, icon in pairs(ChallengesFrame.DungeonIcons) do
                    local btn = createdButtons[icon]
                    if btn then btn:Hide() end
                end
            end
        end)

        -- Hook hide to hide vertical frame
        hooksecurefunc(ChallengesFrame, "Hide", function()
            if verticalFrame then
                SetVerticalFrameVisibility(false)
            end
        end)

        CreateDungeonButtons()
        -- Enforce state on load
        if not MDungeonTeleports.mythicTabVertical and verticalFrame then
            SetVerticalFrameVisibility(false)
        end
        if not MDungeonTeleports.mythicTabButtons and ChallengesFrame.DungeonIcons then
            for _, icon in pairs(ChallengesFrame.DungeonIcons) do
                local btn = createdButtons[icon]
                if btn then btn:Hide() end
            end
        end
    end

    return true
end

-- MARK: Event Handler
local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:RegisterEvent("PLAYER_LOGIN")
eventFrame:RegisterEvent("PLAYER_REGEN_ENABLED")

eventFrame:SetScript("OnEvent", function(self, event, addonName)
    if event == "ADDON_LOADED" and addonName == "Blizzard_ChallengesUI" then
        if Initialize() then
            self:UnregisterEvent("ADDON_LOADED")
        end
    elseif event == "PLAYER_LOGIN" then
        Initialize()
    elseif event == "PLAYER_REGEN_ENABLED" then
        if pendingVerticalRebuild then
            pendingVerticalRebuild = false
            CreateVerticalButtonFrame()
        elseif pendingVerticalVisibility then
            SetVerticalFrameVisibility(pendingVerticalVisibility == "show")
        end
    end
end)

-- MARK: Combat Lockdown Event Management
local function SetButtonEventsEnabled(enabled)
    local allButtons = {}
    for _, btn in ipairs(verticalButtons) do
        table.insert(allButtons, btn)
    end
    for _, button in ipairs(allButtons) do
        if enabled then
            button:RegisterEvent("SPELLS_CHANGED")
            if button.cooldownTicker then
                button.cooldownTicker:Cancel()
                button.cooldownTicker = C_Timer.NewTicker(1, function()
                    local UpdateCooldownText = button.UpdateCooldownText
                    if UpdateCooldownText then
                        UpdateCooldownText(button, button.data.spellID)
                    end
                end)
            end
        else
            button:UnregisterEvent("SPELLS_CHANGED")
            if button.cooldownTicker then
                button.cooldownTicker:Cancel()
            end
        end
    end
end

local combatFrame = CreateFrame("Frame")
combatFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
combatFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
combatFrame:SetScript("OnEvent", function(self, event)
    if event == "PLAYER_REGEN_DISABLED" then
        SetButtonEventsEnabled(false)
    elseif event == "PLAYER_REGEN_ENABLED" then
        SetButtonEventsEnabled(true)
    end
end)
