-- Portal Authority — core/events.lua
-- Main core event frame, registrations, and dispatch ordering.
--
-- Depends on: prior core public methods; PortalAuthority.CoreInternal helpers
-- Exposes:    core event frame only
-- DB keys:    none direct
-- Events:     core event registrations only
-- Search key: none

local ADDON_NAME = ...

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

local PA_IsUiSurfaceGateEnabled = CoreInternal.PA_IsUiSurfaceGateEnabled
local PA_IsStaticBaselineGateEnabled = CoreInternal.PA_IsStaticBaselineGateEnabled
local PA_IsSettingsBaselineGateEnabled = CoreInternal.PA_IsSettingsBaselineGateEnabled
local PA_IsSettingsEagerBuildGateEnabled = CoreInternal.PA_IsSettingsEagerBuildGateEnabled
local PA_IsSettingsDirectBuildGateEnabled = CoreInternal.PA_IsSettingsDirectBuildGateEnabled
local PA_IsSettingsWindowHostEnabled = CoreInternal.PA_IsSettingsWindowHostEnabled
local PA_IsSettingsWindowDevGateEnabled = CoreInternal.PA_IsSettingsWindowDevGateEnabled
local PA_IsSettingsWindowPublicGateEnabled = CoreInternal.PA_IsSettingsWindowPublicGateEnabled
local PA_IsLocaleDevGateEnabled = CoreInternal.PA_IsLocaleDevGateEnabled
local PA_IsOnboardingD1DevGateEnabled = CoreInternal.PA_IsOnboardingD1DevGateEnabled
local PA_IsOnboardingD3DevGateEnabled = CoreInternal.PA_IsOnboardingD3DevGateEnabled
local PA_IsOnboardingD4DevGateEnabled = CoreInternal.PA_IsOnboardingD4DevGateEnabled
local PA_IsOnboardingD3PublicGateEnabled = CoreInternal.PA_IsOnboardingD3PublicGateEnabled
local PA_IsOnboardingD4PublicGateEnabled = CoreInternal.PA_IsOnboardingD4PublicGateEnabled
local PA_IsOnboardingQualifyingUpgradePublicGateEnabled = CoreInternal.PA_IsOnboardingQualifyingUpgradePublicGateEnabled
local PA_IsOnboardingD3Enabled = CoreInternal.PA_IsOnboardingD3Enabled
local PA_IsOnboardingD4Enabled = CoreInternal.PA_IsOnboardingD4Enabled
local trim = CoreInternal.trim
local clampNumber = CoreInternal.clampNumber
local PA_Clamp = CoreInternal.PA_Clamp
local PA_ToNumber = CoreInternal.PA_ToNumber
local PA_SafeBool = CoreInternal.PA_SafeBool
local PA_CompareSemver = CoreInternal.PA_CompareSemver
local PA_IsSemverStringValid = CoreInternal.PA_IsSemverStringValid
local PA_GetCurrentAddonVersionState = CoreInternal.PA_GetCurrentAddonVersionState
local VALID_OUTLINES = CoreInternal.VALID_OUTLINES
local VALID_SOUND_CHANNELS = CoreInternal.VALID_SOUND_CHANNELS
local BUILTIN_FONT_FALLBACK = CoreInternal.BUILTIN_FONT_FALLBACK
local PLAYER_LOGIN_MESSAGE = CoreInternal.PLAYER_LOGIN_MESSAGE
local DOCK_ENABLE_DEFAULTS_VERSION = CoreInternal.DOCK_ENABLE_DEFAULTS_VERSION
local PA_PrintPortalAuthorityMessage = CoreInternal.PA_PrintPortalAuthorityMessage
local PA_MaybeShowMPlusNotice = CoreInternal.PA_MaybeShowMPlusNotice
local ResetMPlusNoticeShown = CoreInternal.ResetMPlusNoticeShown
local PA_FinalizeLocaleStateFromCharacterStore = CoreInternal.PA_FinalizeLocaleStateFromCharacterStore
local PA_IsSecretValue = CoreInternal.PA_IsSecretValue
local PA_NormalizeSafeString = CoreInternal.PA_NormalizeSafeString
local PA_NormalizeSupportedLocaleCode = CoreInternal.PA_NormalizeSupportedLocaleCode
local PA_SafeStringsEqual = CoreInternal.PA_SafeStringsEqual
local PA_SafeUnitGUID = CoreInternal.PA_SafeUnitGUID

local frame = CreateFrame("Frame")
frame:RegisterEvent("ADDON_LOADED")
frame:RegisterEvent("PLAYER_LOGIN")
frame:RegisterEvent("PLAYER_LOGOUT")
frame:RegisterEvent("PLAYER_DEAD")
frame:RegisterEvent("UNIT_SPELLCAST_START")
frame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
frame:RegisterEvent("CHALLENGE_MODE_START")
frame:RegisterEvent("CHAT_MSG_WHISPER")
frame:RegisterEvent("CHAT_MSG_BN_WHISPER")
frame:RegisterEvent("CHAT_MSG_INSTANCE_CHAT")
frame:RegisterEvent("CHAT_MSG_INSTANCE_CHAT_LEADER")
frame:RegisterEvent("CHAT_MSG_RAID")
frame:RegisterEvent("CHAT_MSG_RAID_LEADER")
frame:RegisterEvent("CHAT_MSG_PARTY")
frame:RegisterEvent("CHAT_MSG_PARTY_LEADER")
frame:RegisterEvent("UNIT_DIED")
frame:RegisterEvent("GROUP_ROSTER_UPDATE")
frame:RegisterEvent("PLAYER_REGEN_DISABLED")
frame:RegisterEvent("PLAYER_REGEN_ENABLED")

local function PA_GetLocaleCharacterStore()
    if not PortalAuthority or type(PortalAuthority.GetProfilesCharacterStore) ~= "function" then
        return nil
    end
    local ok, charStore = pcall(PortalAuthority.GetProfilesCharacterStore, PortalAuthority)
    if ok and type(charStore) == "table" then
        return charStore
    end
    return nil
end

local function PA_ReconcileLocaleDuringInit(stage)
    if not PA_IsLocaleDevGateEnabled() then
        return false, PortalAuthority and PortalAuthority._activeLocaleCode or nil
    end

    local charStore = PA_GetLocaleCharacterStore()
    if type(charStore) ~= "table" then
        return false, PortalAuthority and PortalAuthority._activeLocaleCode or nil
    end

    PortalAuthority._localeInitAuthorityStage = stage
    return PA_FinalizeLocaleStateFromCharacterStore(charStore)
end

local function PA_ShouldReconcileLocaleOnPlayerLogin()
    if not PA_IsLocaleDevGateEnabled() then
        return false
    end

    if PortalAuthority._localeStateFinalized ~= true then
        return true
    end

    local charStore = PA_GetLocaleCharacterStore()
    local storedOverride = type(charStore) == "table" and charStore._devLocaleOverride or nil
    storedOverride = PA_NormalizeSupportedLocaleCode and PA_NormalizeSupportedLocaleCode(storedOverride) or nil
    if not storedOverride then
        return false
    end

    return storedOverride ~= PortalAuthority._activeLocaleCode
end

local function PA_PerfCoreEventScope(event)
    if event == "CHAT_MSG_WHISPER"
        or event == "CHAT_MSG_BN_WHISPER"
        or event == "CHAT_MSG_INSTANCE_CHAT"
        or event == "CHAT_MSG_INSTANCE_CHAT_LEADER"
        or event == "CHAT_MSG_RAID"
        or event == "CHAT_MSG_RAID_LEADER"
        or event == "CHAT_MSG_PARTY"
        or event == "CHAT_MSG_PARTY_LEADER"
    then
        return "core_event_chat"
    end
    if event == "GROUP_ROSTER_UPDATE" then
        return "core_event_group_roster_update"
    end
    if event == "UNIT_SPELLCAST_START" or event == "UNIT_SPELLCAST_SUCCEEDED" then
        return "core_event_unit_spellcast"
    end
    return "core_event_other"
end

local function PA_CpuDiagCoreTriggerKey(event)
    if event == "GROUP_ROSTER_UPDATE" then
        return "group_roster"
    end
    if event == "PLAYER_REGEN_DISABLED" then
        return "combat_enter"
    end
    if event == "PLAYER_REGEN_ENABLED" then
        return "combat_leave"
    end
    if event == "CHALLENGE_MODE_START" then
        return "challenge_start"
    end
    return nil
end

frame:SetScript("OnEvent", function(_, event, ...)
    if PortalAuthority.summonDebugEnabled
        and (
            event == "CHAT_MSG_WHISPER"
            or event == "CHAT_MSG_BN_WHISPER"
            or event == "CHAT_MSG_INSTANCE_CHAT"
            or event == "CHAT_MSG_INSTANCE_CHAT_LEADER"
            or event == "CHAT_MSG_RAID"
            or event == "CHAT_MSG_RAID_LEADER"
            or event == "CHAT_MSG_PARTY"
            or event == "CHAT_MSG_PARTY_LEADER"
        )
    then
        print("|cffffd100Portal Authority SummonDebug:|r raw event=" .. tostring(event))
    end

    PortalAuthority:CpuDiagRecordDispatcherEvent("core", event)
    local triggerKey = PA_CpuDiagCoreTriggerKey(event)
    if triggerKey then
        PortalAuthority:CpuDiagRecordTrigger(triggerKey)
    end
    local dispatchStart, dispatchState = PortalAuthority:PerfBegin("core_event_dispatch")
    local eventScope = PA_PerfCoreEventScope(event)
    PortalAuthority:CpuDiagRecordCoreEvent(eventScope)
    local eventStart, eventState = PortalAuthority:PerfBegin(eventScope, dispatchState)
    local function finish(...)
        PortalAuthority:PerfEnd(eventScope, eventStart, eventState)
        PortalAuthority:PerfEnd("core_event_dispatch", dispatchStart, dispatchState)
        return ...
    end

    if event == "ADDON_LOADED" then
        local loadedAddonName = ...
        if loadedAddonName ~= ADDON_NAME then
            return finish()
        end

        PortalAuthority._localeInitAuthorityStage = "addon_loaded"
        if PortalAuthority.InitializeProfiles then
            PortalAuthority:InitializeProfiles()
        end
        PortalAuthority:EnsureDB()
        PA_ReconcileLocaleDuringInit("addon_loaded")
        if PortalAuthority.ApplyPublicOnboardingD5b1FreshInstallState then
            PortalAuthority:ApplyPublicOnboardingD5b1FreshInstallState()
        end
        if PortalAuthority.ApplyPublicOnboardingD5b2QualifyingUpgradeState then
            PortalAuthority:ApplyPublicOnboardingD5b2QualifyingUpgradeState()
        end
        if not PA_IsUiSurfaceGateEnabled() then
            PortalAuthority:InitializeKeystoneUtility()
        end
        if not PA_IsStaticBaselineGateEnabled() then
            PortalAuthority:InitializeKeystoneTooltip()
        end
        if not PA_IsUiSurfaceGateEnabled() then
            PortalAuthority:InitializeDeathAlerts()
        end
        if not PA_IsUiSurfaceGateEnabled() and PortalAuthority.InitializeDock then
            PortalAuthority:InitializeDock()
        end
        return finish()
    end

    if event == "PLAYER_LOGOUT" then
        PortalAuthority._qualifyingUpgradeAnnouncementTeardownSuppressed = true
        if PortalAuthority.CpuDiagStopIdleWitnessTicker then
            PortalAuthority:CpuDiagStopIdleWitnessTicker()
        end
        if PortalAuthority.Profiles_HandlePlayerLogout then
            PortalAuthority:Profiles_HandlePlayerLogout()
        end
        return finish()
    end

    if event == "PLAYER_LOGIN" then
        PortalAuthority._qualifyingUpgradeAnnouncementTeardownSuppressed = nil
        if PA_ShouldReconcileLocaleOnPlayerLogin() then
            PA_ReconcileLocaleDuringInit("player_login")
        end
        if not PA_IsSettingsBaselineGateEnabled() then
            PortalAuthority:CpuDiagEnsureSettingsHooks()
        end
        PortalAuthority:ShowLoginMessage()
        PortalAuthority:ShowDockV200MigrationNotice()
        if PA_IsOnboardingD3Enabled() then
            if PA_IsOnboardingD4Enabled() and PortalAuthority.Profiles_GetOnboardingD4Session then
                local session = PortalAuthority:Profiles_GetOnboardingD4Session()
                if type(session) == "table" then
                    PortalAuthority:ResolveAbandonedOnboardingD4Session("reload-recovery")
                end
            end
            if PortalAuthority:IsPremiumWelcomePending() then
                PortalAuthority:ScheduleAutomaticPremiumWelcome("login-auto")
                PortalAuthority._qualifyingUpgradeAnnouncementReadyAt = 0
            elseif PortalAuthority:IsQualifyingUpgradeWelcomePending() then
                PortalAuthority._premiumWelcomeReadyAt = 0
                PortalAuthority:ScheduleAutomaticQualifyingUpgradeAnnouncement("login-auto")
            else
                PortalAuthority._premiumWelcomeReadyAt = 0
                PortalAuthority._qualifyingUpgradeAnnouncementReadyAt = 0
                PortalAuthority:EnsurePremiumWelcomeFrame()
            end
        else
            PortalAuthority._premiumWelcomeReadyAt = 0
            PortalAuthority._qualifyingUpgradeAnnouncementReadyAt = 0
            if PortalAuthority.Profiles_GetOnboardingD4Session and PortalAuthority.Profiles_ClearOnboardingD4Session then
                local staleSession = PortalAuthority:Profiles_GetOnboardingD4Session()
                if type(staleSession) == "table" then
                    PortalAuthority:Profiles_ClearOnboardingD4Session()
                end
            end
        end
        if not PA_IsUiSurfaceGateEnabled() and not PA_IsOnboardingD3Enabled() then
            PortalAuthority:UpdateMoveHintTickerState()
        end
        if not PA_IsStaticBaselineGateEnabled() then
            PortalAuthority:CpuDiagEnsureIdleWitnessSession()
            PortalAuthority:CpuDiagScheduleIdleWitnessStart()
        end
        return finish()
    end

    if event == "CHALLENGE_MODE_START" then
        PA_MPLUS_NOTICE_SHOWN = false
        PA_MaybeShowMPlusNotice()
        return finish()
    end

    if event == "CHAT_MSG_WHISPER"
        or event == "CHAT_MSG_BN_WHISPER"
        or event == "CHAT_MSG_INSTANCE_CHAT"
        or event == "CHAT_MSG_INSTANCE_CHAT_LEADER"
        or event == "CHAT_MSG_RAID"
        or event == "CHAT_MSG_RAID_LEADER"
        or event == "CHAT_MSG_PARTY"
        or event == "CHAT_MSG_PARTY_LEADER"
    then
        local message, sender, _, _, _, _, _, _, _, _, lineID, senderGUID, bnSenderID = ...
        if PortalAuthority.summonDebugEnabled then
            print("|cffffd100Portal Authority SummonDebug:|r dispatch event=" .. tostring(event))
        end
        local okSummon, errSummon = pcall(PortalAuthority.HandleSummonChatEvent, PortalAuthority, event, message, sender, bnSenderID, senderGUID, lineID)
        if PortalAuthority.summonDebugEnabled and not okSummon then
            print("|cffffd100Portal Authority SummonDebug:|r summon error=" .. tostring(errSummon))
        end
        local okStone, errStone = pcall(PortalAuthority.HandleSummonStoneChatEvent, PortalAuthority, event, message, sender, bnSenderID, senderGUID, lineID)
        if PortalAuthority.summonDebugEnabled and not okStone then
            print("|cffffd100Portal Authority SummonDebug:|r stone error=" .. tostring(errStone))
        end
        return finish()
    end

    if event == "GROUP_ROSTER_UPDATE" then
        if PortalAuthority.DeathAlerts and PortalAuthority.DeathAlerts.wipeTracker then
            PortalAuthority.DeathAlerts.wipeTracker = {}
        end
        return finish()
    end

    if event == "PLAYER_REGEN_DISABLED" or event == "PLAYER_REGEN_ENABLED" then
        if PortalAuthority.ApplyCombatAlertsSettings then
            PortalAuthority:ApplyCombatAlertsSettings()
        end
        return finish()
    end

    if event == "PLAYER_DEAD" then
        if not PortalAuthorityDB or not PortalAuthority or not PortalAuthority.DeathAlerts_HandlePlayerDeath then
            return finish()
        end
        PortalAuthority:DeathAlerts_HandlePlayerDeath()
        return finish()
    end

    if event == "UNIT_DIED" then
        if not PortalAuthorityDB or not PortalAuthority or not PortalAuthority.DeathAlerts_HandleDeath then
            return finish()
        end
        local deadGUID, deadName = ...
        PortalAuthority:DeathAlerts_HandleDeath(deadGUID, deadName)
        return finish()
    end

    local unitTarget, castGUID, spellID = ...
    if unitTarget ~= "player" then
        return finish()
    end

    if event == "UNIT_SPELLCAST_START" or event == "UNIT_SPELLCAST_SUCCEEDED" then
        PortalAuthority:TryAnnounce(spellID, castGUID)
    end
    return finish()
end)
