local _, _ns = ...
local AC = _G.ArenaCore

-- =============================================================================
-- Core/SafeQueue.lua - Safe Queue timer bar system
-- ported from Shade addon with ArenaCore conventions
-- because missing queue pops is the worst feeling in the world
-- =============================================================================

function AC:CreateSafeQueueTimerBar(parent)
    if not parent then return nil end

    local container = CreateFrame("Frame", nil, parent)
    container:SetSize(280, 42)
    container:SetPoint("TOP", parent, "BOTTOM", 0, -8)
    container:SetFrameStrata("DIALOG")
    container:SetFrameLevel(parent:GetFrameLevel() + 5)

    local bar = CreateFrame("StatusBar", nil, container)
    bar:SetSize(280, 24)
    bar:SetPoint("TOP", container, "TOP", 0, 0)
    bar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
    bar:SetStatusBarColor(0.2, 0.8, 0.2, 0.8)
    bar:SetMinMaxValues(0, 1)

    -- 2px black border
    local border = CreateFrame("Frame", nil, bar, "BackdropTemplate")
    border:SetAllPoints(bar)
    border:SetFrameLevel(bar:GetFrameLevel() + 1)
    border:SetBackdrop({
        edgeFile = "Interface\\Buttons\\WHITE8X8",
        edgeSize = 2,
        insets = { left = 0, right = 0, top = 0, bottom = 0 }
    })
    border:SetBackdropBorderColor(0, 0, 0, 1)

    local bg = bar:CreateTexture(nil, "BACKGROUND")
    bg:SetAllPoints()
    bg:SetColorTexture(0.1, 0.1, 0.1, 0.9)

    local text = bar:CreateFontString(nil, "OVERLAY")
    text:SetAllPoints(bar)
    text:SetJustifyH("CENTER")
    text:SetJustifyV("MIDDLE")
    text:SetTextColor(1, 1, 1, 1)
    if text.SetFont then
        text:SetFont(AC.FONT_PATH or "Interface\\AddOns\\ArenaCore\\Media\\Fonts\\arenacore.ttf", 13, "OUTLINE")
    end

    local label = container:CreateFontString(nil, "OVERLAY")
    label:SetPoint("TOP", bar, "BOTTOM", 0, -4)
    label:SetJustifyH("CENTER")
    label:SetJustifyV("TOP")
    label:SetTextColor(1, 1, 1, 1)
    if label.SetFont then
        label:SetFont(AC.FONT_PATH or "Interface\\AddOns\\ArenaCore\\Media\\Fonts\\arenacore.ttf", 11, "OUTLINE")
    end
    label:SetText("Time Left To Join!")

    container.bar = bar
    container.text = text
    container.label = label

    container:Hide()
    return container
end

function AC:UpdateSafeQueueTimer(container, secondsRemaining, totalSeconds)
    if not (container and container.bar and container.text) then return end
    if not secondsRemaining or secondsRemaining < 0 then
        container:Hide()
        return
    end

    local percent = 0
    if totalSeconds and totalSeconds > 0 then
        percent = math.max(0, math.min(1, secondsRemaining / totalSeconds))
    end

    container.bar:SetValue(percent)
    container.text:SetText(string.format("%.1f", secondsRemaining))
    container:Show()
end

-- ============================================================================
-- Internal state
-- ============================================================================

local function SafeQueue_Cleanup()
    if AC.__safeQueueEventFrame then
        AC.__safeQueueEventFrame:SetScript("OnEvent", nil)
        AC.__safeQueueEventFrame:UnregisterAllEvents()
        AC.__safeQueueEventFrame = nil
    end

    if AC.__safeQueuePVPBar then
        AC.__safeQueuePVPBar:Hide()
    end
    if AC.__safeQueueLFGBar then
        AC.__safeQueueLFGBar:Hide()
    end

    AC.__safeQueueStartTimes = nil
end

local function SafeQueue_ShowLFGTimer()
    local dialog = _G.LFGDungeonReadyDialog
    if not dialog or not dialog:IsShown() then return end

    if not AC.__safeQueueLFGBar then
        AC.__safeQueueLFGBar = AC:CreateSafeQueueTimerBar(dialog)
    end

    local bar = AC.__safeQueueLFGBar
    bar.totalSeconds = 40
    bar.startTime = GetTime()
    bar.bar:SetMinMaxValues(0, bar.totalSeconds)

    if not bar.updateScriptSet then
        bar.updateScriptSet = true
        bar:SetScript("OnUpdate", function(self, elapsed)
            if not AC.__safeQueueEnabled then
                self:Hide()
                self.updateScriptSet = nil
                self:SetScript("OnUpdate", nil)
                return
            end

            local elapsedTime = GetTime() - self.startTime
            local remaining = self.totalSeconds - elapsedTime

            if remaining > 0 then
                self.bar:SetValue(remaining)
                self.text:SetFormattedText("%.1f", remaining)
            else
                self:Hide()
                self.updateScriptSet = nil
                self:SetScript("OnUpdate", nil)
            end
        end)
    end

    AC:UpdateSafeQueueTimer(bar, bar.totalSeconds, bar.totalSeconds)
end

local function SafeQueue_CheckPvPQueue()
    for i = 1, GetMaxBattlefieldID() do
        local status = GetBattlefieldStatus(i)
        if status == "confirm" then
            AC:SafeQueue_ShowPvPTimer(i)
            return
        end
    end
end

function AC:SafeQueue_ShowPvPTimer(battlefieldIndex)
    local dialog = _G.PVPReadyDialog
    if not dialog or not dialog:IsShown() then return end

    if not AC.__safeQueuePVPBar then
        AC.__safeQueuePVPBar = AC:CreateSafeQueueTimerBar(dialog)
    end

    local bar = AC.__safeQueuePVPBar
    bar.totalSeconds = 90
    bar.battlefieldIndex = battlefieldIndex
    bar.bar:SetMinMaxValues(0, bar.totalSeconds)

    if not bar.updateScriptSet then
        bar.updateScriptSet = true
        bar:SetScript("OnUpdate", function(self, elapsed)
            if not AC.__safeQueueEnabled then
                self:Hide()
                self.updateScriptSet = nil
                self:SetScript("OnUpdate", nil)
                return
            end

            local remaining = GetBattlefieldPortExpiration(self.battlefieldIndex)
            if remaining and remaining > 0 then
                self.bar:SetValue(remaining)
                self.text:SetFormattedText("%.1f", remaining)
            else
                self:Hide()
                self.updateScriptSet = nil
                self:SetScript("OnUpdate", nil)
            end
        end)
    end

    local remaining = GetBattlefieldPortExpiration(battlefieldIndex)
    if remaining and remaining > 0 then
        AC:UpdateSafeQueueTimer(bar, remaining, bar.totalSeconds)
    end
end

local function SafeQueue_TrackLFGQueueStart()
    if not AC.__safeQueueStartTimes then return end

    for category = 1, NUM_LE_LFG_CATEGORYS or 2 do
        local mode = GetLFGMode(category)
        if mode == "queued" then
            if not AC.__safeQueueStartTimes["LFG_" .. category] then
                local hasData, leaderNeeds, tankNeeds, healerNeeds, dpsNeeds, totalTanks, totalHealers, totalDPS, instanceType, instanceSubType, instanceName, averageWait, tankWait, healerWait, damageWait, myWait, queuedTime = GetLFGQueueStats(category)
                if hasData and queuedTime and queuedTime > 0 then
                    AC.__safeQueueStartTimes["LFG_" .. category] = queuedTime
                end
            end
        elseif mode == "proposal" then
            AC.__safeQueueStartTimes["LFG_" .. category] = nil
        elseif mode == nil or mode == "none" then
            AC.__safeQueueStartTimes["LFG_" .. category] = nil
        end
    end
end

local function SafeQueue_TrackPvPQueueStart()
    if not AC.__safeQueueStartTimes then return end

    for i = 1, GetMaxBattlefieldID() do
        local status = GetBattlefieldStatus(i)
        local key = "PvP_" .. i

        if status == "queued" then
            if not AC.__safeQueueStartTimes[key] then
                AC.__safeQueueStartTimes[key] = GetTime()
            end
        elseif status == "confirm" then
            -- handled by UPDATE_BATTLEFIELD_STATUS
        elseif status == "none" then
            AC.__safeQueueStartTimes[key] = nil
        end
    end
end

local function SafeQueue_FormatWaitTime(seconds)
    if not seconds or seconds <= 0 then
        return "0 secs"
    end

    local hours = math.floor(seconds / 3600)
    local minutes = math.floor((seconds % 3600) / 60)
    local secs = math.floor(seconds % 60)

    if hours > 0 then
        return string.format("%dh %dm %ds", hours, minutes, secs)
    elseif minutes > 0 then
        return string.format("%dm %ds", minutes, secs)
    else
        return string.format("%ds", secs)
    end
end

local function SafeQueue_NotifyQueuePop(queueType, battlefieldIndex)
    if not AC.__safeQueueEnabled then return end

    local waitTime = 0
    local queueName = ""

    if queueType == "LFG" then
        for category = 1, NUM_LE_LFG_CATEGORYS or 2 do
            local mode = GetLFGMode(category)
            if mode == "proposal" then
                local key = "LFG_" .. category
                if AC.__safeQueueStartTimes and AC.__safeQueueStartTimes[key] then
                    waitTime = GetTime() - AC.__safeQueueStartTimes[key]
                end
                queueName = "LFG"
                break
            end
        end
    elseif queueType == "PvP" and battlefieldIndex then
        local key = "PvP_" .. battlefieldIndex
        if AC.__safeQueueStartTimes and AC.__safeQueueStartTimes[key] then
            waitTime = GetTime() - AC.__safeQueueStartTimes[key]
        else
            local timeInQueue = GetBattlefieldTimeWaited(battlefieldIndex)
            if timeInQueue and timeInQueue > 0 then
                waitTime = timeInQueue / 1000
            end
        end

        local status, mapName = GetBattlefieldStatus(battlefieldIndex)
        if mapName then
            queueName = mapName
        else
            queueName = "Battleground"
        end
    end

    local waitTimeStr = SafeQueue_FormatWaitTime(waitTime)
    local message = string.format("|cff8B45FFArena|cffB85CFFCore|r |cffFFFFFFQueue popped after %s (%s)|r", waitTimeStr, queueName)
    DEFAULT_CHAT_FRAME:AddMessage(message, 1, 1, 1)
end

local function SafeQueue_InitializeEventSystem()
    if AC.__safeQueueEventFrame then return end

    local eventFrame = CreateFrame("Frame")
    AC.__safeQueueEventFrame = eventFrame

    AC.__safeQueueStartTimes = {}

    eventFrame:RegisterEvent("LFG_PROPOSAL_SHOW")
    eventFrame:RegisterEvent("LFG_UPDATE")
    eventFrame:RegisterEvent("UPDATE_BATTLEFIELD_STATUS")

    eventFrame:SetScript("OnEvent", function(_, event, ...)
        if not AC.__safeQueueEnabled then return end

        if event == "LFG_PROPOSAL_SHOW" then
            SafeQueue_ShowLFGTimer()
            SafeQueue_NotifyQueuePop("LFG")
        elseif event == "UPDATE_BATTLEFIELD_STATUS" then
            local battlefieldIndex = ...
            SafeQueue_CheckPvPQueue()
            SafeQueue_TrackPvPQueueStart()
            local status = GetBattlefieldStatus(battlefieldIndex)
            if status == "confirm" then
                SafeQueue_NotifyQueuePop("PvP", battlefieldIndex)
            end
        elseif event == "LFG_UPDATE" then
            SafeQueue_TrackLFGQueueStart()
        end
    end)
end

-- ============================================================================
-- Public API
-- ============================================================================

function AC:SetSafeQueueEnabled(enabled)
    enabled = (enabled == true)
    AC.__safeQueueEnabled = enabled

    if enabled then
        SafeQueue_InitializeEventSystem()
    else
        SafeQueue_Cleanup()
    end
end
