local addonName, NS = ...

-- ============================================================================
-- VAULTSKINS: BACKGROUND SCENES
-- ============================================================================
local Skin = NS.Skin
local Shared = NS.SkinShared
local ConfigureSceneDrift = Shared.ConfigureSceneDrift
local ConfigureSceneParticle = Shared.ConfigureSceneParticle
local ConfigureScenePulse = Shared.ConfigureScenePulse
local GetBackgroundSceneColor = Shared.GetBackgroundSceneColor
local GetBackgroundSceneProfile = Shared.GetBackgroundSceneProfile
local SafeCall = Shared.SafeCall
local SceneAssetPath = Shared.SceneAssetPath
local SetVertexColor = Shared.SetVertexColor
local StopSceneTexture = Shared.StopSceneTexture

-- ============================= SCENE LIFECYCLE ==============================
function Skin:StopBackgroundScene(hide, releaseTextures)
    self.backgroundSceneToken = (self.backgroundSceneToken or 0) + 1
    local frame = WeeklyRewardsFrame
    local scene = frame and frame.VaultSkins and frame.VaultSkins.BackgroundScene
    if not scene then return end
    for _, texture in ipairs({ scene.MistA, scene.MistB, scene.SymbolA, scene.SymbolB, scene.Rays }) do
        StopSceneTexture(texture, hide ~= false)
        if releaseTextures and texture and texture.SetTexture then texture:SetTexture(nil) end
    end
    for _, particle in ipairs(scene.Particles or {}) do
        StopSceneTexture(particle, true)
        if releaseTextures and particle and particle.SetTexture then particle:SetTexture(nil) end
    end
    self.backgroundSceneActive = false
end

-- ============================ SCENE APPLICATION =============================
function Skin:ApplyBackgroundScene(theme, preview)
    if self.sessionDisabledFeatures and self.sessionDisabledFeatures.backgroundScene then return false end
    local frame = WeeklyRewardsFrame
    if not frame or not frame:IsShown() or not self:IsEnabled() then return false end
    local main = self:CreateMainSkin(frame)
    local scene = main.BackgroundScene
    local layer = main.SceneLayer
    if not scene or not layer then return false end

    self:StopBackgroundScene(true, true)
    if not VaultSkinsDB or VaultSkinsDB.backgroundScenes == false then
        layer:Hide()
        return false
    end

    local profile, profileID = GetBackgroundSceneProfile(theme)
    local performance = VaultSkinsDB.backgroundPerformance or "balanced"
    local intensity = math.max(0.20, math.min(1.00, tonumber(VaultSkinsDB.backgroundIntensity) or 0.65))
    if preview then intensity = math.min(1.00, math.max(0.85, intensity * 1.35)) end
    local motion = VaultSkinsDB.backgroundMotion ~= false and performance ~= "low" and profile.kind ~= "static"
    local particlesEnabled = VaultSkinsDB.backgroundParticles ~= false and performance ~= "low" and (profile.particles or 0) > 0
    local primary = theme.scenePrimary or GetBackgroundSceneColor(theme, profile.primary, "glow")
    local secondary = theme.sceneSecondary or GetBackgroundSceneColor(theme, profile.secondary, "accent")

    layer:Show()
    layer:SetAlpha(1)

    local sceneWidth = math.max(760, layer:GetWidth())
    local sceneHeight = math.max(250, layer:GetHeight())
    local mistAPath = SceneAssetPath(profileID, "mist_a.tga")
    local mistBPath = SceneAssetPath(profileID, "mist_b.tga")
    local raysPath = SceneAssetPath(profileID, "rays.tga")
    local symbolPath = SceneAssetPath(profileID, "symbol.tga")
    local particlePath = SceneAssetPath(profileID, "particle.tga")

    local showMist = profile.mist ~= false
    local showMistB = showMist and (performance == "full" or preview)
    local showRays = performance == "full" or preview
    local showSymbolB = performance == "full" or preview
    local showPrimarySymbol = performance ~= "low" or preview

    scene.MistA:ClearAllPoints()
    if showMist then
        scene.MistA:SetTexture(mistAPath)
        scene.MistA:SetBlendMode("ADD")
        scene.MistA:SetPoint("TOPLEFT", layer, "TOPLEFT", -36, 18)
        scene.MistA:SetSize(sceneWidth * 0.88, sceneHeight * 0.98)
        scene.MistA:SetVertexColor(1, 1, 1, 1)
        scene.MistA:SetAlpha((profile.mistAlpha or 0.55) * intensity)
        scene.MistA:Show()
    else
        scene.MistA:SetTexture(nil)
        scene.MistA:Hide()
    end

    scene.MistB:ClearAllPoints()
    if showMistB then
        scene.MistB:SetTexture(mistBPath)
        scene.MistB:SetBlendMode("ADD")
        scene.MistB:SetPoint("BOTTOMRIGHT", layer, "BOTTOMRIGHT", 30, -14)
        scene.MistB:SetSize(sceneWidth * 0.82, sceneHeight * 0.92)
        scene.MistB:SetVertexColor(1, 1, 1, 1)
        scene.MistB:SetAlpha((profile.mistAlpha or 0.55) * 0.82 * intensity)
        scene.MistB:Show()
    else
        scene.MistB:SetTexture(nil)
        scene.MistB:Hide()
    end

    scene.Rays:ClearAllPoints()
    if showRays then
        scene.Rays:SetTexture(raysPath)
        scene.Rays:SetBlendMode("ADD")
        scene.Rays:SetPoint("CENTER", layer, "CENTER", 118, 8)
        scene.Rays:SetSize(sceneWidth * 0.82, sceneHeight * 0.86)
        scene.Rays:SetVertexColor(1, 1, 1, 1)
        scene.Rays:SetAlpha((profile.rayAlpha or 0.20) * intensity)
        scene.Rays:Show()
    else
        scene.Rays:SetTexture(nil)
        scene.Rays:Hide()
    end

    scene.SymbolA:ClearAllPoints()
    if showPrimarySymbol then
        scene.SymbolA:SetTexture(symbolPath)
        scene.SymbolA:SetBlendMode("ADD")
        scene.SymbolA:SetPoint("CENTER", layer, "CENTER", 205, -22)
        scene.SymbolA:SetSize(300, 300)
        scene.SymbolA:SetVertexColor(primary.r, primary.g, primary.b, 1)
        scene.SymbolA:SetAlpha((profile.symbolAlpha or 0.28) * intensity)
        scene.SymbolA:Show()
    else
        scene.SymbolA:SetTexture(nil)
        scene.SymbolA:Hide()
    end

    scene.SymbolB:ClearAllPoints()
    if showSymbolB then
        scene.SymbolB:SetTexture(symbolPath)
        scene.SymbolB:SetBlendMode("ADD")
        scene.SymbolB:SetPoint("CENTER", layer, "CENTER", -118, -48)
        scene.SymbolB:SetSize(190, 190)
        scene.SymbolB:SetTexCoord(1, 0, 0, 1)
        scene.SymbolB:SetVertexColor(secondary.r, secondary.g, secondary.b, 1)
        scene.SymbolB:SetAlpha((profile.symbolAlpha or 0.28) * 0.48 * intensity)
        scene.SymbolB:Show()
    else
        scene.SymbolB:SetTexture(nil)
        scene.SymbolB:Hide()
    end

    if motion then
        if scene.MistA:IsShown() then ConfigureSceneDrift(scene.MistA, (profile.mistAlpha or 0.55) * 0.62 * intensity, (profile.mistAlpha or 0.55) * intensity, profile.duration or 13, profile.driftX or 40, profile.driftY or 8, 0):Play() end
        if scene.MistB:IsShown() then ConfigureSceneDrift(scene.MistB, (profile.mistAlpha or 0.55) * 0.46 * intensity, (profile.mistAlpha or 0.55) * 0.82 * intensity, (profile.duration or 13) * 1.16, -(profile.driftX or 40) * 0.62, -(profile.driftY or 8) * 0.45, 0.35):Play() end
        if scene.SymbolA:IsShown() then ConfigureScenePulse(scene.SymbolA, (profile.symbolAlpha or 0.28) * 0.52 * intensity, (profile.symbolAlpha or 0.28) * intensity, (profile.duration or 13) * 0.62, 0.15):Play() end
        if scene.SymbolB:IsShown() then ConfigureScenePulse(scene.SymbolB, (profile.symbolAlpha or 0.28) * 0.20 * intensity, (profile.symbolAlpha or 0.28) * 0.48 * intensity, (profile.duration or 13) * 0.78, 0.65):Play() end
        if scene.Rays:IsShown() then ConfigureScenePulse(scene.Rays, (profile.rayAlpha or 0.20) * 0.35 * intensity, (profile.rayAlpha or 0.20) * intensity, (profile.duration or 13) * 0.54, 0.30):Play() end
    end

    for index, particle in ipairs(scene.Particles or {}) do
        if particlesEnabled and index <= (performance == "full" and math.min(12, profile.particles or 0) or math.min(4, profile.particles or 0)) then
            local point = particle.VaultSkinsScenePoint
            particle:ClearAllPoints()
            particle:SetTexture(particlePath)
            particle:SetBlendMode("ADD")
            particle:SetPoint("BOTTOMLEFT", layer, "BOTTOMLEFT", layer:GetWidth() * point[1], layer:GetHeight() * point[2])
            local size = point[3] + (performance == "full" and 5 or 0)
            particle:SetSize(size, size)
            particle:SetVertexColor(1, 1, 1, 1)
            local xOffset, yOffset = 10 + (index % 3) * 5, 24 + (index % 4) * 8
            if profile.particleMode == "rise" then
                xOffset = ((index % 2 == 0) and 1 or -1) * (6 + index)
                yOffset = 58 + (index % 4) * 13
            elseif profile.particleMode == "orbit" then
                xOffset = ((index % 2 == 0) and 1 or -1) * (24 + index)
                yOffset = ((index % 3 == 0) and -1 or 1) * (18 + index)
            else
                xOffset = ((index % 2 == 0) and 1 or -1) * (12 + index)
                yOffset = 22 + (index % 5) * 8
            end
            ConfigureSceneParticle(particle, math.min(0.78, (0.34 + (index % 3) * 0.09) * intensity), (4.8 + (index % 4) * 0.72) * (profile.duration or 13) / 13, xOffset, yOffset, (index - 1) * 0.34):Play()
        else
            StopSceneTexture(particle, true)
            if particle.SetTexture then particle:SetTexture(nil) end
        end
    end

    self.backgroundSceneActive = true
    return true
end

-- ============================= PUBLIC SCENE API =============================
function Skin:RefreshBackgroundScene()
    local frame = WeeklyRewardsFrame
    if not frame or not frame:IsShown() then return false end
    local result = SafeCall("background scene refresh", Skin.ApplyBackgroundScene, Skin, Skin:GetTheme(), false)
    if NS.Layout then NS.Layout:ApplyVisualOverrides(frame, NS.Layout:GetProfile()) end
    return result
end

function Skin:PreviewBackgroundScene()
    local frame = WeeklyRewardsFrame
    if not frame or not frame:IsShown() then return false end
    return SafeCall("background scene preview", Skin.ApplyBackgroundScene, Skin, Skin:GetTheme(), true)
end
