-- ============================================================================
-- BLACKOUT ENGINE - BETTERBLIZZPLATES PATTERN (COMPLETE REWRITE)
-- ============================================================================
-- TAINT-FREE IMPLEMENTATION:
-- - Uses hooksecurefunc instead of function replacement
-- - Adds IsForbidden/IsProtected checks everywhere
-- - NEVER hides/shows background (prevents white background bug)
-- - Only touches health bar color
-- - Modular design for ArenaCore
-- ============================================================================

-- CRITICAL FIX: Don't check AC at load time - it may not exist yet
-- Instead, get AC reference when functions are called
local function GetAC()
    return _G.ArenaCore
end

-- ============================================================================
-- BLACKOUT SPELL LOOKUP
-- ============================================================================

local blackoutSpells = {}

local function RebuildBlackoutSpells()
    wipe(blackoutSpells)
    
    local AC = GetAC()
    if not AC then return end
    
    local db = AC.DB and AC.DB.profile and AC.DB.profile.blackout
    if not db or not db.spells then
        if AC.BLACKOUT_DEBUG then
            print("|cffFF0000[Blackout]|r Database not ready - spell list empty")
        end
        return
    end
    
    local count = 0
    for _, spellID in ipairs(db.spells) do
        blackoutSpells[spellID] = true
        count = count + 1
    end
    
    if AC.BLACKOUT_DEBUG then
        print("|cff00FF00[Blackout]|r Loaded", count, "blackout spells")
    end
end

-- ============================================================================
-- BLACKOUT TRACKING TABLE (Combat Log Based)
-- ============================================================================
-- Track active blackout spells by unit GUID (since we can't see enemy buffs)
local activeBlackouts = {} -- [unitGUID] = {spellID = X, expiresAt = time}

-- ============================================================================
-- CHECK IF UNIT HAS BLACKOUT (Combat Log Based)
-- ============================================================================

local function HasBlackoutAura(unit)
    if not unit or not UnitExists(unit) then return false end
    
    -- CRITICAL: ONLY work on ENEMY PLAYERS (not NPCs, not friendlies, not pets)
    if not UnitIsPlayer(unit) then return false end  -- Must be a player
    if not UnitIsEnemy("player", unit) then return false end  -- Must be hostile to you
    if UnitIsUnit(unit, "player") then return false end  -- Never yourself
    
    local unitGUID = UnitGUID(unit)
    if not unitGUID then return false end
    
    -- Additional GUID check: Player GUIDs start with "Player-"
    if not unitGUID:match("^Player%-") then return false end
    
    -- Check if unit has active blackout in our tracking table
    local blackoutData = activeBlackouts[unitGUID]
    if blackoutData and blackoutData.expiresAt > GetTime() then
        return true, blackoutData.spellID
    end
    
    -- Cleanup expired entry
    if blackoutData then
        activeBlackouts[unitGUID] = nil
    end
    
    return false, nil
end

-- ============================================================================
-- FRAME CONFIG INITIALIZATION (BetterBlizzPlates Pattern)
-- ============================================================================

local function InitializeFrameConfig(frame)
    if not frame.ArenaCore then
        frame.ArenaCore = {}
    end
    if not frame.ArenaCore.config then
        frame.ArenaCore.config = {}
    end
    return frame.ArenaCore.config
end

-- ============================================================================
-- BLACKOUT COLOR SCANNER
-- ============================================================================
-- Scans for blackout auras and stores the result in frame config

local function ScanBlackoutAura(frame)
    if not frame or not frame.unit then return end
    if frame:IsForbidden() or frame:IsProtected() then return end -- TAINT PREVENTION
    
    -- CRITICAL: ONLY work on ENEMY PLAYERS (not NPCs, not friendlies, not pets)
    if not UnitIsPlayer(frame.unit) then return end  -- Must be a player
    if not UnitIsEnemy("player", frame.unit) then return end  -- Must be hostile
    if UnitIsUnit(frame.unit, "player") then return end  -- Never yourself
    
    local AC = GetAC()
    if not AC then return end
    
    local db = AC.DB and AC.DB.profile and AC.DB.profile.blackout
    if not db or db.enabled == false then
        -- Clear any existing blackout state
        local config = frame.ArenaCore and frame.ArenaCore.config
        if config then
            config.blackoutColor = nil
        end
        return
    end
    
    -- Initialize config if needed
    local config = InitializeFrameConfig(frame)
    
    -- Check for blackout aura
    local hasBlackout, spellID = HasBlackoutAura(frame.unit)
    
    if hasBlackout then
        -- Store blackout color in config (BetterBlizzPlates pattern)
        config.blackoutColor = {r = 0, g = 0, b = 0}
        config.blackoutSpellID = spellID
        
        if AC.BLACKOUT_DEBUG then
            print("|cff00FFFF[Blackout]|r Stored blackout color for", frame.unit)
        end
    else
        -- Clear blackout color
        config.blackoutColor = nil
        config.blackoutSpellID = nil
    end
end

-- ============================================================================
-- HEALTH COLOR UPDATE HOOK (BetterBlizzPlates Pattern)
-- ============================================================================
-- CRITICAL: Uses hooksecurefunc to avoid taint
-- Runs AFTER Blizzard's function, only overrides color if blackout detected

hooksecurefunc("CompactUnitFrame_UpdateHealthColor", function(frame)
    if not frame or not frame.unit then return end
    if frame:IsForbidden() or frame:IsProtected() then return end -- TAINT PREVENTION
    
    -- Only handle nameplates
    if not frame.unit:find("nameplate") then return end
    
    -- CRITICAL: ONLY work on ENEMY PLAYERS (not NPCs, not friendlies, not pets)
    if not UnitIsPlayer(frame.unit) then return end  -- Must be a player
    if not UnitIsEnemy("player", frame.unit) then return end  -- Must be hostile
    if UnitIsUnit(frame.unit, "player") then return end  -- Never yourself
    
    local AC = GetAC()
    if not AC then return end
    
    local db = AC.DB and AC.DB.profile and AC.DB.profile.blackout
    if not db or db.enabled == false then return end
    
    -- Check if frame has blackout color stored in config
    local config = frame.ArenaCore and frame.ArenaCore.config
    if config and config.blackoutColor then
        local healthBar = frame.healthBar
        if healthBar and not healthBar:IsForbidden() and not healthBar:IsProtected() then
            -- Apply blackout color (BLACK) - ONLY touch health bar color
            -- NEVER touch background - this prevents white background bug
            healthBar:SetStatusBarColor(
                config.blackoutColor.r,
                config.blackoutColor.g,
                config.blackoutColor.b
            )
            
            if AC.BLACKOUT_DEBUG then
                print("|cff00FFFF[Blackout]|r Applied black color to", frame.unit)
            end
        end
    end
end)

-- ============================================================================
-- COMBAT_LOG_EVENT_UNFILTERED HANDLER
-- ============================================================================
-- Detect when blackout spells are cast/applied/removed

local combatLogFrame = CreateFrame("Frame")
combatLogFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
combatLogFrame:RegisterEvent("GROUP_ROSTER_UPDATE") -- Solo Shuffle cleanup

combatLogFrame:SetScript("OnEvent", function(self, event)
    local AC = GetAC()
    if not AC then return end
    
    if event == "GROUP_ROSTER_UPDATE" then
        -- Solo Shuffle round transition - clean up blackout states
        local _, instanceType = IsInInstance()
        if instanceType == "arena" then
            -- Clear all blackout tracking
            wipe(activeBlackouts)
            
            -- Trigger health color update for all nameplates to restore colors
            C_Timer.After(0.3, function()
                for _, nameplate in ipairs(C_NamePlate.GetNamePlates()) do
                    local frame = nameplate.UnitFrame
                    if frame and frame.unit and not frame:IsForbidden() and not frame:IsProtected() then
                        ScanBlackoutAura(frame)
                        CompactUnitFrame_UpdateHealthColor(frame)
                    end
                end
            end)
            
            if AC.BLACKOUT_DEBUG then
                print("|cff00FFFF[Blackout]|r Solo Shuffle cleanup complete")
            end
        end
        return
    end
    
    -- COMBAT_LOG_EVENT_UNFILTERED handling
    local _, subEvent, _, sourceGUID, _, _, _, destGUID, _, _, _, spellID = CombatLogGetCurrentEventInfo()
    
    if not spellID or not blackoutSpells[spellID] then return end
    
    local db = AC.DB and AC.DB.profile and AC.DB.profile.blackout
    if not db or db.enabled == false then return end
    
    -- SPELL_AURA_APPLIED: Blackout spell applied
    if subEvent == "SPELL_AURA_APPLIED" or subEvent == "SPELL_AURA_REFRESH" then
        -- CRITICAL: ONLY track if destination is an ENEMY PLAYER
        -- GUID format check: Player GUIDs start with "Player-"
        if not destGUID or not destGUID:match("^Player%-") then return end
        
        -- Additional check: Ensure it's not a friendly player (arena teammates, etc.)
        -- We can't directly check UnitIsEnemy from GUID, but Player- prefix ensures it's a player
        -- The nameplate filtering will handle the enemy check
        
        -- Track the blackout with conservative 20-second duration
        activeBlackouts[destGUID] = {
            spellID = spellID,
            expiresAt = GetTime() + 20
        }
        
        if AC.BLACKOUT_DEBUG then
            local spellName = C_Spell.GetSpellName(spellID)
            print("|cff00FFFF[Blackout]|r Applied:", spellName, "(", spellID, ")")
        end
        
        -- Trigger health color update for all nameplates
        C_Timer.After(0.05, function()
            for _, namePlateFrameBase in pairs(C_NamePlate.GetNamePlates()) do
                local frame = namePlateFrameBase.UnitFrame
                if frame and frame.unit and not frame:IsForbidden() and not frame:IsProtected() then
                    local guid = UnitGUID(frame.unit)
                    if guid == destGUID then
                        ScanBlackoutAura(frame)
                        CompactUnitFrame_UpdateHealthColor(frame)
                    end
                end
            end
        end)
        
    -- SPELL_AURA_REMOVED: Blackout spell removed
    elseif subEvent == "SPELL_AURA_REMOVED" then
        activeBlackouts[destGUID] = nil
        
        if AC.BLACKOUT_DEBUG then
            local spellName = C_Spell.GetSpellName(spellID)
            print("|cff00FFFF[Blackout]|r Removed:", spellName, "(", spellID, ")")
        end
        
        -- Trigger health color update for all nameplates
        C_Timer.After(0.05, function()
            for _, namePlateFrameBase in pairs(C_NamePlate.GetNamePlates()) do
                local frame = namePlateFrameBase.UnitFrame
                if frame and frame.unit and not frame:IsForbidden() and not frame:IsProtected() then
                    local guid = UnitGUID(frame.unit)
                    if guid == destGUID then
                        ScanBlackoutAura(frame)
                        CompactUnitFrame_UpdateHealthColor(frame)
                    end
                end
            end
        end)
    end
end)

-- ============================================================================
-- NAME_PLATE_UNIT_ADDED HANDLER
-- ============================================================================
-- Scan new nameplates immediately when they appear

local nameplateFrame = CreateFrame("Frame")
nameplateFrame:RegisterEvent("NAME_PLATE_UNIT_ADDED")

nameplateFrame:SetScript("OnEvent", function(self, event, unit)
    local AC = GetAC()
    if not AC then return end
    
    local db = AC.DB and AC.DB.profile and AC.DB.profile.blackout
    if not db or db.enabled == false then return end
    
    local nameplate = C_NamePlate.GetNamePlateForUnit(unit)
    if nameplate and nameplate.UnitFrame then
        local frame = nameplate.UnitFrame
        if not frame:IsForbidden() and not frame:IsProtected() then
            -- Scan for blackout aura immediately
            ScanBlackoutAura(frame)
            
            -- Trigger health color update
            if frame.healthBar then
                CompactUnitFrame_UpdateHealthColor(frame)
            end
        end
    end
end)

-- ============================================================================
-- UNIT_AURA HANDLER (For friendly/neutral units we can scan)
-- ============================================================================

local auraFrame = CreateFrame("Frame")
auraFrame:RegisterEvent("UNIT_AURA")

auraFrame:SetScript("OnEvent", function(self, event, unit)
    -- Only handle nameplates
    if not unit or not unit:find("nameplate") then return end
    
    local AC = GetAC()
    if not AC then return end
    
    local db = AC.DB and AC.DB.profile and AC.DB.profile.blackout
    if not db or db.enabled == false then return end
    
    local nameplate = C_NamePlate.GetNamePlateForUnit(unit)
    if nameplate and nameplate.UnitFrame then
        local frame = nameplate.UnitFrame
        if not frame:IsForbidden() and not frame:IsProtected() then
            ScanBlackoutAura(frame)
            
            if frame.healthBar then
                CompactUnitFrame_UpdateHealthColor(frame)
            end
        end
    end
end)

-- ============================================================================
-- PUBLIC API
-- ============================================================================

-- Public API function - needs to be added to AC when it exists
local function RefreshBlackout()
    RebuildBlackoutSpells()
    
    -- Rescan all visible nameplates
    local nameplates = C_NamePlate.GetNamePlates()
    for _, nameplate in ipairs(nameplates) do
        if nameplate.UnitFrame and nameplate.UnitFrame.unit then
            local frame = nameplate.UnitFrame
            if not frame:IsForbidden() and not frame:IsProtected() then
                ScanBlackoutAura(frame)
                if frame.healthBar then
                    CompactUnitFrame_UpdateHealthColor(frame)
                end
            end
        end
    end
end

-- Register the public API when AC is ready
C_Timer.After(0.1, function()
    local AC = GetAC()
    if AC then
        AC.RefreshBlackout = RefreshBlackout
    end
end)

-- ============================================================================
-- RELOAD SAFETY NET
-- ============================================================================

local reloadFrame = CreateFrame("Frame")
reloadFrame:RegisterEvent("PLAYER_ENTERING_WORLD")

reloadFrame:SetScript("OnEvent", function(self, event)
    C_Timer.After(0.5, function()
        -- Rebuild spell list
        RebuildBlackoutSpells()
        
        local AC = GetAC()
        if not AC then return end
        
        local db = AC.DB and AC.DB.profile and AC.DB.profile.blackout
        if not db or db.enabled == false then return end
        
        -- Scan all visible nameplates
        local nameplates = C_NamePlate.GetNamePlates()
        for _, nameplate in ipairs(nameplates) do
            if nameplate.UnitFrame and nameplate.UnitFrame.unit then
                local frame = nameplate.UnitFrame
                if not frame:IsForbidden() and not frame:IsProtected() then
                    ScanBlackoutAura(frame)
                    if frame.healthBar then
                        CompactUnitFrame_UpdateHealthColor(frame)
                    end
                end
            end
        end
        
        if AC.BLACKOUT_DEBUG then
            print("|cff00FFFF[Blackout]|r System initialized")
        end
    end)
end)

-- ============================================================================
-- DEBUG COMMAND
-- ============================================================================

local function TestBlackout()
    print("|cff00FFFF[Blackout Debug]|r ==================")
    
    local AC = GetAC()
    if not AC then
        print("|cffFF0000[Blackout]|r ArenaCore not loaded yet!")
        return
    end
    
    -- Check if enabled
    local db = AC.DB and AC.DB.profile and AC.DB.profile.blackout
    if not db then
        print("|cffFF0000[Blackout]|r Database not found!")
        return
    end
    
    print("|cff00FF00[Blackout]|r Enabled:", tostring(db.enabled))
    
    -- Count spells
    local count = 0
    for _ in pairs(blackoutSpells) do count = count + 1 end
    print("|cff00FF00[Blackout]|r Spells loaded:", count)
    
    -- Check target
    if UnitExists("target") then
        print("|cff00FF00[Blackout]|r Target:", UnitName("target"))
        
        -- Check blackout detection
        local hasBlackout, spellID = HasBlackoutAura("target")
        print("|cff00FF00[Blackout]|r Has blackout aura:", tostring(hasBlackout))
        if spellID then
            local spellName = C_Spell.GetSpellName(spellID)
            print("|cff00FF00[Blackout]|r Detected spell:", spellName, "(", spellID, ")")
        end
        
        -- Check active blackouts
        print("|cffFFAA00[Blackout]|r Active blackouts:")
        local activeCount = 0
        for guid, data in pairs(activeBlackouts) do
            activeCount = activeCount + 1
            local spellName = C_Spell.GetSpellName(data.spellID)
            local timeLeft = data.expiresAt - GetTime()
            print("  ", guid, ":", spellName, "(", data.spellID, ") -", string.format("%.1f", timeLeft), "sec left")
        end
        if activeCount == 0 then
            print("  |cffFFAA00No active blackouts|r")
        end
    else
        print("|cffFFAA00[Blackout]|r No target selected")
    end
    
    print("|cff00FFFF[Blackout Debug]|r ==================")
end

-- Register dedicated slash command
SLASH_BLACKOUTTEST1 = "/testblackout"
SLASH_BLACKOUTTEST2 = "/blackouttest"
SlashCmdList["BLACKOUTTEST"] = TestBlackout

-- ============================================================================
-- INITIALIZATION
-- ============================================================================

C_Timer.After(1, function()
    RebuildBlackoutSpells()
    
    local AC = GetAC()
    if not AC then return end
    
    -- Silent initialization - debug with /testblackout if needed
    if AC.BLACKOUT_DEBUG then
        local db = AC.DB and AC.DB.profile and AC.DB.profile.blackout
        local count = 0
        for _ in pairs(blackoutSpells) do count = count + 1 end
        
        print("|cff00FFFF[Blackout]|r System initialized (BetterBlizzPlates pattern)")
        print("|cff00FFFF[Blackout]|r Enabled:", tostring(db and db.enabled))
        print("|cff00FFFF[Blackout]|r Spells loaded:", count)
        print("|cff00FFFF[Blackout]|r Use /testblackout to debug")
    end
end)
