local ADDON_NAME, private = ... -- luacheck: ignore

-- RealUI Dual-Specialization Support System
-- This module handles automatic profile switching based on specialization changes
-- Integrates LibDualSpec for automatic profile switching
-- Implements specialization detection and change handling
-- Creates per-spec configuration storage and retrieval

local RealUI = private.RealUI
local debug = RealUI.GetDebug("DualSpecSystem")

local DualSpecSystem = {}
RealUI.DualSpecSystem = DualSpecSystem

-- LibDualSpec integration
local LDS = _G.LibStub("LibDualSpec-1.0")

-- Specialization tracking
local currentSpec = nil
local specProfiles = {}
local specConfigurations = {}
local isInitialized = false
local isLibDualSpecSetup = false
local initialSpecSyncPending = false

-- Profile to Layout Mapping (from Core.lua)
local profileToLayout = {
    ["RealUI"] = 1,
    ["RealUI-Healing"] = 2
}

local layoutToProfile = {
    "RealUI",
    "RealUI-Healing"
}

-- (EnsureBartenderActionBarsProfiles removed with Bartender4 support,
--  2026-08-22: it seeded bar-enabled flags into Bartender4DB's
--  ActionBars namespace. RealUI_ActionBars seeds its own profiles
--  through AceDB defaults + ProfileCoordinator's copy-on-create.)

--- Keep RealUI_ActionBars' LibDualSpec mapping in sync with Core's so
--- spec-triggered switches stay coordinated (the bars DB has its own LDS
--- integration and would otherwise fight the coordinator).
local function SyncActionBarsLDS(specIndex, profileName)
    if not RealUI.ProfileCoordinator:IsScopeLinked(RealUI.ProfileCoordinator.SCOPE_ACTIONBARS) then
        return
    end
    local AceAddon = _G.LibStub and _G.LibStub("AceAddon-3.0", true)
    local rab = AceAddon and AceAddon:GetAddon("RealUIActionBars", true)
    if rab and rab.db and rab.db.SetDualSpecProfile then
        debug("Syncing action bars LDS mapping for spec:", specIndex, "->", profileName)
        rab.db:SetDualSpecProfile(profileName, specIndex)
    end
end

-- Enhanced Specialization Detection Functions
function DualSpecSystem:GetCurrentSpecialization()
    if _G.IsPlayerInitialSpec() then
        debug("Player is in initial spec state")
        return nil
    end

    local specIndex = _G.C_SpecializationInfo.GetSpecialization()
    if not specIndex then
        debug("No specialization index available")
        return nil
    end

    local specInfo = RealUI.charInfo.specs[specIndex]
    if not specInfo then
        debug("No spec info found for index:", specIndex)
        return nil
    end

    debug("Current specialization:", specIndex, specInfo.name, specInfo.role)
    return specInfo
end

function DualSpecSystem:GetSpecializationRole(specIndex)
    if not specIndex or not RealUI.charInfo.specs[specIndex] then
        debug("Invalid spec index or no spec info:", specIndex)
        return nil
    end

    local role = RealUI.charInfo.specs[specIndex].role
    debug("Spec role for", specIndex, ":", role)
    return role
end

function DualSpecSystem:IsHealingSpec(specIndex)
    local role = self:GetSpecializationRole(specIndex)
    local isHealer = role == "HEALER"
    debug("Is healing spec", specIndex, ":", isHealer)
    return isHealer
end

function DualSpecSystem:GetAllSpecializations()
    local specs = {}
    for i = 1, #RealUI.charInfo.specs do
        specs[i] = {
            index = i,
            info = RealUI.charInfo.specs[i],
            profile = self:GetSpecProfile(i),
            role = self:GetSpecializationRole(i)
        }
    end
    debug("Retrieved all specializations:", #specs)
    return specs
end

-- Enhanced Profile Assignment Functions
function DualSpecSystem:SetSpecProfile(specIndex, profileName)
    if not specIndex or not profileName then
        debug("Invalid parameters for SetSpecProfile:", specIndex, profileName)
        return false
    end

    debug("Setting spec profile:", specIndex, "->", profileName)
    specProfiles[specIndex] = profileName

    -- Persist custom assignment in db.char.specProfiles
    if RealUI.db and RealUI.db.char then
        if not RealUI.db.char.specProfiles then
            RealUI.db.char.specProfiles = {}
        end
        RealUI.db.char.specProfiles[specIndex] = profileName
        debug("Persisted spec profile in db.char.specProfiles:", specIndex, "->", profileName)
    end

    -- Update character database layout mapping (legacy compat)
    local dbc = RealUI.db and RealUI.db.char
    if dbc and dbc.layout and dbc.layout.spec then
        local layoutIndex = profileToLayout[profileName] or 1
        dbc.layout.spec[specIndex] = layoutIndex
        debug("Updated layout spec mapping:", specIndex, "->", layoutIndex)
    end

    -- Update LibDualSpec mapping if initialized
    if isLibDualSpecSetup and RealUI.db then
        debug("Updating LibDualSpec profile mapping for spec:", specIndex)
        RealUI.db:SetDualSpecProfile(profileName, specIndex)

        SyncActionBarsLDS(specIndex, profileName)
    end

    debug("Spec profile set successfully:", specIndex, "->", profileName)
    return true
end

function DualSpecSystem:GetSpecProfile(specIndex)
    if not specIndex then
        debug("No spec index provided for GetSpecProfile")
        return nil
    end

    local profile = specProfiles[specIndex]
    debug("Retrieved spec profile:", specIndex, "->", profile)
    return profile
end

function DualSpecSystem:GetDefaultProfileForSpec(specIndex)
    -- Check for a custom profile assignment first (persisted in db.char.specProfiles)
    if RealUI.db and RealUI.db.char and RealUI.db.char.specProfiles then
        local customProfile = RealUI.db.char.specProfiles[specIndex]
        if customProfile then
            -- Verify the custom profile still exists in the database
            local profiles = RealUI.db:GetProfiles()
            if profiles then
                for _, name in ipairs(profiles) do
                    if name == customProfile then
                        debug("Custom profile for spec", specIndex, ":", customProfile)
                        return customProfile
                    end
                end
            end
            -- Custom profile was deleted — fall through to role-based default
            debug("Custom profile", customProfile, "no longer exists for spec", specIndex, "— falling back to default")
        end
    end

    -- Fall back to role-based default
    local defaultProfile
    if self:IsHealingSpec(specIndex) then
        defaultProfile = layoutToProfile[2] -- Healing profile
    else
        defaultProfile = layoutToProfile[1] -- DPS/Tank profile
    end

    debug("Default profile for spec", specIndex, ":", defaultProfile)
    return defaultProfile
end

function DualSpecSystem:GetAllSpecProfiles()
    local profiles = {}
    for specIndex, profileName in pairs(specProfiles) do
        profiles[specIndex] = {
            specIndex = specIndex,
            profileName = profileName,
            specInfo = RealUI.charInfo.specs[specIndex],
            isDefault = profileName == self:GetDefaultProfileForSpec(specIndex)
        }
    end
    debug("Retrieved all spec profiles:", #profiles)
    return profiles
end

-- Enhanced Automatic Profile Switching
function DualSpecSystem:SwitchToSpecProfile(specIndex)
    if not specIndex then
        debug("No spec index provided for profile switching")
        return false
    end

    if not isInitialized then
        debug("DualSpecSystem not initialized, cannot switch profiles")
        return false
    end

    local targetProfile = self:GetSpecProfile(specIndex)
    if not targetProfile then
        targetProfile = self:GetDefaultProfileForSpec(specIndex)
        debug("Using default profile for spec:", specIndex, "->", targetProfile)

        -- Set the default profile for future use
        self:SetSpecProfile(specIndex, targetProfile)
    end

    if not targetProfile then
        debug("No profile found for spec:", specIndex)
        return false
    end

    local currentProfile = RealUI.ProfileSystem:GetCurrentProfile()
    if currentProfile == targetProfile then
        debug("Already using correct profile:", targetProfile)
        currentSpec = specIndex
        return true
    end

    debug("Switching profile for spec change:", currentProfile, "->", targetProfile)

    -- Save current spec configuration before switching
    if currentSpec and currentSpec ~= specIndex then
        self:SaveCurrentSpecConfiguration()
    end

    -- Delegate to ProfileCoordinator for coordinated switching across all linked scopes
    local success, warnings = RealUI.ProfileCoordinator:CoordinatedSwitch(targetProfile)
    if success then
        debug("Coordinated profile switch completed successfully")

        -- Load spec-specific configuration
        self:LoadSpecConfiguration(specIndex)

        -- Update current spec tracking
        currentSpec = specIndex

        if warnings and #warnings > 0 then
            for _, w in ipairs(warnings) do
                debug("Switch warning:", w)
            end
        end
    else
        debug("Coordinated profile switch failed or deferred")
        if warnings then
            for _, w in ipairs(warnings) do
                debug("Switch issue:", w)
            end
        end
    end

    return success
end

function DualSpecSystem:CanSwitchProfiles()
    if _G.InCombatLockdown() then
        debug("Cannot switch profiles during combat")
        return false, "Cannot switch profiles during combat"
    end

    if not isInitialized then
        debug("DualSpecSystem not initialized")
        return false, "DualSpecSystem not initialized"
    end

    if not RealUI.ProfileSystem then
        debug("ProfileSystem not available")
        return false, "ProfileSystem not available"
    end

    return true
end

-- Enhanced Specialization Change Handling
function DualSpecSystem:OnSpecializationChanged(specIndex)
    debug("Specialization changed to:", specIndex)

    if not specIndex then
        debug("Invalid specialization index")
        return
    end

    -- Check if we can switch profiles
    local canSwitch, reason = self:CanSwitchProfiles()
    if not canSwitch then
        debug("Cannot switch profiles:", reason)

        -- Schedule the switch for when combat ends if in combat
        if _G.InCombatLockdown() then
            debug("Scheduling profile switch for after combat")
            RealUI:RegisterEvent("PLAYER_REGEN_ENABLED", function()
                RealUI:UnregisterEvent("PLAYER_REGEN_ENABLED")
                self:OnSpecializationChanged(specIndex)
            end)
        end
        return
    end

    -- Update RealUI character info
    if RealUI.charInfo.specs[specIndex] then
        RealUI.charInfo.specs.current = RealUI.charInfo.specs[specIndex]
        debug("Updated current spec info:", RealUI.charInfo.specs.current.name, RealUI.charInfo.specs.current.role)
    end

    -- Switch profile if needed
    if self:SwitchToSpecProfile(specIndex) then
        debug("Profile switched successfully for spec:", specIndex)

        -- Update layout if needed
        local dbc = RealUI.db and RealUI.db.char
        local layoutSwitched = false
        if dbc and dbc.layout and dbc.layout.spec[specIndex] then
            local targetLayout = dbc.layout.spec[specIndex]
            if dbc.layout.current ~= targetLayout then
                debug("Updating layout:", dbc.layout.current, "->", targetLayout)
                if RealUI.LayoutManager then
                    RealUI.LayoutManager:SwitchToLayout(targetLayout)
                else
                    RealUI:UpdateLayout(targetLayout)
                end
                layoutSwitched = true
            end
        end

        -- When the RealUI layout index didn't change (DPS→DPS, DPS→Tank, etc.),
        -- WoW 12's per-spec EditMode tracking may have reset the active layout to
        -- a preset (often "Modern"). Re-activate explicitly. We skip this when
        -- layoutSwitched=true because SwitchToLayout already calls ActivateLayout
        -- via its RegisterLayoutChangeCallback — calling it twice races the bars recompute.
        if not layoutSwitched and RealUI.EditModeManager and RealUI.EditModeManager:IsInitialized() then
            local role = self:IsHealingSpec(specIndex) and "healing" or "dpstank"
            debug("Same-layout spec swap: re-asserting EditMode layout for role:", role)
            RealUI.EditModeManager:ActivateLayout(role)
        end

        -- Notify other systems of the spec change
        RealUI:SendMessage("REALUI_SPEC_CHANGED", specIndex, RealUI.charInfo.specs[specIndex])

    else
        debug("Failed to switch profile for spec:", specIndex)
    end
end

function DualSpecSystem:ForceSpecializationUpdate()
    debug("Forcing specialization update")

    local currentSpecInfo = self:GetCurrentSpecialization()
    if currentSpecInfo then
        self:OnSpecializationChanged(currentSpecInfo.index)
    else
        debug("No current specialization available for forced update")
    end
end

-- Enhanced LibDualSpec Integration
function DualSpecSystem:SetupLibDualSpec()
    if not RealUI.db then
        debug("Database not available for LibDualSpec setup")
        return false
    end

    if isLibDualSpecSetup then
        debug("LibDualSpec already set up")
        return true
    end

    debug("Setting up LibDualSpec integration")

    -- Enhance database with LibDualSpec support
    LDS:EnhanceDatabase(RealUI.db, "RealUI")

    -- Create healing profile if it doesn't exist
    local profiles = RealUI.db:GetProfiles()
    local hasHealingProfile = false
    for _, profile in ipairs(profiles) do
        if profile == layoutToProfile[2] then
            hasHealingProfile = true
            break
        end
    end

    if not hasHealingProfile then
        debug("Creating healing profile")
        RealUI.db:SetProfile(layoutToProfile[2])
        RealUI.db:SetProfile(layoutToProfile[1]) -- Switch back to default
    end

    -- Set up dual-spec profiles for all specs
    -- NOTE: We set isLibDualSpecSetup = true BEFORE calling SetSpecProfile
    -- so that SetSpecProfile's action-bars LDS sync branch is active.
    isLibDualSpecSetup = true

    for specIndex = 1, #RealUI.charInfo.specs do
        local spec = RealUI.charInfo.specs[specIndex]
        local profileName = self:GetDefaultProfileForSpec(specIndex)

        debug("Setting up spec profile:", specIndex, spec.name, spec.role, "->", profileName)

        -- Set the dual-spec profile in LibDualSpec (Core)
        RealUI.db:SetDualSpecProfile(profileName, specIndex)

        -- Update our internal mapping (this also syncs the bars DB's LDS via SetSpecProfile)
        self:SetSpecProfile(specIndex, profileName)
    end

    debug("LibDualSpec setup complete")
    return true
end

function DualSpecSystem:IsLibDualSpecReady()
    return isLibDualSpecSetup and RealUI.db ~= nil
end

function DualSpecSystem:RefreshLibDualSpecProfiles()
    if not self:IsLibDualSpecReady() then
        debug("LibDualSpec not ready for refresh")
        return false
    end

    debug("Refreshing LibDualSpec profiles")

    -- Re-setup all spec profiles (Core + action bars if linked)
    for specIndex = 1, #RealUI.charInfo.specs do
        local profileName = self:GetSpecProfile(specIndex)
        if profileName then
            RealUI.db:SetDualSpecProfile(profileName, specIndex)
            debug("Refreshed Core LDS spec profile:", specIndex, "->", profileName)
            SyncActionBarsLDS(specIndex, profileName)
        end
    end

    return true
end

-- Enhanced Per-Spec Configuration Storage and Retrieval
function DualSpecSystem:SaveSpecConfiguration(specIndex, configData)
    if not specIndex then
        debug("No spec index provided for SaveSpecConfiguration")
        return false
    end

    -- Use current spec if no specific data provided
    if not configData then
        configData = self:GetCurrentConfiguration()
    end

    if not configData then
        debug("No configuration data available to save")
        return false
    end

    debug("Saving configuration for spec:", specIndex)

    -- Store in memory
    specConfigurations[specIndex] = {
        data = configData,
        timestamp = _G.time(),
        specInfo = RealUI.charInfo.specs[specIndex]
    }

    -- Store in profile database for persistence
    local profile = RealUI.ProfileSystem:GetProfileData()
    if profile then
        if not profile.specConfigs then
            profile.specConfigs = {}
        end
        profile.specConfigs[specIndex] = specConfigurations[specIndex]
        debug("Saved configuration to profile database for spec:", specIndex)
    end

    debug("Configuration saved successfully for spec:", specIndex)
    return true
end

function DualSpecSystem:LoadSpecConfiguration(specIndex)
    if not specIndex then
        debug("No spec index provided for LoadSpecConfiguration")
        return nil
    end

    debug("Loading configuration for spec:", specIndex)

    -- Try memory first
    local config = specConfigurations[specIndex]

    -- Fall back to profile database
    if not config then
        local profile = RealUI.ProfileSystem:GetProfileData()
        if profile and profile.specConfigs then
            config = profile.specConfigs[specIndex]
            if config then
                -- Cache in memory
                specConfigurations[specIndex] = config
                debug("Loaded configuration from profile database for spec:", specIndex)
            end
        end
    end

    if config then
        debug("Configuration loaded for spec:", specIndex, "timestamp:", config.timestamp)

        -- Apply the configuration
        if config.data then
            self:ApplyConfiguration(config.data)
        end

        return config.data
    else
        debug("No configuration found for spec:", specIndex)
        return nil
    end
end

function DualSpecSystem:ClearSpecConfiguration(specIndex)
    if not specIndex then
        debug("No spec index provided for ClearSpecConfiguration")
        return false
    end

    debug("Clearing configuration for spec:", specIndex)

    -- Clear from memory
    specConfigurations[specIndex] = nil

    -- Clear from profile database
    local profile = RealUI.ProfileSystem:GetProfileData()
    if profile and profile.specConfigs then
        profile.specConfigs[specIndex] = nil
        debug("Cleared configuration from profile database for spec:", specIndex)
    end

    debug("Configuration cleared successfully for spec:", specIndex)
    return true
end

function DualSpecSystem:GetAllSpecConfigurations()
    local configs = {}

    -- Get from memory first
    for specIndex, config in pairs(specConfigurations) do
        configs[specIndex] = config
    end

    -- Fill in any missing from profile database
    local profile = RealUI.ProfileSystem:GetProfileData()
    if profile and profile.specConfigs then
        for specIndex, config in pairs(profile.specConfigs) do
            if not configs[specIndex] then
                configs[specIndex] = config
                -- Cache in memory
                specConfigurations[specIndex] = config
            end
        end
    end

    debug("Retrieved all spec configurations:", #configs)
    return configs
end

function DualSpecSystem:SaveCurrentSpecConfiguration()
    if not currentSpec then
        debug("No current spec to save configuration for")
        return false
    end

    debug("Saving current spec configuration:", currentSpec)
    return self:SaveSpecConfiguration(currentSpec)
end

function DualSpecSystem:GetCurrentConfiguration()
    -- Collect current UI state for per-spec persistence.
    -- NOTE: modules are intentionally excluded — module enabled states
    -- are managed solely by db.profile.modules and must not be
    -- overwritten by stale spec-config snapshots.
    --[[ `positions` and `hudSize` were BOTH removed 2026-08-24 (B86/B103).

         They used to be captured here and restored wholesale in
         `ApplyConfiguration`. That is the same fault the note there already
         records for `modules` — a stale snapshot overwriting authoritative
         profile state — and it was left in place for these two.

         RealUI already has per-spec positions: a spec change switches the
         AceDB PROFILE (layout 1 → "RealUI", layout 2 → "RealUI-Healing"), and
         positions live on the profile. Snapshotting them per spec on top of
         that is not a second feature, it is a second writer racing the first.

         Caught in a dump: a linked HuD write reached
         `RealUI-Healing.positions[2].HuDY = -220` correctly, and the spec swap
         put the stale `-52` back over it, in raw storage as well as live.

         `positions` was also captured by REFERENCE, not copied, so the
         "snapshot" aliased the live table until a profile switch swapped it
         out — which is its own way of being wrong. ]]
    return {
        timestamp = _G.time(),
    }
end

function DualSpecSystem:ApplyConfiguration(configData)
    if not configData then
        debug("No configuration data to apply")
        return false
    end

    debug("Applying configuration data")

    --[[ NOTHING is applied from the snapshot any more (B86/B103, 2026-08-24).

         `hudSize` and `positions` used to be restored here. Both are profile
         state, and a spec change already switches the profile — so restoring a
         per-spec copy on top could only ever overwrite the profile with an
         older version of itself. It is exactly the fault the `modules` note
         below describes, and it was killing linked position writes (B86) and
         is a second, independent way for "Use Large HuD" to differ between
         specs on its own (B92).

         Kept as a function rather than deleted: `LoadSpecConfiguration` still
         calls it, older saved variables still hold these fields, and ignoring
         them is what makes those stale snapshots harmless. ]]

    -- NOTE: Do NOT apply configData.modules here. Module enabled states
    -- are authoritative in db.profile.modules and managed by AceDB's
    -- profile system + the snapshot restore in Core:OnProfileUpdate.
    -- Wholesale-replacing db.profile.modules with a stale snapshot was
    -- a persistence vector for the CastBars-disabled-on-healer-login bug.

    debug("Configuration applied successfully")
    return true
end

-- Enhanced Event Handlers
local function UpdateSpec()
    debug("UpdateSpec called")

    if _G.IsPlayerInitialSpec() then
        debug("Player is in initial spec state, seeding LDS currentSpec only")
        -- Only seed LDS.currentSpec here. Do NOT call CheckDualSpecState on
        -- all databases during initial spec — other DBs' namespaces may not be
        -- fully initialized yet; RealUI's DB is handled when the spec
        -- actually fires later.
        LDS.currentSpec = RealUI.charInfo.specs.current.index

        -- Schedule a deferred profile/layout sync once initial spec resolves
        if not initialSpecSyncPending then
            initialSpecSyncPending = true
            RealUI:ScheduleTimer(function()
                initialSpecSyncPending = false
                if not _G.IsPlayerInitialSpec() then
                    local specIndex = _G.C_SpecializationInfo.GetSpecialization()
                    if specIndex and RealUI.DualSpecSystem:IsInitialized() then
                        -- Always call OnSpecializationChanged to ensure currentSpec
                        -- is set and profile/layout are correct, even if the profile
                        -- already happens to match.
                        RealUI.DualSpecSystem:OnSpecializationChanged(specIndex)
                    end
                end
            end, 2)
        else
            debug("Initial-spec deferred sync already queued")
        end
        return
    end

    local specInfo = RealUI.charInfo.specs
    local newSpecIndex = _G.C_SpecializationInfo.GetSpecialization()

    if not newSpecIndex then
        debug("No specialization index available")
        return
    end

    if not specInfo.current or specInfo.current.index ~= newSpecIndex then
        debug("Spec change detected:", specInfo.current and specInfo.current.index or "nil", "->", newSpecIndex)

        -- Update spec info
        if RealUI.charInfo.specs[newSpecIndex] then
            specInfo.current = RealUI.charInfo.specs[newSpecIndex]
            debug("Updated current spec info:", specInfo.current.name, specInfo.current.role)
        end

        -- Handle the specialization change
        RealUI.DualSpecSystem:OnSpecializationChanged(newSpecIndex)
    else
        debug("No spec change detected, current:", specInfo.current.index)
    end
end

local function OnPlayerLogin()
    debug("Player login detected, initializing spec tracking")

    -- Small delay to ensure all systems are ready
    RealUI:ScheduleTimer(function()
        if RealUI.DualSpecSystem:IsInitialized() then
            RealUI.DualSpecSystem:ForceSpecializationUpdate()
        end
    end, 1)
end

local function OnPlayerEnterWorld()
    debug("Player entered world, checking spec state")

    -- Defer profile switch out of the PLAYER_ENTERING_WORLD event batch.
    -- The profile switch cascade (CoordinatedSwitch → ActionBars:RefreshMod)
    -- touches restricted action bar frames which taints execution. Without
    -- deferral that taint propagates to CastingBarMixin:OnEvent (also
    -- registered for PLAYER_ENTERING_WORLD) and causes a "forbidden table"
    -- error when it indexes CastingBarTypeInfo whose keys are secretwrap values.
    _G.C_Timer.After(0, UpdateSpec)
end

-- Enhanced Initialization
function DualSpecSystem:Initialize()
    debug("Initializing DualSpecSystem")

    if isInitialized then
        debug("DualSpecSystem already initialized")
        return true
    end

    -- Initialize spec profiles mapping
    for specIndex = 1, #RealUI.charInfo.specs do
        local defaultProfile = self:GetDefaultProfileForSpec(specIndex)
        self:SetSpecProfile(specIndex, defaultProfile)
        debug("Initialized spec profile mapping:", specIndex, "->", defaultProfile)
    end

    -- Set up current spec tracking
    local currentSpecInfo = self:GetCurrentSpecialization()
    if currentSpecInfo then
        currentSpec = currentSpecInfo.index
        debug("Current spec:", currentSpec, currentSpecInfo.name, currentSpecInfo.role)
    else
        debug("No current spec available during initialization")
    end

    -- Register event handlers for specialization changes
    RealUI:RegisterEvent("UNIT_LEVEL", UpdateSpec)
    RealUI:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED", UpdateSpec)
    RealUI:RegisterEvent("PLAYER_TALENT_UPDATE", UpdateSpec)
    RealUI:RegisterEvent("TRAIT_CONFIG_UPDATED", UpdateSpec)
    RealUI:RegisterEvent("PLAYER_LOGIN", OnPlayerLogin)
    RealUI:RegisterEvent("PLAYER_ENTERING_WORLD", OnPlayerEnterWorld)

    isInitialized = true
    debug("DualSpecSystem initialized successfully")
    return true
end

function DualSpecSystem:PostInitialize()
    debug("Post-initializing DualSpecSystem")

    if not isInitialized then
        debug("Cannot post-initialize: DualSpecSystem not initialized")
        return false
    end

    -- Set up LibDualSpec integration after database is ready
    if RealUI.db then
        local success = self:SetupLibDualSpec()
        if not success then
            debug("Failed to set up LibDualSpec integration")
            return false
        end
    else
        debug("Database not ready for LibDualSpec setup")
        return false
    end

    -- Register OnProfileDeleted callback to handle custom profile deletion fallback (Req 9.7)
    RealUI.db.RegisterCallback(self, "OnProfileDeleted", function(_, _, profileKey)
        debug("Profile deleted:", profileKey)
        local dbc = RealUI.db and RealUI.db.char
        if not dbc or not dbc.specProfiles then return end

        for specIndex, assignedProfile in pairs(dbc.specProfiles) do
            if assignedProfile == profileKey then
                -- Revert to built-in default for this spec's role
                local defaultProfile
                if DualSpecSystem:IsHealingSpec(specIndex) then
                    defaultProfile = layoutToProfile[2] -- "RealUI-Healing"
                else
                    defaultProfile = layoutToProfile[1] -- "RealUI"
                end

                debug("Reverting spec", specIndex, "from deleted profile", profileKey, "to default", defaultProfile)
                dbc.specProfiles[specIndex] = defaultProfile
                specProfiles[specIndex] = defaultProfile

                -- Update LibDualSpec mapping
                if isLibDualSpecSetup then
                    RealUI.db:SetDualSpecProfile(defaultProfile, specIndex)
                    SyncActionBarsLDS(specIndex, defaultProfile)
                end

                -- Notify user
                RealUI:Notification(
                    "Profile Deleted",
                    false,
                    "Spec " .. specIndex .. " reverted to '" .. defaultProfile .. "' (deleted: '" .. profileKey .. "')",
                    nil,
                    [[Interface\AddOns\RealUI\Media\Notification_Alert]]
                )
            end
        end
    end)

    -- Load existing spec configurations
    self:GetAllSpecConfigurations()

    debug("DualSpecSystem post-initialization completed successfully")
    return true
end

function DualSpecSystem:Shutdown()
    debug("Shutting down DualSpecSystem")

    -- Save current spec configuration before shutdown
    if currentSpec then
        self:SaveCurrentSpecConfiguration()
    end

    -- Unregister events
    RealUI:UnregisterEvent("UNIT_LEVEL")
    RealUI:UnregisterEvent("PLAYER_SPECIALIZATION_CHANGED")
    RealUI:UnregisterEvent("PLAYER_TALENT_UPDATE")
    RealUI:UnregisterEvent("TRAIT_CONFIG_UPDATED")
    RealUI:UnregisterEvent("PLAYER_LOGIN")
    RealUI:UnregisterEvent("PLAYER_ENTERING_WORLD")

    isInitialized = false
    isLibDualSpecSetup = false

    debug("DualSpecSystem shutdown completed")
end

-- Enhanced Utility Functions
function DualSpecSystem:GetCurrentSpec()
    return currentSpec
end

function DualSpecSystem:GetSpecProfiles()
    return specProfiles
end

function DualSpecSystem:GetSpecConfigurations()
    return specConfigurations
end

function DualSpecSystem:IsInitialized()
    return isInitialized
end

function DualSpecSystem:GetSystemStatus()
    return {
        initialized = isInitialized,
        libDualSpecSetup = isLibDualSpecSetup,
        currentSpec = currentSpec,
        specProfilesCount = #specProfiles,
        specConfigurationsCount = #specConfigurations,
        hasDatabase = RealUI.db ~= nil
    }
end

function DualSpecSystem:ValidateSpecIndex(specIndex)
    if not specIndex or type(specIndex) ~= "number" then
        debug("Invalid spec index type:", type(specIndex))
        return false
    end

    if specIndex < 1 or specIndex > #RealUI.charInfo.specs then
        debug("Spec index out of range:", specIndex, "max:", #RealUI.charInfo.specs)
        return false
    end

    return true
end

function DualSpecSystem:GetDebugInfo()
    local info = {
        system = self:GetSystemStatus(),
        currentSpecInfo = currentSpec and RealUI.charInfo.specs[currentSpec] or nil,
        allSpecs = self:GetAllSpecializations(),
        allProfiles = self:GetAllSpecProfiles(),
        profileToLayout = profileToLayout,
        layoutToProfile = layoutToProfile
    }

    debug("Debug info generated")
    return info
end

-- Register with RealUI namespace
RealUI:RegisterNamespace("DualSpecSystem", DualSpecSystem)
