-- ===================== Alias input popup =====================
StaticPopupDialogs["BPS_ALIAS_PROMPT"] = {
    text = "", -- set dynamically
    button1 = "", -- set dynamically
    hasEditBox = true,
    maxLetters = 16,
    OnShow = function(self)
        local editBox = self.editBox or _G[self:GetName() .. "EditBox"]
        editBox:SetText(BattlePetStatisticsDB.alias or "")
        editBox:HighlightText()
        editBox:SetFocus()
    end,
    OnAccept = function(self)
        local editBox = self.editBox or _G[self:GetName() .. "EditBox"]
        local text = editBox:GetText()
        if text and text ~= "" then
            local newAlias = text:sub(1, 16)
            if newAlias ~= BattlePetStatisticsDB.alias then
                -- Alias actually changed: force the next battle resolution
                -- to perform a real rename with the new name, bypassing the
                -- "assume already done" compatibility bridge entirely (that
                -- bridge is only meant for the very first time we ever see
                -- an alias, e.g. upgrading from an older addon version).
                BattlePetStatisticsDB.lastRenamedAlias = nil
                BattlePetStatisticsDB.forceRenameNext = true
            end
            BattlePetStatisticsDB.alias = newAlias
            BattlePetStatisticsDB.tradeWinEnabled = true
        end
    end,
    EditBoxOnEnterPressed = function(self)
        local parent = self:GetParent()
        local text = self:GetText()
        if text and text ~= "" then
            local newAlias = text:sub(1, 16)
            if newAlias ~= BattlePetStatisticsDB.alias then
                BattlePetStatisticsDB.lastRenamedAlias = nil
                BattlePetStatisticsDB.forceRenameNext = true
            end
            BattlePetStatisticsDB.alias = newAlias
            BattlePetStatisticsDB.tradeWinEnabled = true
        end
        parent:Hide()
    end,
    EditBoxOnEscapePressed = function(self)
        self:GetParent():Hide()
    end,
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
    preferredIndex = 3,
}

-- Returns true if the player's pets have already been custom-renamed by this
-- addon (i.e. the first battle pet's name no longer matches its species name).
local function IsFirstPetAlreadyRenamed()
    if not C_PetJournal or not C_PetJournal.GetPetLoadOutInfo or not C_PetJournal.GetPetInfoByPetID then
        return false
    end
    local ok, petID = pcall(C_PetJournal.GetPetLoadOutInfo, 1)
    if not ok or not petID then return false end
    local ok2, _, customName = pcall(C_PetJournal.GetPetInfoByPetID, petID)
    return ok2 and customName ~= nil and customName ~= ""
end

local function ShowAliasPopup()
    local L = BPS_GetLocale()
    local d2 = StaticPopupDialogs["BPS_ALIAS_PROMPT"]
    d2.text = L.ALIAS_PROMPT_TITLE
    d2.button1 = L.ALIAS_VALIDATE
    StaticPopup_Show("BPS_ALIAS_PROMPT")
end

-- Called once per login, a few seconds after entering the world. Whether the
-- alias popup actually appears depends on BattlePetStatisticsDB.showWindowMode,
-- set in the Options tab:
--   "startup"            -> always show at login
--   "after_first_battle" -> don't show here; BPS_MaybeShowAliasAfterBattle
--                            handles it once the first PvP battle resolves
--   "never"              -> never show
--   "if_not_renamed"     -> only show if the pets aren't already renamed
function BPS_MaybeShowSetupPrompt()
    EnsureDB()
    local mode = BattlePetStatisticsDB.showWindowMode

    if mode == "after_first_battle" or mode == "never" then return end

    if mode == "if_not_renamed" then
        if IsFirstPetAlreadyRenamed() then return end
        ShowAliasPopup()
        return
    end

    -- "startup" (default)
    ShowAliasPopup()
end

-- Called right after the first PvP pet battle of the login session resolves.
-- Only relevant when showWindowMode == "after_first_battle".
function BPS_MaybeShowAliasAfterBattle()
    EnsureDB()
    if BattlePetStatisticsDB.showWindowMode ~= "after_first_battle" then return end
    ShowAliasPopup()
end

-- Forces the alias popup open regardless of showWindowMode. Used by the
-- "/bps setup" slash command so the player can always reconfigure manually.
function BPS_ForceShowAliasPopup()
    EnsureDB()
    ShowAliasPopup()
end

-- ===================== Pet renaming at end of battle =====================
-- Renames the player's first 3 active battle pets according to the alias,
-- as a way to let opponents who also run this addon identify the player
-- reliably (pet species can vary battle to battle, a custom name doesn't).
--
-- IMPORTANT: this only actually calls SetCustomName once per alias (tracked
-- via BattlePetStatisticsDB.lastRenamedAlias). Re-sending SetCustomName every
-- single battle — even on pets that are already correctly named — is what
-- was triggering Blizzard's intermittent "invalid characters" error.
--
-- We deliberately do NOT try to verify the pets' current names via
-- C_PetJournal before renaming: that data isn't reliably available right
-- after a battle ends, and a false "not renamed yet" reading was exactly
-- what caused SetCustomName to be re-sent on already-correct pets. So: the
-- very first time we see a non-empty alias with no confirmation flag yet
-- (e.g. upgrading from an older version of the addon), we assume renaming
-- was already done and simply record the flag — actual renaming only
-- happens the next time the player deliberately sets/changes their alias
-- in the popup (see BPS_ALIAS_PROMPT's OnAccept, which clears the flag).
function BPS_RenameOwnPetsForTradeWin()
    Debug("BPS_RenameOwnPetsForTradeWin called. tradeWinEnabled=" .. tostring(BattlePetStatisticsDB.tradeWinEnabled))
    if not BattlePetStatisticsDB.tradeWinEnabled then return end
    local alias = BattlePetStatisticsDB.alias
    Debug("alias=" .. tostring(alias))
    if not alias or alias == "" then return end

    local forced = BattlePetStatisticsDB.forceRenameNext == true
    Debug("forced=" .. tostring(forced) .. " lastRenamedAlias=" .. tostring(BattlePetStatisticsDB.lastRenamedAlias))

    -- Already renamed (or assumed already renamed) for this exact alias —
    -- unless the player just deliberately set/changed it (forced), in which
    -- case we always go through with a real rename.
    if not forced and BattlePetStatisticsDB.lastRenamedAlias == alias then
        Debug("Skipping rename: already done for this alias")
        return
    end

    -- First time ever seeing an alias with no flag at all (e.g. upgrading
    -- from an older addon version where the flag didn't exist yet): assume
    -- renaming was already done rather than guessing from potentially-stale
    -- pet data, to avoid re-triggering Blizzard's rename bug. This bridge is
    -- skipped entirely when the player just deliberately typed a new alias.
    if not forced and BattlePetStatisticsDB.lastRenamedAlias == nil then
        Debug("First-time bridge: assuming already renamed, not calling SetCustomName")
        BattlePetStatisticsDB.lastRenamedAlias = alias
        return
    end

    if not C_PetJournal or not C_PetJournal.GetPetLoadOutInfo or not C_PetJournal.SetCustomName then
        Debug("C_PetJournal API missing, aborting rename")
        return
    end

    local pet1Name
    if #alias < 7 then
        pet1Name = string.format("%s TradeWin", alias)
    else
        pet1Name = alias
    end

    local names = { pet1Name, "TradeWin", "I Need To Win" }

    local allOk = true
    for slot = 1, 3 do
        local ok, petID = pcall(C_PetJournal.GetPetLoadOutInfo, slot)
        Debug("slot " .. slot .. ": GetPetLoadOutInfo ok=" .. tostring(ok) .. " petID=" .. tostring(petID))
        if ok and petID then
            local ok2, err2 = pcall(C_PetJournal.SetCustomName, petID, names[slot])
            Debug("slot " .. slot .. ": SetCustomName ok=" .. tostring(ok2) .. " err=" .. tostring(err2) .. " name=" .. names[slot])
            if not ok2 then allOk = false end
        else
            allOk = false
        end
    end

    -- Only remember this alias as "done" if every slot was actually reached.
    -- If a pet slot was missing/unavailable this battle, we'll retry next time.
    if allOk then
        BattlePetStatisticsDB.lastRenamedAlias = alias
        BattlePetStatisticsDB.forceRenameNext = false
        BattlePetStatisticsDB.petsCurrentlyRenamed = true
        Debug("Rename succeeded for all 3 slots")
    else
        Debug("Rename FAILED for at least one slot, will retry next battle")
    end
end

-- Restores the player's first 3 active battle pets to their default (no
-- custom name) state. Called either on logout (when
-- BattlePetStatisticsDB.restoreNamesOnLogout is enabled) or as a catch-up
-- safeguard on the next login if that didn't happen (see
-- BPS_CatchUpPendingRestore below).
function BPS_RestoreOwnPetNames()
    if not C_PetJournal or not C_PetJournal.GetPetLoadOutInfo or not C_PetJournal.SetCustomName then
        return
    end
    for slot = 1, 3 do
        local ok, petID = pcall(C_PetJournal.GetPetLoadOutInfo, slot)
        if ok and petID then
            -- Passing an empty string clears the custom name in the Pet Journal API.
            pcall(C_PetJournal.SetCustomName, petID, "")
        end
    end
    -- The pets no longer carry the TradeWin names, so the next battle should
    -- rename them again rather than thinking it's already been done.
    if BattlePetStatisticsDB then
        BattlePetStatisticsDB.lastRenamedAlias = nil
        BattlePetStatisticsDB.petsCurrentlyRenamed = false
    end
end

-- Safeguard for abnormal exits (crash, force-quit, disconnect) where
-- PLAYER_LOGOUT never fires, so the restore-on-logout step never ran even
-- though the player asked for it. Called once on login: if the pets were
-- left in their renamed state from last session AND the player wants
-- restoreNamesOnLogout, catch up by restoring them now instead of leaving
-- them stuck with TradeWin names indefinitely.
function BPS_CatchUpPendingRestore()
    EnsureDB()
    if BattlePetStatisticsDB.restoreNamesOnLogout
        and BattlePetStatisticsDB.petsCurrentlyRenamed then
        BPS_RestoreOwnPetNames()
    end
end
