-- Portal Authority — core/bootstrap.lua
-- Core bootstrap, gate evaluation, and global table initialization.
--
-- Depends on: none
-- Exposes:    PortalAuthority buildConfig/gate methods; PortalAuthority.CoreInternal gate/localization helpers
-- DB keys:    PortalAuthorityCharacterDB._devLocaleOverride (resolved during dev-gated init finalize)
-- Events:     none
-- Search key: none

-- Portal Authority
-- Core event handling, settings migration, and chat announcement logic.

local ADDON_NAME = ...

PortalAuthority = PortalAuthority or {}
PortalAuthorityDiagDump = nil

local PA_SETTINGS_WINDOW_DEV_GATE_ENABLED = false
local PA_SETTINGS_WINDOW_PUBLIC_GATE_ENABLED = true
local PA_DIAG_GATE_ENABLED = false
local PA_LOCALE_DEV_GATE_ENABLED = false

local PA_IsSecretValue
local PA_NormalizeSafeString
local PA_SafeStringsEqual
local PA_SafeUnitGUID

PortalAuthority.CoreInternal = PortalAuthority.CoreInternal or {}
local CoreInternal = PortalAuthority.CoreInternal

PortalAuthority._buildConfig = {
    gates = {
        uiSurface = false,
        staticBaseline = false,
        settingsBaseline = false,
        settingsEagerBuild = false,
        settingsDirectBuild = false,
        settingsWindowDev = PA_SETTINGS_WINDOW_DEV_GATE_ENABLED,
        settingsWindowPublic = PA_SETTINGS_WINDOW_PUBLIC_GATE_ENABLED,
        diag = PA_DIAG_GATE_ENABLED,
        localeDev = PA_LOCALE_DEV_GATE_ENABLED,
        onboardingD1Dev = false, -- Internal onboarding branch only; keep false in public builds.
        onboardingD3Dev = false, -- Internal onboarding branch only; keep false in public builds.
        onboardingD4Dev = false, -- Internal onboarding branch only; keep false in public builds.
        onboardingD3Public = true,
        onboardingD4Public = true,
        onboardingQualifyingUpgradePublic = true,
    },
    release = {
        premiumOnboardingResetEpoch = "PA_2_0_0_BASELINE",
        premiumOnboardingVersion = "PA_2_0_0_PREMIUM_V1",
        qualifyingUpgradeOnboardingVersion = "PA_2_1_1_QUALIFYING_UPGRADE_V1",
        settingsWindowAnnouncementVersion = "2.1.2",
        premiumAuthoredFontPath = "Fonts\\FRIZQT__.TTF",
        premiumAuthoredFontName = "Overclock: Friz",
        overclockWarcraftLogsUrl = "https://classic.warcraftlogs.com/guild/us/faerlina/overclock",
    },
    settings = {
        keystoneBootstrapStates = {
            scheduled = true,
            ran = true,
            suppressed = true,
            unknown = true,
        },
        bootstrapActiveStates = {
            none = true,
            root = true,
            announcements = true,
            dock = true,
            timers = true,
            interrupt = true,
            combat = true,
            profiles = true,
        },
    },
}

local PA_SUPPORTED_LOCALE_CODES = {
    deDE = "deDE",
    enUS = "enUS",
    esES = "esES",
    esMX = "esMX",
    frFR = "frFR",
    itIT = "itIT",
    koKR = "koKR",
    ptBR = "ptBR",
    ruRU = "ruRU",
    zhCN = "zhCN",
    zhTW = "zhTW",
}

local PA_SUPPORTED_LOCALE_LOOKUP = {
    dede = "deDE",
    enus = "enUS",
    eses = "esES",
    esmx = "esMX",
    frfr = "frFR",
    itit = "itIT",
    kokr = "koKR",
    ptbr = "ptBR",
    ruru = "ruRU",
    zhcn = "zhCN",
    zhtw = "zhTW",
}

local function PA_TrimLocaleCode(localeCode)
    if type(localeCode) ~= "string" then
        return nil
    end
    local trimmed = localeCode:gsub("^%s+", ""):gsub("%s+$", "")
    if trimmed == "" then
        return nil
    end
    return trimmed
end

local function PA_NormalizeSupportedLocaleCode(localeCode)
    local trimmed = PA_TrimLocaleCode(localeCode)
    if not trimmed then
        return nil
    end
    return PA_SUPPORTED_LOCALE_CODES[trimmed] or PA_SUPPORTED_LOCALE_LOOKUP[string.lower(trimmed)]
end

local function PA_GetClientLocaleCode()
    local clientLocale = type(GetLocale) == "function" and GetLocale() or nil
    return PA_NormalizeSupportedLocaleCode(clientLocale) or "enUS"
end

local function PA_ApplyLocalePayloadTable(payload)
    local L = PortalAuthority and PortalAuthority.L or nil
    if type(L) ~= "table" or type(payload) ~= "table" then
        return false
    end

    for key, value in pairs(payload) do
        L[key] = value
    end

    return true
end

local function PA_RegisterLocalePayload(localeCode, payload)
    local normalizedLocale = PA_NormalizeSupportedLocaleCode(localeCode)
    if not normalizedLocale or normalizedLocale == "enUS" or type(payload) ~= "table" then
        return false
    end

    local registry = PortalAuthority and PortalAuthority._localeOverridePayloads or nil
    if type(registry) ~= "table" then
        return false
    end

    registry[normalizedLocale] = payload
    return true
end

local function PA_ApplyRegisteredLocalePayload(localeCode)
    local normalizedLocale = PA_NormalizeSupportedLocaleCode(localeCode)
    if not normalizedLocale or normalizedLocale == "enUS" then
        return true
    end

    local registry = PortalAuthority and PortalAuthority._localeOverridePayloads or nil
    local payload = type(registry) == "table" and registry[normalizedLocale] or nil
    if type(payload) ~= "table" then
        return false
    end

    return PA_ApplyLocalePayloadTable(payload)
end

local function PA_IsLocaleCharStoreAuthoritative(charStore)
    if type(charStore) ~= "table" then
        return false
    end

    if type(PortalAuthorityCharacterDB) ~= "table" or PortalAuthorityCharacterDB ~= charStore then
        return false
    end

    local stage = PortalAuthority and PortalAuthority._localeInitAuthorityStage or nil
    return stage == "addon_loaded" or stage == "player_login"
end

local function PA_FinalizeLocaleStateFromCharacterStore(charStore)
    local clientLocale = PA_GetClientLocaleCode()
    local activeLocale = PA_NormalizeSupportedLocaleCode(PortalAuthority._activeLocaleCode) or clientLocale

    if not PA_IsLocaleDevGateEnabled() then
        PortalAuthority._localeCharStoreAuthoritative = true
        PortalAuthority._localeDesiredCode = clientLocale
        PortalAuthority._activeLocaleCode = clientLocale
        PortalAuthority._localeStateFinalized = true
        return true, clientLocale
    end

    local isAuthoritative = PA_IsLocaleCharStoreAuthoritative(charStore)
    PortalAuthority._localeCharStoreAuthoritative = isAuthoritative and true or false
    if not isAuthoritative then
        return PortalAuthority._localeStateFinalized == true, activeLocale
    end

    local storedOverride = PA_NormalizeSupportedLocaleCode(charStore._devLocaleOverride)
    PortalAuthority._devLocaleOverride = storedOverride

    local desiredLocale = storedOverride or clientLocale
    PortalAuthority._localeDesiredCode = desiredLocale

    if PortalAuthority._localeStateFinalized == true
        and desiredLocale == activeLocale
        and (
            desiredLocale == "enUS"
            or PortalAuthority._localeAppliedPayloadCode == desiredLocale
        )
    then
        return true, desiredLocale
    end

    if desiredLocale == "enUS" then
        PortalAuthority._activeLocaleCode = desiredLocale
        PortalAuthority._localeStateFinalized = true
        return true, desiredLocale
    end

    if PortalAuthority._localeAppliedPayloadCode == desiredLocale then
        PortalAuthority._activeLocaleCode = desiredLocale
        PortalAuthority._localeStateFinalized = true
        return true, desiredLocale
    end

    if not PA_ApplyRegisteredLocalePayload(desiredLocale) then
        return false, activeLocale
    end

    PortalAuthority._localeAppliedPayloadCode = desiredLocale
    PortalAuthority._activeLocaleCode = desiredLocale
    PortalAuthority._localeStateFinalized = true
    return true, desiredLocale
end

PortalAuthority._devLocaleOverride = nil
PortalAuthority._activeLocaleCode = PA_GetClientLocaleCode()
PortalAuthority._localeOverridePayloads = PA_LOCALE_DEV_GATE_ENABLED and {} or nil
PortalAuthority._localeStateFinalized = false
PortalAuthority._localeDesiredCode = nil
PortalAuthority._localeAppliedPayloadCode = nil
PortalAuthority._localeCharStoreAuthoritative = false
PortalAuthority._localeInitAuthorityStage = nil

function PA_IsUiSurfaceGateEnabled()
    return PortalAuthority._buildConfig.gates.uiSurface == true
end

function PortalAuthority:IsUiSurfaceGateEnabled()
    return PA_IsUiSurfaceGateEnabled()
end

function PA_IsStaticBaselineGateEnabled()
    return PortalAuthority._buildConfig.gates.staticBaseline == true
end

function PortalAuthority:IsStaticBaselineGateEnabled()
    return PA_IsStaticBaselineGateEnabled()
end

function PA_IsSettingsBaselineGateEnabled()
    return PortalAuthority._buildConfig.gates.settingsBaseline == true
end

function PortalAuthority:IsSettingsBaselineGateEnabled()
    return PA_IsSettingsBaselineGateEnabled()
end

function PA_IsSettingsEagerBuildGateEnabled()
    if PortalAuthority._buildConfig.gates.settingsEagerBuild == true then
        return true
    end
    return PortalAuthority
        and PortalAuthority.IsSettingsWindowHostEnabled
        and PortalAuthority:IsSettingsWindowHostEnabled()
        or false
end

function PortalAuthority:IsSettingsEagerBuildGateEnabled()
    return PA_IsSettingsEagerBuildGateEnabled()
end

function PA_IsSettingsDirectBuildGateEnabled()
    return PortalAuthority._buildConfig.gates.settingsDirectBuild == true
end

function PortalAuthority:IsSettingsDirectBuildGateEnabled()
    return PA_IsSettingsDirectBuildGateEnabled()
end

function PA_IsSettingsWindowDevGateEnabled()
    return PortalAuthority._buildConfig.gates.settingsWindowDev == true
end

function PortalAuthority:IsSettingsWindowDevGateEnabled()
    return PA_IsSettingsWindowDevGateEnabled()
end

function PA_IsSettingsWindowPublicGateEnabled()
    return PortalAuthority._buildConfig.gates.settingsWindowPublic == true
end

function PortalAuthority:IsSettingsWindowPublicGateEnabled()
    return PA_IsSettingsWindowPublicGateEnabled()
end

function PA_IsSettingsWindowHostEnabled()
    return PA_IsSettingsWindowDevGateEnabled() or PA_IsSettingsWindowPublicGateEnabled()
end

function PortalAuthority:IsSettingsWindowHostEnabled()
    return PA_IsSettingsWindowHostEnabled()
end

BINDING_HEADER_PORTAL_AUTHORITY = "Portal Authority"
BINDING_NAME_PORTAL_AUTHORITY_OPEN_SETTINGS = (PortalAuthority and PortalAuthority.L and PortalAuthority.L["COMMON_OPEN_SETTINGS"]) or "Open Settings"

function PA_Binding_ToggleSettingsWindow()
    if not PortalAuthority then
        return
    end

    if PortalAuthority.IsSettingsWindowOpen and PortalAuthority:IsSettingsWindowOpen() then
        if PortalAuthority.CloseSettingsWindow then
            PortalAuthority:CloseSettingsWindow()
        end
        return
    end

    if PortalAuthority.HandleSlashRootEntry then
        PortalAuthority:HandleSlashRootEntry()
    end
end

function PA_IsDiagGateEnabled()
    return PortalAuthority._buildConfig.gates.diag == true
end

function PortalAuthority:IsDiagDumpEnabled()
    return PA_IsDiagGateEnabled()
end

function PA_IsLocaleDevGateEnabled()
    return PortalAuthority._buildConfig.gates.localeDev == true
end

function PortalAuthority:IsLocaleDevGateEnabled()
    return PA_IsLocaleDevGateEnabled()
end

function PA_IsOnboardingD1DevGateEnabled()
    return PortalAuthority._buildConfig.gates.onboardingD1Dev == true
end

function PortalAuthority:IsOnboardingD1DevGateEnabled()
    return PA_IsOnboardingD1DevGateEnabled()
end

function PA_IsOnboardingD3DevGateEnabled()
    return PortalAuthority._buildConfig.gates.onboardingD3Dev == true
end

function PortalAuthority:IsOnboardingD3DevGateEnabled()
    return PA_IsOnboardingD3DevGateEnabled()
end

function PA_IsOnboardingD4DevGateEnabled()
    return PA_IsOnboardingD3DevGateEnabled() and PortalAuthority._buildConfig.gates.onboardingD4Dev == true
end

function PortalAuthority:IsOnboardingD4DevGateEnabled()
    return PA_IsOnboardingD4DevGateEnabled()
end

function PA_IsOnboardingD3PublicGateEnabled()
    return PortalAuthority._buildConfig.gates.onboardingD3Public == true
end

function PortalAuthority:IsOnboardingD3PublicGateEnabled()
    return PA_IsOnboardingD3PublicGateEnabled()
end

function PA_IsOnboardingD4PublicGateEnabled()
    return PA_IsOnboardingD3PublicGateEnabled() and PortalAuthority._buildConfig.gates.onboardingD4Public == true
end

function PortalAuthority:IsOnboardingD4PublicGateEnabled()
    return PA_IsOnboardingD4PublicGateEnabled()
end

function PA_IsOnboardingQualifyingUpgradePublicGateEnabled()
    return PortalAuthority._buildConfig.gates.onboardingQualifyingUpgradePublic == true
end

function PortalAuthority:IsOnboardingQualifyingUpgradePublicGateEnabled()
    return PA_IsOnboardingQualifyingUpgradePublicGateEnabled()
end

function PA_IsOnboardingD3Enabled()
    return PA_IsOnboardingD3DevGateEnabled() or PA_IsOnboardingD3PublicGateEnabled()
end

function PortalAuthority:IsOnboardingD3Enabled()
    return PA_IsOnboardingD3Enabled()
end

function PA_IsOnboardingD4Enabled()
    return PA_IsOnboardingD4DevGateEnabled() or PA_IsOnboardingD4PublicGateEnabled()
end

function PortalAuthority:IsOnboardingD4Enabled()
    return PA_IsOnboardingD4Enabled()
end

function PortalAuthority:IsCombatAlertsEnabled()
    local db = PortalAuthorityDB or self.defaults or {}
    return db.combatAlertsEnabled ~= false
end

function PortalAuthority:SetSettingsKeystoneBootstrapState(state)
    local states = PortalAuthority._buildConfig.settings.keystoneBootstrapStates
    local normalized = type(state) == "string" and states[state] and state or "unknown"
    local currentState = self and self._settingsKeystoneBootstrapState or nil
    local current = type(currentState) == "string" and states[currentState] and currentState or "unknown"

    if current == "ran" then
        return current
    end
    if current == "scheduled" and (normalized == "unknown" or normalized == "scheduled" or normalized == "suppressed") then
        return current
    end
    if current == "suppressed" and normalized ~= "ran" then
        return current
    end
    if normalized == "unknown" and self and self._settingsKeystoneBootstrapState ~= nil then
        return current
    end

    self._settingsKeystoneBootstrapState = normalized
    return normalized
end

function PortalAuthority:GetSettingsKeystoneBootstrapState()
    local state = self and self._settingsKeystoneBootstrapState or nil
    local states = PortalAuthority._buildConfig.settings.keystoneBootstrapStates
    if type(state) == "string" and states[state] then
        return state
    end
    return "unknown"
end

function PortalAuthority:SetSettingsBootstrapActive(state)
    local states = PortalAuthority._buildConfig.settings.bootstrapActiveStates
    local normalized = type(state) == "string" and states[state] and state or "none"
    self._settingsBootstrapActive = normalized
    return normalized
end

function PortalAuthority:GetSettingsBootstrapActive()
    local state = self and self._settingsBootstrapActive or nil
    local states = PortalAuthority._buildConfig.settings.bootstrapActiveStates
    if type(state) == "string" and states[state] then
        return state
    end
    return "none"
end

CoreInternal.PA_IsUiSurfaceGateEnabled = PA_IsUiSurfaceGateEnabled
CoreInternal.PA_IsStaticBaselineGateEnabled = PA_IsStaticBaselineGateEnabled
CoreInternal.PA_IsSettingsBaselineGateEnabled = PA_IsSettingsBaselineGateEnabled
CoreInternal.PA_IsSettingsEagerBuildGateEnabled = PA_IsSettingsEagerBuildGateEnabled
CoreInternal.PA_IsSettingsDirectBuildGateEnabled = PA_IsSettingsDirectBuildGateEnabled
CoreInternal.PA_IsSettingsWindowHostEnabled = PA_IsSettingsWindowHostEnabled
CoreInternal.PA_IsSettingsWindowDevGateEnabled = PA_IsSettingsWindowDevGateEnabled
CoreInternal.PA_IsSettingsWindowPublicGateEnabled = PA_IsSettingsWindowPublicGateEnabled
CoreInternal.PA_IsLocaleDevGateEnabled = PA_IsLocaleDevGateEnabled
CoreInternal.PA_IsOnboardingD1DevGateEnabled = PA_IsOnboardingD1DevGateEnabled
CoreInternal.PA_IsOnboardingD3DevGateEnabled = PA_IsOnboardingD3DevGateEnabled
CoreInternal.PA_IsOnboardingD4DevGateEnabled = PA_IsOnboardingD4DevGateEnabled
CoreInternal.PA_IsOnboardingD3PublicGateEnabled = PA_IsOnboardingD3PublicGateEnabled
CoreInternal.PA_IsOnboardingD4PublicGateEnabled = PA_IsOnboardingD4PublicGateEnabled
CoreInternal.PA_IsOnboardingQualifyingUpgradePublicGateEnabled = PA_IsOnboardingQualifyingUpgradePublicGateEnabled
CoreInternal.PA_IsOnboardingD3Enabled = PA_IsOnboardingD3Enabled
CoreInternal.PA_IsOnboardingD4Enabled = PA_IsOnboardingD4Enabled
CoreInternal.PA_ApplyLocalePayloadTable = PA_ApplyLocalePayloadTable
CoreInternal.PA_RegisterLocalePayload = PA_RegisterLocalePayload
CoreInternal.PA_FinalizeLocaleStateFromCharacterStore = PA_FinalizeLocaleStateFromCharacterStore
CoreInternal.PA_NormalizeSupportedLocaleCode = PA_NormalizeSupportedLocaleCode
