--- ============================================================================
-- File: ArenaCore/modules/Absorbs/Absorbs.lua
-- Purpose: Absorb shield tracking system (isolated module)
-- Extracted from ArenaCore.lua for better maintainability
--- ============================================================================

local AC = _G.ArenaCore or {}
_G.ArenaCore = AC

-- Create Absorbs namespace
AC.Absorbs = AC.Absorbs or {}
local Absorbs = AC.Absorbs

-- Debug flag
Absorbs.DEBUG = false

--- ============================================================================
-- ABSORB FRAME CREATION
-- Called during frame initialization to create absorb UI elements
--- ============================================================================

function Absorbs:CreateAbsorbElements(frame)
    if not frame then return end
    
    -- ========================================================================
    -- ABSORB BAR CREATION (for More Goodies absorb shields)
    -- CRITICAL FIX: Parent to frame (not healthBar) and use MEDIUM strata
    -- ========================================================================
    
    -- Create absorb bar parented to main frame (not health bar)
    frame.totalAbsorb = CreateFrame("StatusBar", nil, frame)
    frame.totalAbsorb:SetFrameStrata("HIGH") -- CRITICAL FIX: HIGH strata for full shield texture visibility
    frame.totalAbsorb:SetFrameLevel(frame:GetFrameLevel() + 15) -- Well above health bar
    frame.totalAbsorb:SetAllPoints(frame.healthBar) -- Position over health bar
    frame.totalAbsorb:SetStatusBarTexture("Interface\\RaidFrame\\Shield-Fill")
    frame.totalAbsorb:GetStatusBarTexture():SetHorizTile(false)
    frame.totalAbsorb:GetStatusBarTexture():SetVertTile(false)
    frame.totalAbsorb:SetStatusBarColor(1, 1, 1, 0.7) -- Standard Blizzard alpha
    frame.totalAbsorb:SetMinMaxValues(0, 1)
    frame.totalAbsorb:SetValue(0)
    frame.totalAbsorb:Hide()
    
    -- CRITICAL FIX: Create separate HIGH STRATA frame for shield overlay texture
    -- This ensures the shield pattern is ALWAYS visible above all other elements
    frame.totalAbsorbOverlayFrame = CreateFrame("Frame", nil, frame)
    frame.totalAbsorbOverlayFrame:SetFrameStrata("HIGH") -- Above MEDIUM (absorb bar) and everything else
    frame.totalAbsorbOverlayFrame:SetFrameLevel(frame:GetFrameLevel() + 50) -- Way above everything
    frame.totalAbsorbOverlayFrame:SetAllPoints(frame.healthBar) -- Position over health bar
    
    -- Create the shield overlay texture on the HIGH strata frame
    frame.totalAbsorbOverlay = frame.totalAbsorbOverlayFrame:CreateTexture(nil, "OVERLAY", nil, 7)
    frame.totalAbsorbOverlay:SetAllPoints(frame.totalAbsorbOverlayFrame)
    frame.totalAbsorbOverlay:SetTexture("Interface\\RaidFrame\\Shield-Overlay", true, true)
    frame.totalAbsorbOverlay:SetAlpha(1.0) -- Full opacity for maximum visibility
    frame.totalAbsorbOverlay:Hide() -- Hidden by default, shown when absorbs exist
    
    -- Over-absorb glow effect - Also on MEDIUM strata
    frame.overAbsorbGlow = frame.totalAbsorb:CreateTexture(nil, "OVERLAY", nil, 6)
    frame.overAbsorbGlow:SetTexture("Interface\\RaidFrame\\Shield-Overshield")
    frame.overAbsorbGlow:SetBlendMode("ADD")
    frame.overAbsorbGlow:SetPoint("BOTTOMLEFT", frame.healthBar, "BOTTOMRIGHT", -7, 0)
    frame.overAbsorbGlow:SetPoint("TOPLEFT", frame.healthBar, "TOPRIGHT", -7, 0)
    frame.overAbsorbGlow:SetWidth(16)
    frame.overAbsorbGlow:Hide()
end

--- ============================================================================
-- ABSORB UPDATE LOGIC
-- Main function to update absorb bars based on unit data
--- ============================================================================

function Absorbs:UpdateAbsorbBar(frame)
    if not frame then
        -- DEBUG REMOVED FOR RELEASE: Frame is nil
        return
    end
    
    -- CRITICAL: Only apply to ArenaCore frames, not nameplates
    if not frame.totalAbsorb or not frame.id then 
        -- DEBUG REMOVED FOR RELEASE: Not an ArenaCore frame
        return 
    end
    
    -- Additional safety: Check if this is actually an arena frame
    local unit = frame.unit
    if not unit or not unit:match("^arena[1-5]$") then
        -- DEBUG REMOVED FOR RELEASE: Not an arena unit
        return
    end
    
    -- DEBUG REMOVED FOR RELEASE: UpdateAbsorbBar called
    
    -- HIDE ABSORBS IN PREP ROOM (user request)
    -- CRITICAL FIX: Proper prep room detection
    -- Prep room = specs exist BUT units don't exist
    -- Live arena = both specs AND units exist
    local _, instanceType = IsInInstance()
    local inPrepRoom = false
    
    if instanceType == "arena" then
        local numOpponents = GetNumArenaOpponentSpecs and GetNumArenaOpponentSpecs()
        if numOpponents and numOpponents > 0 then
            -- Specs exist - now check if any arena units actually exist
            local anyUnitExists = false
            for i = 1, 3 do
                if UnitExists("arena" .. i) then
                    anyUnitExists = true
                    break
                end
            end
            -- Only in prep room if specs exist but NO units exist
            inPrepRoom = not anyUnitExists
        end
        
        -- If in prep room, hide all absorbs
        if inPrepRoom then
            if frame.totalAbsorb then frame.totalAbsorb:Hide() end
            if frame.totalAbsorbOverlay then frame.totalAbsorbOverlay:Hide() end
            if frame.overAbsorbGlow then frame.overAbsorbGlow:Hide() end
            -- Hidden in prep room
            return
        end
    end
    
    local moreGoodiesDB = AC.DB and AC.DB.profile and AC.DB.profile.moreGoodies
    -- CRITICAL FIX: Default to true if setting doesn't exist (absorbs enabled by default)
    local absorbsEnabled = true
    if moreGoodiesDB and moreGoodiesDB.absorbs then
        absorbsEnabled = moreGoodiesDB.absorbs.enabled ~= false
    end
    
    -- DEBUG REMOVED FOR RELEASE: Settings check
    
    local totalAbsorb = 0
    local maxHealth = 100 -- Default for test/sim mode
    -- Treat frames with non-existent units as simulation (test) mode so preview works anywhere
    -- BUT: Don't treat prep room as test mode (prep room was already handled above)
    local unitExists = unit and UnitExists(unit)
    -- CRITICAL FIX: NEVER use test mode in arena instances (prep room or live arena)
    local isTestMode = (AC.testModeEnabled == true) and (not unitExists) and (instanceType ~= "arena")
    
    -- If explicitly disabled in settings, always hide (both test and live)
    if absorbsEnabled == false then
        -- DEBUG REMOVED FOR RELEASE: Absorbs disabled in settings
        if frame.totalAbsorb then frame.totalAbsorb:Hide() end
        if frame.totalAbsorbOverlay then frame.totalAbsorbOverlay:Hide() end
        if frame.overAbsorbGlow then frame.overAbsorbGlow:Hide() end
        return
    end
    
    if isTestMode then
        -- Test/sim mode: Show different absorb effects for each frame
        local unitSafe = tostring(unit or "arena1")
        local arenaIndex = tonumber(unitSafe:match("arena(%d)")) or 1
        
        if arenaIndex == 1 then
            -- Arena 1 (Death Knight): No absorb
            totalAbsorb = 0
        elseif arenaIndex == 2 then
            -- Arena 2 (Mage): Green magic absorb (50% of health)
            totalAbsorb = 50
            maxHealth = 100
        elseif arenaIndex == 3 then
            -- Arena 3 (Hunter): White physical over-absorb (150% of health)
            totalAbsorb = 150
            maxHealth = 100
        end
    else
        -- Live mode: Use actual unit data
        if not unit or not UnitExists(unit) then
            -- DEBUG REMOVED FOR RELEASE: Unit doesn't exist
            -- CRITICAL FIX: Hide absorb elements when unit doesn't exist
            if frame.totalAbsorb then frame.totalAbsorb:Hide() end
            if frame.totalAbsorbOverlay then frame.totalAbsorbOverlay:Hide() end
            if frame.overAbsorbGlow then frame.overAbsorbGlow:Hide() end
            return
        end
        totalAbsorb = UnitGetTotalAbsorbs(unit) or 0
        maxHealth = UnitHealthMax(unit) or 1
        
        -- DEBUG REMOVED FOR RELEASE: Absorb values
    end
    
    if totalAbsorb > 0 then
        -- DEBUG REMOVED FOR RELEASE: Showing absorb amount
        
        -- Showing absorb
        -- Calculate absorb percentage relative to max health
        local absorbPercent = math.min(totalAbsorb / maxHealth, 1)
        
        -- Set up the absorb bar
        frame.totalAbsorb:SetMinMaxValues(0, maxHealth)
        frame.totalAbsorb:SetValue(totalAbsorb)
        
        -- Ensure the absorb bar has proper size and is positioned correctly
        local healthBar = frame.healthBar
        if healthBar then
            frame.totalAbsorb:ClearAllPoints()
            frame.totalAbsorb:SetAllPoints(healthBar)
            -- CRITICAL FIX: Maintain HIGH strata and high frame level for shield texture visibility
            frame.totalAbsorb:SetFrameStrata("HIGH")
            frame.totalAbsorb:SetFrameLevel(frame:GetFrameLevel() + 15)
            -- Re-apply texture to be safe after toggles
            frame.totalAbsorb:SetStatusBarTexture("Interface\\RaidFrame\\Shield-Fill")
            local tex = frame.totalAbsorb:GetStatusBarTexture()
            if tex then
                tex:SetHorizTile(false)
                tex:SetVertTile(false)
            end
        end
        
        -- Determine absorb color based on type (magic vs physical)
        local r, g, b = 1, 1, 1 -- Default to white (physical)
        
        if isTestMode then
            -- Test mode: Set specific colors for demonstration
            local arenaIndex = tonumber(unit:match("arena(%d)")) or 1
            if arenaIndex == 2 then
                -- Arena 2 (Mage): Tuned green magic absorb
                r, g, b = 0.35, 0.95, 0.35
            elseif arenaIndex == 3 then
                -- Arena 3 (Hunter): White physical absorb
                r, g, b = 1, 1, 1
            end
        else
            -- Live mode: Comprehensive absorb spell detection (TWW 11.2.x)
            local magicAbsorbSpells = {
                -- Death Knight (Magic-only) - Makes absorb bar GREEN
                [48707] = true,    -- Anti-Magic Shell
            }
            
            local physicalAbsorbSpells = {
                -- Death Knight (Physical-only)
                [77535] = true,    -- Blood Shield (Mastery)
            }
            
            local allDamageAbsorbSpells = {
                -- Priest - Power Word: Shield
                [17] = true,       -- Power Word: Shield
                
                -- Monk (Mistweaver) - Life Cocoon
                [116849] = true,   -- Life Cocoon
                
                -- Paladin (Retribution) - Shield of Vengeance
                [184662] = true,   -- Shield of Vengeance
                
                -- Mage (Frost) - Ice Barrier
                [11426] = true,    -- Ice Barrier
                
                -- Mage (Fire) - Blazing Barrier
                [235313] = true,   -- Blazing Barrier
                
                -- Mage (Arcane) - Prismatic Barrier
                [235450] = true,   -- Prismatic Barrier
                
                -- Warlock - Dark Pact
                [108416] = true,   -- Dark Pact
                
                -- Warlock - Soul Leech
                [108366] = true,   -- Soul Leech (CORRECTED from 108370)
                
                -- Warrior (Protection) - Ignore Pain
                [190456] = true,   -- Ignore Pain
                
                -- Shaman (Restoration) - Earthen Wall Totem (absorb effect)
                [201633] = true,   -- Earthen Wall (absorb effect from Earthen Wall Totem 198838)
                
                -- Demon Hunter (Vengeance) - Soul Barrier
                [263648] = true,   -- Soul Barrier
            }
            
            -- Check if unit has any magic absorb buffs (simplified detection)
            for i = 1, 40 do
                local auraData = C_UnitAuras.GetBuffDataByIndex(unit, i)
                if not auraData then break end
                if auraData.spellId and magicAbsorbSpells[auraData.spellId] then
                    r, g, b = 0.35, 0.95, 0.35 -- Tuned green for magic absorbs
                    break
                end
            end
        end
        
        frame.totalAbsorb:SetStatusBarColor(r, g, b, 0.7)
        -- CRITICAL FIX: Show absorb bar (safe in combat - these are custom frames, not secure)
        frame.totalAbsorb:Show()
        
        -- Ensure overlay is visible when absorbs are shown
        if frame.totalAbsorbOverlay and frame.totalAbsorbOverlayFrame then
            -- CRITICAL FIX: Match overlay size to actual absorb bar width (not full health bar)
            -- This ensures shield texture lines only show over the actual shield, not empty space
            local healthBar = frame.healthBar
            if healthBar then
                local healthBarWidth = healthBar:GetWidth() or 235
                local absorbWidth = healthBarWidth * absorbPercent -- Use calculated absorb percentage
                
                -- Position overlay frame to match absorb bar size
                frame.totalAbsorbOverlayFrame:ClearAllPoints()
                frame.totalAbsorbOverlayFrame:SetPoint("TOPLEFT", healthBar, "TOPLEFT", 0, 0)
                frame.totalAbsorbOverlayFrame:SetPoint("BOTTOMLEFT", healthBar, "BOTTOMLEFT", 0, 0)
                frame.totalAbsorbOverlayFrame:SetWidth(absorbWidth) -- CRITICAL: Match absorb width
                frame.totalAbsorbOverlayFrame:SetFrameStrata("HIGH")
                frame.totalAbsorbOverlayFrame:SetFrameLevel(frame:GetFrameLevel() + 50)
                
                -- Show the overlay texture with proper tiling
                frame.totalAbsorbOverlay:ClearAllPoints()
                frame.totalAbsorbOverlay:SetAllPoints(frame.totalAbsorbOverlayFrame)
                frame.totalAbsorbOverlay:SetTexture("Interface\\RaidFrame\\Shield-Overlay", true, true)
                frame.totalAbsorbOverlay:SetAlpha(1.0) -- Full opacity
                frame.totalAbsorbOverlay:Show()
                
                -- DEBUG REMOVED FOR RELEASE: Overlay showing confirmation
            end
        else
            -- DEBUG REMOVED FOR RELEASE: Missing overlay elements warning
        end
        
        -- Show over-absorb glow if absorb exceeds health
        if totalAbsorb > maxHealth then
            frame.overAbsorbGlow:Show()
        else
            frame.overAbsorbGlow:Hide()
        end
    else
        -- No absorb
        frame.totalAbsorb:Hide()
        if frame.totalAbsorbOverlay then frame.totalAbsorbOverlay:Hide() end
        frame.overAbsorbGlow:Hide()
    end
end

--- ============================================================================
-- HELPER FUNCTIONS
--- ============================================================================

-- Hide absorbs (used in prep room, etc.)
function Absorbs:HideAbsorbs(frame)
    if not frame then return end
    if frame.totalAbsorb then frame.totalAbsorb:Hide() end
    if frame.totalAbsorbOverlay then frame.totalAbsorbOverlay:Hide() end
    if frame.overAbsorbGlow then frame.overAbsorbGlow:Hide() end
end

-- Refresh all absorbs (called when settings change)
function Absorbs:RefreshAll()
    local frames = nil
    if AC.FrameManager and AC.FrameManager.GetFrames then
        frames = AC.FrameManager:GetFrames()
    end
    
    if frames then
        for i = 1, #frames do
            local f = frames[i]
            if f then 
                pcall(function() self:UpdateAbsorbBar(f) end)
            end
        end
    end
end

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

function Absorbs:Initialize()
    if self.initialized then return end
    
    -- Module initialized
    self.initialized = true
    
    -- DEBUG REMOVED FOR RELEASE: Module initialized
end

-- Auto-initialize
C_Timer.After(1, function()
    Absorbs:Initialize()
end)

-- Expose for backward compatibility
_G.UpdateAbsorbBar = function(frame)
    Absorbs:UpdateAbsorbBar(frame)
end
