local battleFrame = CreateFrame("Frame", "BPSBattleFrame", UIParent, "BackdropTemplate")
battleFrame:SetSize(320, 230)
battleFrame:SetPoint("TOP", UIParent, "TOP", 0, -130)
battleFrame:SetFrameStrata("HIGH")
battleFrame:SetBackdrop({
    bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true, tileSize = 16, edgeSize = 12,
    insets = { left = 4, right = 4, top = 4, bottom = 4 },
})
battleFrame:SetBackdropColor(0, 0, 0, 0.75)
battleFrame:SetMovable(true)
battleFrame:EnableMouse(true)
battleFrame:RegisterForDrag("LeftButton")
battleFrame:SetScript("OnDragStart", function(self) self:StartMoving() end)
battleFrame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
battleFrame:Hide()

local function NewLine(anchorTo, fontTemplate, yOffset)
    local fs = battleFrame:CreateFontString(nil, "OVERLAY", fontTemplate or "GameFontNormal")
    if anchorTo then
        fs:SetPoint("TOP", anchorTo, "BOTTOM", 0, yOffset or -4)
    else
        fs:SetPoint("TOP", battleFrame, "TOP", 0, -10)
    end
    return fs
end

local sessionTitle   = NewLine(nil, "GameFontNormalLarge")
local overallLine    = NewLine(sessionTitle, "GameFontNormal")
local winrateLine    = NewLine(overallLine, "GameFontNormal")
local nrOverallLine  = NewLine(winrateLine, "GameFontNormal")
local nrWinrateLine  = NewLine(nrOverallLine, "GameFontNormal")
local goalLine       = NewLine(nrWinrateLine, "GameFontNormal")
local vsLine         = NewLine(goalLine, "GameFontNormalLarge", -10)
local vsStatsLine    = NewLine(vsLine, "GameFontNormal")
local vsWinrateLine  = NewLine(vsStatsLine, "GameFontNormal")
local predictionLine = NewLine(vsWinrateLine, "GameFontNormalLarge")

-- Edit button: lets the player correct the win/loss count against the
-- current opponent directly from the battle overlay (top-right corner),
-- shown as soon as an opponent has been identified. Reuses the same
-- edit popup as the Statistics tab, so both stay perfectly in sync.
local editVsButton = CreateFrame("Button", nil, battleFrame, "UIPanelButtonTemplate")
editVsButton:SetSize(60, 18)
editVsButton:SetPoint("TOPRIGHT", battleFrame, "TOPRIGHT", -6, -6)
editVsButton:Hide()
editVsButton:SetScript("OnClick", function()
    local opponentName = BPS_GetCurrentOpponentDisplayName()
    if opponentName and BPS_OpenEditPopup then
        local w, l = BPS_GetStatsFor(opponentName)
        BPS_OpenEditPopup(opponentName, w, l)
    end
end)

-- Forfeit button
local forfeitButton = CreateFrame("Button", nil, battleFrame, "UIPanelButtonTemplate")
forfeitButton:SetSize(140, 24)
forfeitButton:SetPoint("TOP", predictionLine, "BOTTOM", 0, -10)
forfeitButton:SetScript("OnClick", function()
    if C_PetBattles.IsInBattle and C_PetBattles.IsInBattle() then
        C_PetBattles.ForfeitGame()
    end
end)

local function Round(n)
    return math.floor(n + 0.5)
end

local function ComputeWinrate(wins, losses)
    local total = wins + losses
    if total == 0 then return 0 end
    return Round((wins / total) * 100)
end

-- A "Random" opponent is one whose display name starts with the localised
-- VS_RANDOM prefix (e.g. "Random (CAT/FEL/DRA)"). We also check the raw
-- English word as a safe fallback, regardless of the active language.
local function IsRandomOpponent(name)
    if not name then return false end
    local L = BPS_GetLocale()
    local lk = name:lower()
    return lk:find("^random%(") ~= nil
        or lk:find("^random ") ~= nil
        or name:find("^" .. (L.VS_RANDOM or "Random") .. "%(") ~= nil
        or name:find("^" .. (L.VS_RANDOM or "Random") .. " ") ~= nil
end

local function RefreshDisplay()
    local L = BPS_GetLocale()
    local display = BattlePetStatisticsDB.display

    sessionTitle:SetText(L.SESSION_TITLE)

    local oWins, oLosses = BPS_GetSessionTotals()
    if display.showOverall then
        overallLine:SetText(string.format(L.OVERALL, oWins, oLosses))
        overallLine:Show()
    else
        overallLine:Hide()
    end

    if display.showWinrate then
        winrateLine:SetText(string.format(L.WINRATE, ComputeWinrate(oWins, oLosses)))
        winrateLine:Show()
    else
        winrateLine:Hide()
    end

    -- No-random session stats
    if display.showNRStats then
        local nrW, nrL = BPS_GetSessionNRTotals()
        local nrTotal = nrW + nrL
        nrOverallLine:SetText(string.format(L.NR_SESSION_GAMES or "w/o Random: %d", nrTotal) ..
            "  " .. string.format(L.WIN .. ": %d  " .. L.LOSE .. ": %d", nrW, nrL))
        nrOverallLine:SetTextColor(1.0, 0.85, 0.3)
        nrWinrateLine:SetText(string.format("w/o Random " .. L.WINRATE, ComputeWinrate(nrW, nrL)))
        nrWinrateLine:SetTextColor(1.0, 0.85, 0.3)
        nrOverallLine:Show(); nrWinrateLine:Show()
    else
        nrOverallLine:Hide(); nrWinrateLine:Hide()
    end

    if display.showGoal then
        local goal = BPS_GetCurrentGoal()
        if goal then
            local progress = BPS_GetRealProgress(goal)
            goalLine:SetText(string.format(L.GOAL_LINE, BPS_GetGoalName(goal), math.min(progress, goal.threshold), goal.threshold))
        else
            goalLine:SetText(L.GOAL_DONE_LINE)
        end
        goalLine:Show()
    else
        goalLine:Hide()
    end

    local opponentName = BPS_GetCurrentOpponentDisplayName()
    local wins, losses = 0, 0
    if opponentName then
        -- Session-only stats vs this opponent (resets each login), not the
        -- lifetime/global record, so the battle overlay reflects how the
        -- current session is going against them specifically.
        wins, losses = BPS_GetSessionStatsFor(opponentName)
    end

    -- Edit button: always available as soon as an opponent is known,
    -- independent of which lines are toggled on/off.
    editVsButton:SetText(L.BATTLE_EDIT_BUTTON or L.EDIT_BUTTON)
    if opponentName then
        editVsButton:Show()
    else
        editVsButton:Hide()
    end

    if display.showVs and opponentName then
        vsLine:SetText(string.format("%s %s", L.VS, opponentName))
        vsLine:Show()
    else
        vsLine:Hide()
    end

    if display.showVsStats and opponentName then
        vsStatsLine:SetText(string.format("%s : %d   %s: %d", L.WIN, wins, L.LOSE, losses))
        vsStatsLine:Show()
    else
        vsStatsLine:Hide()
    end

    if display.showVsWinrate and opponentName then
        vsWinrateLine:SetText(string.format(L.WINRATE, ComputeWinrate(wins, losses)))
        vsWinrateLine:Show()
    else
        vsWinrateLine:Hide()
    end

    -- Prediction rule: wins < losses -> Win, otherwise -> Lose.
    local shouldWin = opponentName and (wins < losses) or false

    if display.showPrediction and opponentName then
        if shouldWin then
            predictionLine:SetText(L.YOU_SHOULD_WIN)
            predictionLine:SetTextColor(0.1, 1.0, 0.1)
        else
            predictionLine:SetText(L.YOU_SHOULD_LOSE)
            predictionLine:SetTextColor(1.0, 0.1, 0.1)
        end
        predictionLine:Show()
    else
        predictionLine:Hide()
    end

    -- The "Forfeit vs Random even when winning" Interface option forces the
    -- Forfeit button to show against Random opponents specifically, even
    -- when the prediction says we should win against them.
    local isRandomOpponent = IsRandomOpponent(opponentName)
    local forceForfeitForRandom = display.showForfeitVsRandomWhenWinning and opponentName and isRandomOpponent

    forfeitButton:SetText(L.FORFEIT_BUTTON)
    if display.showForfeitButton and (not shouldWin or forceForfeitForRandom) then
        forfeitButton:Show()
    else
        forfeitButton:Hide()
    end

    -- Re-flow the frame height roughly based on visible lines
    battleFrame:SetHeight(60 +
        (overallLine:IsShown() and 18 or 0) +
        (winrateLine:IsShown() and 18 or 0) +
        (nrOverallLine:IsShown() and 18 or 0) +
        (nrWinrateLine:IsShown() and 18 or 0) +
        (goalLine:IsShown() and 18 or 0) +
        (vsLine:IsShown() and 24 or 0) +
        (vsStatsLine:IsShown() and 18 or 0) +
        (vsWinrateLine:IsShown() and 18 or 0) +
        (predictionLine:IsShown() and 24 or 0) +
        (forfeitButton:IsShown() and 30 or 0))
end

function BPS_ShowBattleFrame()
    RefreshDisplay()
    if not battleFrame:IsShown() then
        battleFrame:Show()
    end
end

function BPS_UpdateBattleFrame()
    RefreshDisplay()
end

function BPS_HideBattleFrame()
    battleFrame:Hide()
end

-- ===================== Requeue button (shown after battle ends) =====================
local requeueButton = CreateFrame("Button", "BPSRequeueButton", UIParent, "UIPanelButtonTemplate")
requeueButton:SetSize(260, 50)
requeueButton:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
requeueButton:SetFrameStrata("DIALOG")
requeueButton:GetFontString():SetFontObject("GameFontNormalLarge")
requeueButton:Hide()

requeueButton:SetScript("OnClick", function()
    if BPS_ForceResolvePendingBattle then BPS_ForceResolvePendingBattle() end
    pcall(C_PetBattles.StartPVPMatchmaking)
    requeueButton:Hide()
end)

-- Close (X) button on the requeue popup so players can dismiss it without re-queuing
local requeueClose = CreateFrame("Button", nil, requeueButton)
requeueClose:SetSize(20, 20)
requeueClose:SetPoint("TOPRIGHT", requeueButton, "TOPRIGHT", 2, 2)
requeueClose:SetNormalTexture("Interface\\Buttons\\UI-StopButton")
requeueClose:GetNormalTexture():SetAlpha(0.8)
requeueClose:SetHighlightTexture("Interface\\Buttons\\UI-StopButton")
requeueClose:SetScript("OnClick", function() requeueButton:Hide() end)

function BPS_ShowRequeueButton()
    -- When auto-requeue is enabled, the addon re-enters the queue by itself,
    -- so the manual "Queue Again" button would be redundant/confusing.
    if BattlePetStatisticsDB and BattlePetStatisticsDB.autoRequeue then
        requeueButton:Hide()
        return
    end
    local L = BPS_GetLocale()
    requeueButton:SetText(L.REQUEUE_BUTTON)
    requeueButton:Show()
end

-- Hide the requeue button once a new battle starts
local hideHelper = CreateFrame("Frame")
hideHelper:RegisterEvent("PET_BATTLE_OPENING_START")
hideHelper:SetScript("OnEvent", function()
    requeueButton:Hide()
end)

-- ===================== Big "all goals completed" celebration popup =====================
local celebrationFrame = CreateFrame("Frame", "BPSCelebrationFrame", UIParent, "BackdropTemplate")
celebrationFrame:SetSize(520, 180)
celebrationFrame:SetPoint("CENTER", UIParent, "CENTER", 0, 150)
celebrationFrame:SetFrameStrata("FULLSCREEN_DIALOG")
celebrationFrame:SetBackdrop({
    bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
    edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
    tile = true, tileSize = 32, edgeSize = 32,
    insets = { left = 11, right = 12, top = 12, bottom = 11 },
})
celebrationFrame:Hide()

local celebrationText = celebrationFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
celebrationText:SetPoint("CENTER", 0, 0)
celebrationText:SetWidth(460)
celebrationText:SetJustifyH("CENTER")

local celebrationClose = CreateFrame("Button", nil, celebrationFrame, "UIPanelCloseButton")
celebrationClose:SetPoint("TOPRIGHT", -5, -5)
celebrationClose:SetScript("OnClick", function() celebrationFrame:Hide() end)

function BPS_OnGoalCompleted(goal)
    if goal and goal.id == BPS_BIG_CELEBRATION_GOAL_ID then
        local L = BPS_GetLocale()
        celebrationText:SetText(L.BIG_CONGRATS)
        celebrationFrame:Show()
        local ok = pcall(PlaySound, SOUNDKIT and SOUNDKIT.IG_QUEST_LIST_COMPLETE, "Master")
        if not ok then
            pcall(PlaySound, SOUNDKIT and SOUNDKIT.READY_CHECK, "Master")
        end
    end
end
