-- ExtraResourcePlate v1.0 Release Version
-- Author: Majo0o - HeftiKuss Guild Blackmoore - Made with AI
-- Für WoW 12.0

local addonName, ns = ...

-- =========================================================================
-- 1. LOKALISIERUNG & KONSTANTEN
-- =========================================================================

local L = {
    TAB_GENERAL = "General",
    TAB_DESIGN = "Design",
    TAB_ALERTS = "Alerts", 
    TAB_COLORS = "Colors",
    TAB_PROFILE = "Profile",
    
    SECTION_ANIMATIONS = "Visual Animations",
    SECTION_SOUNDS = "Sound Alerts",
    SECTION_PROFILE = "Profile Settings",
    SECTION_MANAGE_PROFILES = "Manage Profiles",
    
    ENABLED = "Enable Addon",
    CONTAINER_BORDER = "Show Container Background",
    POSITION = "Position",
    POS_TOP = "Top",
    POS_BOTTOM = "Bottom",
    POS_HINT = "(Above/Below Nameplate)",
    SIZE = "Size",
    WIDTH = "Width",
    HEIGHT = "Height",
    SPACING = "Spacing",
    OFFSET_Y = "Vertical Offset", 
    OFFSET_X = "Horizontal Offset",
    BG_OPACITY = "Background Opacity",
    BG_STYLE = "Background Style",
    MENU_SCALE = "Menu Zoom",
    
    SHAPE = "Icon Shape",
    BORDER = "Show Border (Pixel Perfect)",
    STYLE_CIRCLE = "Circle",
    STYLE_SQUARE = "Square",
    STYLE_SOFT = "Soft",
    STYLE_BARS = "Bars",
    STYLE_SWORDS = "Swords",
    STYLE_SKULLS = "Skulls",
    STYLE_DIAMONDS = "Gemstones",
    STYLE_SHIELD = "Shield",
    STYLE_RUNE_BLOOD = "Rune (Blood)",
    STYLE_RUNE_FROST = "Rune (Frost)",
    STYLE_RUNE_UNHOLY = "Rune (Unholy)",
    STYLE_FIST = "Fist",
    STYLE_LIGHTNING = "Lightning",

    ANIM_TRIGGER_1 = "Stage 1 (Builder) - Starts at:",
    ANIM_TRIGGER_2 = "Stage 2 (Full Resource)",
    ANIM_SLOT_1 = "Effect A:",
    ANIM_SLOT_2 = "Effect B:",
    ANIM_DISCLAIMER = "Note: Some Animations may not work in all combination of Designs and Colors.",
    
    ANIM_NONE = "None",
    ANIM_PULSE = "Pulse",
    ANIM_FLASH = "Flash",
    ANIM_SHAKE = "Shake",
    ANIM_ROTATE = "Rotate",
    ANIM_GLOW = "Glow",
    
    SOUND_NONE = "None",
    SOUND_1 = "Sound 1",
    SOUND_2 = "Sound 2",
    SOUND_3 = "Sound 3",
    SOUND_4 = "Sound 4",
    SOUND_5 = "Sound 5",
    SOUND_6 = "Sound 6",
    SOUND_7 = "Sound 7",
    SOUND_8 = "Sound 8",
    SOUND_9 = "Sound 9",
    SOUND_10 = "Sound 10",
    
    COLOR_MODE = "Color Mode",
    COLOR_CLASS = "Use Class Color",
    COLOR_CUSTOM = "Use Custom Color",
    COLOR_PICK = "Pick Color",
    
    PREVIEW = "Live Preview (Simulation)",
    FOOTER = "Majo0o - HeftiKuss Guild Blackmoore - Made with AI",
    LOADED_MSG = "ExtraResourcePlate v1.0 loaded. Type /erp for options.",
    MINIMAP_TOOLTIP = "ExtraResourcePlate\nLeft Click: Open Settings",
    
    EXPORT_DESC = "Share Profile (String):",
    IMPORT_DESC = "Import Profile (String):",
    BTN_EXPORT = "Export to Clipboard",
    BTN_IMPORT = "Import String",
    IMPORT_SUCCESS = "Profile imported successfully!",
    IMPORT_FAIL = "Invalid profile string!",
    
    SAVE_PROFILE = "Save Current Profile",
    LOAD_PROFILE = "Load Profile",
    DELETE_PROFILE = "Delete",
    PROFILE_NAME_HINT = "Enter Profile Name...",
    PROFILE_SAVED = "Profile saved: ",
    PROFILE_LOADED = "Profile loaded: ",
    PROFILE_DELETED = "Profile deleted: ",
    NO_PROFILE_NAME = "Please enter a profile name.",
}

if GetLocale() == "deDE" then
    L.TAB_GENERAL = "Allgemein"
    L.TAB_DESIGN = "Design"
    L.TAB_ALERTS = "Alerts" 
    L.TAB_COLORS = "Farben"
    L.TAB_PROFILE = "Profil"
    
    L.SECTION_ANIMATIONS = "Visuelle Animationen"
    L.SECTION_SOUNDS = "Sound Alerts"
    L.SECTION_PROFILE = "Profil Import/Export"
    L.SECTION_MANAGE_PROFILES = "Profile Verwalten"
    
    L.ENABLED = "Addon aktivieren"
    L.CONTAINER_BORDER = "Hintergrund/Rahmen anzeigen"
    L.POSITION = "Position"
    L.POS_TOP = "Oben"
    L.POS_BOTTOM = "Unten"
    L.POS_HINT = "(Über/Unter Nameplate)"
    L.SIZE = "Größe"
    L.WIDTH = "Breite"
    L.HEIGHT = "Höhe"
    L.SPACING = "Abstand"
    L.OFFSET_Y = "Vertikaler Versatz"
    L.OFFSET_X = "Horizontaler Versatz"
    L.BG_OPACITY = "Hintergrund Deckkraft"
    L.BG_STYLE = "Hintergrund Stil"
    L.MENU_SCALE = "Menü Zoom"
    
    L.SHAPE = "Form / Icon"
    L.BORDER = "Rand anzeigen (Pixel Perfect)"
    L.STYLE_CIRCLE = "Kreis"
    L.STYLE_SQUARE = "Quadrat"
    L.STYLE_SOFT = "Weich"
    L.STYLE_BARS = "Balken"
    L.STYLE_SWORDS = "Schwerter"
    L.STYLE_SKULLS = "Totenköpfe"
    L.STYLE_DIAMONDS = "Edelsteine"
    L.STYLE_SHIELD = "Schild"
    L.STYLE_RUNE_BLOOD = "Rune (Blut)"
    L.STYLE_RUNE_FROST = "Rune (Frost)"
    L.STYLE_RUNE_UNHOLY = "Rune (Unheilig)"
    L.STYLE_FIST = "Faust"
    L.STYLE_LIGHTNING = "Blitz"

    L.ANIM_TRIGGER_1 = "Stufe 1 (Aufbau) - Start ab:"
    L.ANIM_TRIGGER_2 = "Stufe 2 (Voll aufgeladen)"
    L.ANIM_SLOT_1 = "Effekt A:"
    L.ANIM_SLOT_2 = "Effekt B:"
    L.ANIM_DISCLAIMER = "Hinweis: Manche Animationen funktionieren nicht perfekt mit jeder Kombination aus Design und Farbe."
    
    L.ANIM_NONE = "Keine"
    L.ANIM_PULSE = "Pulsieren"
    L.ANIM_FLASH = "Blinken"
    L.ANIM_SHAKE = "Wackeln"
    L.ANIM_ROTATE = "Drehen"
    L.ANIM_GLOW = "Glühen (Glow)"
    
    L.SOUND_NONE = "Keiner"
    L.SOUND_1 = "Sound 1"
    L.SOUND_2 = "Sound 2"
    L.SOUND_3 = "Sound 3"
    L.SOUND_4 = "Sound 4"
    L.SOUND_5 = "Sound 5"
    L.SOUND_6 = "Sound 6"
    L.SOUND_7 = "Sound 7"
    L.SOUND_8 = "Sound 8"
    L.SOUND_9 = "Sound 9"
    L.SOUND_10 = "Sound 10"
    
    L.COLOR_MODE = "Farbmodus"
    L.COLOR_CLASS = "Klassenfarbe nutzen"
    L.COLOR_CUSTOM = "Eigene Farbe nutzen"
    L.COLOR_PICK = "Farbe wählen"
    
    L.PREVIEW = "Live Vorschau (Simulation)"
    L.LOADED_MSG = "ExtraResourcePlate v1.0 geladen. Tippe /erp für Optionen."
    L.MINIMAP_TOOLTIP = "ExtraResourcePlate\nLinksklick: Einstellungen öffnen"
    
    L.EXPORT_DESC = "Profil Teilen (String):"
    L.IMPORT_DESC = "Profil Importieren (String):"
    L.BTN_EXPORT = "Exportieren"
    L.BTN_IMPORT = "Importieren"
    L.IMPORT_SUCCESS = "Profil erfolgreich importiert!"
    L.IMPORT_FAIL = "Ungültiger Profil-Code!"
    
    L.SAVE_PROFILE = "Profil Speichern"
    L.LOAD_PROFILE = "Profil Laden"
    L.DELETE_PROFILE = "Löschen"
    L.PROFILE_NAME_HINT = "Profilname eingeben..."
    L.PROFILE_SAVED = "Profil gespeichert: "
    L.PROFILE_LOADED = "Profil geladen: "
    L.PROFILE_DELETED = "Profil gelöscht: "
    L.NO_PROFILE_NAME = "Bitte einen Profilnamen eingeben."
end

-- =========================================================================
-- 2. DATENSTRUKTUREN
-- =========================================================================

local defaults = {
    enabled = true,
    showContainerBorder = true,
    position = "TOP",
    yOffset = 20,
    xOffset = 0, 
    width = 14,
    height = 14,
    spacing = 4,
    scale = 1.0,
    
    bgAlpha = 0.5,
    bgStyle = 1, 
    
    design = 1,
    showBorder = false,
    
    -- Animation Config
    anim1_trigger = 3,
    anim1_type_a = 1, 
    anim1_type_b = 1, 
    
    anim2_type_a = 2, 
    anim2_type_b = 1, 
    
    -- Sound Config
    sound1_id = 1, -- None
    sound2_id = 1, -- None
    
    useClassColor = true,
    customColor = {r=1, g=0.8, b=0, a=1},
    
    minimapPos = 45,
    menuScale = 1.0, 
    
    -- Saved Profiles Container
    savedProfiles = {}
}

local STYLES = {
    { id = 1, name = "STYLE_CIRCLE",   tex = "Interface\\Common\\Indicator-Yellow",      bar=false },
    { id = 2, name = "STYLE_SQUARE",   tex = "Interface\\Buttons\\WHITE8X8",             bar=false },
    { id = 3, name = "STYLE_SOFT",     tex = "Interface\\Common\\Indicator-Gray",        bar=false },
    { id = 4, name = "STYLE_BARS",     tex = "Interface\\Buttons\\WHITE8X8",             bar=true }, 
    { id = 5, name = "STYLE_SWORDS",   tex = "Interface\\Cursor\\Attack",                bar=false },
    { id = 6, name = "STYLE_SKULLS",   tex = "Interface\\Icons\\inv_misc_bone_skull_02", bar=false },
    { id = 7, name = "STYLE_DIAMONDS", tex = "Interface\\Icons\\inv_jewelcrafting_gem_28", bar=false },
    { id = 8, name = "STYLE_SHIELD",   tex = "Interface\\Icons\\ability_warrior_shieldbash", bar=false },
    { id = 9,name = "STYLE_RUNE_BLOOD", tex = "Interface\\Icons\\spell_deathknight_bloodpresence", bar=false },
    { id = 10,name = "STYLE_RUNE_FROST", tex = "Interface\\Icons\\spell_deathknight_frostpresence", bar=false },
    { id = 11,name = "STYLE_RUNE_UNHOLY",tex = "Interface\\Icons\\spell_deathknight_unholypresence", bar=false },
    { id = 12,name = "STYLE_FIST",     tex = "Interface\\Icons\\ability_monk_tigerpalm",   bar=false },
    { id = 13,name = "STYLE_LIGHTNING",tex = "Interface\\Icons\\spell_nature_lightning",   bar=false },
}

local ANIMATIONS = {
    { id = 1, key = "ANIM_NONE" },
    { id = 2, key = "ANIM_PULSE" },
    { id = 3, key = "ANIM_FLASH" },
    { id = 4, key = "ANIM_SHAKE" },
    { id = 5, key = "ANIM_ROTATE" },
    { id = 6, key = "ANIM_GLOW" },
}

-- SOUND LIST
local SOUNDS = {
    { id = 1, key = "SOUND_NONE",    file = nil },
    -- Soft / Short
    { id = 2, key = "SOUND_1", file = 416 },     -- Murloc
    { id = 3, key = "SOUND_2", file = 294726 },  
    { id = 4, key = "SOUND_3", file = 120 },     -- Magic Sizzle/Impact
    { id = 5, key = "SOUND_4", file = 1131 },    -- Heavy Thud (Earth Shock)
    -- Medium
    { id = 6, key = "SOUND_5", file = 17316 },   -- Clear Ping (LFG Role)
    { id = 7, key = "SOUND_6", file = 12867 },   -- Metallic Clang (Ready Check)
    { id = 8, key = "SOUND_7", file = 12334 },   
    -- Loud
    { id = 9, key = "SOUND_8", file = 8959 },    -- Raid Warning (Horn)
    { id = 10,key = "SOUND_9", file = 6423 },    
    { id = 11,key = "SOUND_10",file = 254469 },  
}

local BG_STYLES = {
    { name = "Modern (Dark)",   file = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark", edge = "Interface\\Tooltips\\UI-Tooltip-Border", tile=true },
    { name = "Metallic",        file = "Interface\\FrameGeneral\\UI-Background-Rock", edge = "Interface\\DialogFrame\\UI-DialogBox-Border", tile=true },
    { name = "Stone",           file = "Interface\\DialogFrame\\UI-DialogBox-Background", edge = "Interface\\DialogFrame\\UI-DialogBox-Border", tile=true },
}

local RESOURCE_COLORS = {
    [Enum.PowerType.ComboPoints]  = {1, 0.9, 0},     
    [Enum.PowerType.HolyPower]    = {0.95, 0.9, 0.2},
    [Enum.PowerType.ArcaneCharges]= {0.2, 0.6, 1},   
    [Enum.PowerType.Chi]          = {0.71, 1, 0.92}, 
    [Enum.PowerType.SoulShards]   = {0.5, 0.32, 0.55},   
    [Enum.PowerType.Essence]      = {0.4, 0.6, 1},   
}

-- Globals
local pointPool = {}
local containerFrame = nil
local optionsFrame = nil
local lastPowerValue = 0 
local lastAnimState = 0 
-- Forward declaration
local UpdateDisplay 
local AttachToTargetNameplate 

-- =========================================================================
-- 3. ANIMATION ENGINE
-- =========================================================================

local function CreateAnimations(f)
    -- Important: f is now a Frame, so animations work on the frame, affecting children
    -- 1. Pulse
    local agPulse = f:CreateAnimationGroup()
    agPulse:SetLooping("REPEAT")
    local s1 = agPulse:CreateAnimation("Scale")
    s1:SetOrder(1); s1:SetDuration(0.4); s1:SetScaleFrom(1,1); s1:SetScaleTo(0.85, 0.85); s1:SetSmoothing("OUT")
    local s2 = agPulse:CreateAnimation("Scale")
    s2:SetOrder(2); s2:SetDuration(0.4); s2:SetScaleFrom(0.85, 0.85); s2:SetScaleTo(1,1); s2:SetSmoothing("IN")
    f.animPulse = agPulse

    -- 2. Flash
    local agFlash = f:CreateAnimationGroup()
    agFlash:SetLooping("REPEAT")
    local a1 = agFlash:CreateAnimation("Alpha")
    a1:SetOrder(1); a1:SetDuration(0.2); a1:SetFromAlpha(1); a1:SetToAlpha(0.2)
    local a2 = agFlash:CreateAnimation("Alpha")
    a2:SetOrder(2); a2:SetDuration(0.2); a2:SetFromAlpha(0.2); a2:SetToAlpha(1)
    f.animFlash = agFlash

    -- 3. Shake
    local agShake = f:CreateAnimationGroup()
    agShake:SetLooping("REPEAT")
    local t1 = agShake:CreateAnimation("Translation")
    t1:SetOrder(1); t1:SetDuration(0.05); t1:SetOffset(2, 2)
    local t2 = agShake:CreateAnimation("Translation")
    t2:SetOrder(2); t2:SetDuration(0.05); t2:SetOffset(-4, -4)
    local t3 = agShake:CreateAnimation("Translation")
    t3:SetOrder(3); t3:SetDuration(0.05); t3:SetOffset(2, 2)
    f.animShake = agShake

    -- 4. Rotate
    local agRot = f:CreateAnimationGroup()
    agRot:SetLooping("REPEAT")
    local r1 = agRot:CreateAnimation("Rotation")
    r1:SetOrder(1); r1:SetDuration(2.0); r1:SetDegrees(-360)
    r1:SetOrigin("CENTER", 0, 0)
    f.animRotate = agRot

    -- 5. Glow
    f.glow = f:GetParent():CreateTexture(nil, "OVERLAY")
    f.glow:SetTexture("Interface\\Glues\\Models\\UI_Draenei\\GenericGlow64") 
    f.glow:SetBlendMode("ADD")
    f.glow:SetAlpha(0)
    f.glow:SetVertexColor(1, 1, 1, 1)
    
    local agGlow = f.glow:CreateAnimationGroup()
    agGlow:SetLooping("REPEAT")
    local ga1 = agGlow:CreateAnimation("Alpha")
    ga1:SetOrder(1); ga1:SetDuration(0.5); ga1:SetFromAlpha(0.2); ga1:SetToAlpha(1)
    local ga2 = agGlow:CreateAnimation("Alpha")
    ga2:SetOrder(2); ga2:SetDuration(0.5); ga2:SetFromAlpha(1); ga2:SetToAlpha(0.2)
    f.animGlow = agGlow
end

local function StopAllAnimations(point)
    if point.animPulse then point.animPulse:Stop() end
    if point.animFlash then point.animFlash:Stop() end
    if point.animShake then point.animShake:Stop() end
    if point.animRotate then point.animRotate:Stop() end
    
    if point.animGlow then point.animGlow:Stop(); point.glow:SetAlpha(0); end

    -- Reset Properties
    point:SetScale(1)
    point:SetAlpha(1) 
    point:SetPoint("CENTER", 0, 0)
    
    -- Reset inner rotations just in case
    if point.fg then point.fg:SetRotation(0) end
    if point.bg then point.bg:SetRotation(0) end
end

local function PlayAnimation(point, animID)
    if animID == 2 and point.animPulse then point.animPulse:Play() end
    if animID == 3 and point.animFlash then point.animFlash:Play() end
    if animID == 4 and point.animShake then point.animShake:Play() end
    if animID == 5 and point.animRotate then point.animRotate:Play() end
    
    if animID == 6 and point.animGlow then 
        point.glow:SetPoint("CENTER", point, "CENTER", 0, 0)
        point.glow:SetSize(point:GetWidth()*2.0, point:GetHeight()*2.0)
        point.animGlow:Play() 
    end
end

-- =========================================================================
-- 4. CORE UPDATE LOGIC
-- =========================================================================

containerFrame = CreateFrame("Frame", "ExtraResourcePlateContainer", UIParent, "BackdropTemplate")
containerFrame:SetSize(100, 30)
containerFrame:SetFrameStrata("HIGH") 
containerFrame:EnableMouse(false) 
containerFrame:Hide()

local function GetPointFrame(index, isPreview, parent)
    local pool
    if isPreview then
        if not parent.previewPool then parent.previewPool = {} end
        pool = parent.previewPool
    else
        pool = pointPool
    end

    if not pool[index] then
        -- Frame holding textures
        local f = CreateFrame("Frame", nil, (isPreview and parent or containerFrame), "BackdropTemplate")
        
        -- Background Layer (Empty/Inactive)
        local bg = f:CreateTexture(nil, "BACKGROUND")
        bg:SetAllPoints()
        f.bg = bg
        
        -- Foreground Layer (Filled/Active)
        local fg = f:CreateTexture(nil, "ARTWORK")
        fg:SetAllPoints()
        f.fg = fg
        
        -- FIX 3: BORDER using Backdrop instead of Texture
        -- We apply the backdrop to 'f' itself. We don't need a separate border texture.
        f:SetBackdrop({
            edgeFile = "Interface\\Buttons\\WHITE8X8", 
            edgeSize = 1,
        })
        f:SetBackdropBorderColor(0, 0, 0, 1) -- Black border
        f:SetBackdropColor(0,0,0,0) -- Transparent inside
        
        CreateAnimations(f)
        pool[index] = f
    end
    return pool[index]
end

local function DrawResourcePoints(frame, maxPoints, curPoints, isPreview, forceUpdateFrame)
    local db = ExtraResourcePlateCharDB
    
    local scale = db.scale or 1
    local width = (db.width or 14) * scale
    local height = (db.height or 14) * scale
    local spacing = (db.spacing or 4) * scale
    
    local styleIdx = db.design or 1
    local styleData = STYLES[styleIdx] or STYLES[1]
    
    -- Background Style (Live Only)
    if not isPreview then
        if db.showContainerBorder then
            local bgIdx = db.bgStyle or 1
            local bgData = BG_STYLES[bgIdx]
            frame:SetBackdrop({
                bgFile = bgData.file, 
                edgeFile = bgData.edge, 
                tile = bgData.tile, tileSize = 16, edgeSize = 12, 
                insets = { left = 4, right = 4, top = 4, bottom = 4 } 
            })
            frame:SetBackdropColor(0, 0, 0, db.bgAlpha or 0.5)
            frame:SetBackdropBorderColor(0, 0, 0, 1)
        else
            frame:SetBackdrop(nil)
        end
    end

    if styleData.bar then
        width = width * 1.5
        height = height * 0.6
    end

    -- COLOR LOGIC
    local color = {1, 1, 1, 1}
    local resourceType = nil
    local _, class = UnitClass("player")
    
    if db.useClassColor then
        if class == "ROGUE" or class == "DRUID" then resourceType = Enum.PowerType.ComboPoints
        elseif class == "PALADIN" then resourceType = Enum.PowerType.HolyPower
        elseif class == "MAGE" then resourceType = Enum.PowerType.ArcaneCharges
        elseif class == "MONK" then resourceType = Enum.PowerType.Chi
        elseif class == "WARLOCK" then resourceType = Enum.PowerType.SoulShards
        elseif class == "EVOKER" then resourceType = Enum.PowerType.Essence end
        
        if resourceType and RESOURCE_COLORS[resourceType] then
            local c = RESOURCE_COLORS[resourceType]
            color = {c[1], c[2], c[3], 1}
        else
            color = {1, 0.9, 0, 1} 
        end
    else
        local c = db.customColor
        color = {c.r, c.g, c.b, c.a}
    end
    
    local inactiveColor = {0.3, 0.3, 0.3, 0.6}

    local totalWidth = (maxPoints * width) + ((maxPoints - 1) * spacing) + (20 * scale)
    if not isPreview then
        frame:SetSize(totalWidth, height + (20 * scale))
    end
    
    -- --- ANIMATION & SOUND STATE LOGIC ---
    local animA, animB = 1, 1
    local currentState = 0 
    
    -- Stage 1 Trigger Logic
    local s1Trigger = db.anim1_trigger or 1

    if curPoints == maxPoints then
        currentState = 2
        if (db.anim2_type_a or 1) > 1 then animA = db.anim2_type_a end
        if (db.anim2_type_b or 1) > 1 then animB = db.anim2_type_b end
    elseif curPoints >= s1Trigger then
        currentState = 1
        if (db.anim1_type_a or 1) > 1 then animA = db.anim1_type_a end
        if (db.anim1_type_b or 1) > 1 then animB = db.anim1_type_b end
    end
    
    local powerChanged = (curPoints ~= lastPowerValue)
    -- FIX 1: Allow forcing update if passed from Options
    local forceUpdate = (currentState ~= lastAnimState) or powerChanged or forceUpdateFrame

    -- Play Sounds (Live only)
    if not isPreview and powerChanged then
        -- Trigger Stage 1 Sound
        if curPoints >= s1Trigger and lastPowerValue < s1Trigger then
            local sndId = db.sound1_id or 1
            if SOUNDS[sndId] and SOUNDS[sndId].file then
                PlaySound(SOUNDS[sndId].file, "Master")
            end
        end
        
        -- Trigger Stage 2 Sound
        if curPoints == maxPoints and lastPowerValue < maxPoints then
             local sndId = db.sound2_id or 1
             if SOUNDS[sndId] and SOUNDS[sndId].file then
                PlaySound(SOUNDS[sndId].file, "Master")
            end
        end
    end
    
    -- FIX 2: IMPROVED PRECISE POWER LOGIC (Warlocks / Fragments)
    local useFragments = false
    local precisePower = curPoints
    
    if not isPreview and resourceType then
        local p_precise = UnitPower("player", resourceType, true)
        local mp_precise = UnitPowerMax("player", resourceType, true)
        local mp_regular = UnitPowerMax("player", resourceType, false)
        
        -- If precise max is higher than regular max (e.g. 50 vs 5), we have fragments
        if mp_precise > mp_regular then
            useFragments = true
            precisePower = p_precise
            
            -- Calculate step size (e.g., 50 / 5 = 10 fragments per shard)
            local step = mp_precise / mp_regular
            
            for i = 1, maxPoints do
                local point = GetPointFrame(i, isPreview, frame)
                point:ClearAllPoints()
                point:SetSize(width, height)
                
                point.bg:SetTexture(styleData.tex)
                point.fg:SetTexture(styleData.tex)
                point.bg:SetVertexColor(unpack(inactiveColor))
                point.fg:SetVertexColor(unpack(color))
                
                -- Border Visibility check
                if db.showBorder then
                    point:SetBackdropBorderColor(0,0,0,1)
                else
                    point:SetBackdropBorderColor(0,0,0,0)
                end
                
                -- Fragment Calculation
                local rangeStart = (i - 1) * step
                local rangeEnd = i * step
                
                local isFull = false
                local fillAmt = 0
                
                if precisePower >= rangeEnd then
                    isFull = true
                    fillAmt = 1
                elseif precisePower > rangeStart then
                    isFull = true -- Active, but partial
                    fillAmt = (precisePower - rangeStart) / step
                else
                    isFull = false
                end
                
                if isFull then
                    point.fg:Show()
                    point.fg:SetTexCoord(0, fillAmt, 0, 1)
                    point.fg:SetWidth(width * fillAmt)
                    
                    if isPreview or forceUpdate then
                        StopAllAnimations(point)
                        -- Only animate fully completed points (optional, feels cleaner)
                        if fillAmt >= 0.99 then
                            if i <= curPoints then 
                                if animA > 1 then PlayAnimation(point, animA) end
                                if animB > 1 and animB ~= animA then PlayAnimation(point, animB) end
                            end
                        end
                    end
                else
                    point.fg:Hide()
                    StopAllAnimations(point)
                end
                
                -- Positioning
                if isPreview then
                    if i == 1 then point:SetPoint("LEFT", frame, "CENTER", -(totalWidth/2) + (10*scale), 0)
                    else local prev = frame.previewPool[i-1]; point:SetPoint("LEFT", prev, "RIGHT", spacing, 0) end
                else
                    if i == 1 then point:SetPoint("LEFT", frame, "LEFT", 10 * scale, 0)
                    else point:SetPoint("LEFT", pointPool[i-1], "RIGHT", spacing, 0) end
                end
                point:Show()
            end
            
            -- Finish Fragments Loop, skip standard loop
            if not isPreview then lastAnimState = currentState end
            local pool = isPreview and frame.previewPool or pointPool
            for i = maxPoints + 1, #pool do 
                pool[i]:Hide()
                StopAllAnimations(pool[i])
            end
            return -- Exit function, we handled drawing
        end
    end

    -- STANDARD LOOP (Non-Fragment)
    for i = 1, maxPoints do
        local point = GetPointFrame(i, isPreview, frame)
        point:ClearAllPoints()
        point:SetSize(width, height)
        
        point.bg:SetTexture(styleData.tex)
        point.fg:SetTexture(styleData.tex)
        point.bg:SetVertexColor(unpack(inactiveColor))
        point.fg:SetVertexColor(unpack(color))
        
        if db.showBorder then
            point:SetBackdropBorderColor(0,0,0,1)
        else
            point:SetBackdropBorderColor(0,0,0,0)
        end

        local isFull = (i <= curPoints)

        if isFull then
            point.fg:Show()
            point.fg:SetTexCoord(0, 1, 0, 1)
            point.fg:SetWidth(width)
            
            if isPreview or forceUpdate then
                StopAllAnimations(point)
                if animA > 1 then PlayAnimation(point, animA) end
                if animB > 1 and animB ~= animA then PlayAnimation(point, animB) end
            end
        else
            point.fg:Hide()
            StopAllAnimations(point)
        end

        -- Positioning
        if isPreview then
            if i == 1 then point:SetPoint("LEFT", frame, "CENTER", -(totalWidth/2) + (10*scale), 0)
            else local prev = frame.previewPool[i-1]; point:SetPoint("LEFT", prev, "RIGHT", spacing, 0) end
        else
            if i == 1 then point:SetPoint("LEFT", frame, "LEFT", 10 * scale, 0)
            else point:SetPoint("LEFT", pointPool[i-1], "RIGHT", spacing, 0) end
        end
        point:Show()
    end
    
    if not isPreview then
        lastAnimState = currentState
    end
    
    local pool = isPreview and frame.previewPool or pointPool
    for i = maxPoints + 1, #pool do 
        pool[i]:Hide()
        StopAllAnimations(pool[i])
    end
end

-- Updated to accept force argument
UpdateDisplay = function(force)
    if not ExtraResourcePlateCharDB.enabled then 
        containerFrame:Hide() 
        return 
    end

    local _, class = UnitClass("player")
    local resourceType = nil
    if class == "ROGUE" or class == "DRUID" then resourceType = Enum.PowerType.ComboPoints
    elseif class == "PALADIN" then resourceType = Enum.PowerType.HolyPower
    elseif class == "MAGE" and GetSpecialization() == 1 then resourceType = Enum.PowerType.ArcaneCharges
    elseif class == "MONK" then resourceType = Enum.PowerType.Chi
    elseif class == "WARLOCK" then resourceType = Enum.PowerType.SoulShards
    elseif class == "EVOKER" then resourceType = Enum.PowerType.Essence end
    
    if not resourceType then containerFrame:Hide() return end

    local cur = UnitPower("player", resourceType)
    local max = UnitPowerMax("player", resourceType)
    
    if not cur or not max or max == 0 then 
        containerFrame:Hide()
        lastPowerValue = 0
        return 
    end
    
    DrawResourcePoints(containerFrame, max, cur, false, force)
    lastPowerValue = cur
    containerFrame:Show()
end

AttachToTargetNameplate = function()
    if not C_NamePlate then return end
    local targetNameplate = C_NamePlate.GetNamePlateForUnit("target")
    
    -- Check Enabled
    if not ExtraResourcePlateCharDB.enabled then 
        containerFrame:Hide()
        return 
    end
    
    if targetNameplate and not targetNameplate:IsForbidden() then
        containerFrame:SetParent(targetNameplate)
        containerFrame:ClearAllPoints()
        
        local db = ExtraResourcePlateCharDB
        local pos = db.position or "TOP"
        local yOffset = db.yOffset or 20
        local xOffset = db.xOffset or 0 
        
        local visualFrame = targetNameplate.UnitFrame
        local anchorFrame = (visualFrame and not visualFrame:IsForbidden()) and visualFrame or targetNameplate
        
        if pos == "TOP" then
            containerFrame:SetPoint("BOTTOM", anchorFrame, "TOP", xOffset, yOffset)
        else
            containerFrame:SetPoint("TOP", anchorFrame, "BOTTOM", xOffset, -yOffset) 
        end
        UpdateDisplay(true) -- Force update on re-attach
    else
        containerFrame:Hide()
    end
end

-- =========================================================================
-- 5. OPTIONS MENU
-- =========================================================================

-- PROFILE HELPER FUNCTIONS
local function ExportProfile()
    local str = "ERP:v1"
    for k, v in pairs(ExtraResourcePlateCharDB) do
        -- Don't export the entire SavedProfiles list inside a single profile export
        if k ~= "savedProfiles" then
            if type(v) == "table" and v.r then
                 str = str .. "|" .. k .. string.format(":%.2f,%.2f,%.2f,%.2f", v.r, v.g, v.b, v.a)
            elseif type(v) ~= "function" and type(v) ~= "table" then
                str = str .. "|" .. k .. ":" .. tostring(v)
            end
        end
    end
    return str
end

local function ImportProfile(str)
    if not str or str == "" then return false end
    if not string.find(str, "^ERP:v1") then return false end
    
    -- Keep existing saved profiles
    local saved = ExtraResourcePlateCharDB.savedProfiles
    
    -- Reset to defaults
    ExtraResourcePlateCharDB = CopyTable(defaults)
    ExtraResourcePlateCharDB.savedProfiles = saved
    
    for item in string.gmatch(str, "([^|]+)") do
        if item ~= "ERP:v1" then
            local k, v = string.match(item, "([^:]+):(.+)")
            if k and v then
                if string.find(v, ",") then
                    local r, g, b, a = string.match(v, "([%d%.]+),([%d%.]+),([%d%.]+),([%d%.]+)")
                    ExtraResourcePlateCharDB[k] = {r=tonumber(r), g=tonumber(g), b=tonumber(b), a=tonumber(a)}
                else
                    if v == "true" then ExtraResourcePlateCharDB[k] = true
                    elseif v == "false" then ExtraResourcePlateCharDB[k] = false
                    elseif tonumber(v) then ExtraResourcePlateCharDB[k] = tonumber(v)
                    else ExtraResourcePlateCharDB[k] = v end
                end
            end
        end
    end
    return true
end

local function SaveProfile(name)
    if not name or name == "" then return false end
    if not ExtraResourcePlateCharDB.savedProfiles then ExtraResourcePlateCharDB.savedProfiles = {} end
    
    local profileData = {}
    for k, v in pairs(ExtraResourcePlateCharDB) do
        if k ~= "savedProfiles" then
            profileData[k] = v
        end
    end
    ExtraResourcePlateCharDB.savedProfiles[name] = profileData
    return true
end

local function LoadProfile(name)
    if not ExtraResourcePlateCharDB.savedProfiles or not ExtraResourcePlateCharDB.savedProfiles[name] then return false end
    local data = ExtraResourcePlateCharDB.savedProfiles[name]
    
    local saved = ExtraResourcePlateCharDB.savedProfiles
    ExtraResourcePlateCharDB = CopyTable(data)
    ExtraResourcePlateCharDB.savedProfiles = saved
    return true
end

CreateOptionsFrame = function()
    if optionsFrame then return end
    local f = CreateFrame("Frame", "ExtraResourcePlateOptions", UIParent, "BackdropTemplate")
    f:SetSize(500, 650)
    f:SetPoint("CENTER")
    f:SetFrameStrata("DIALOG")
    f:EnableMouse(true)
    f:SetMovable(true)
    f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", f.StopMovingOrSizing)
    
    if ExtraResourcePlateCharDB.menuScale then f:SetScale(ExtraResourcePlateCharDB.menuScale) end
    f:Hide()

    f:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
        edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
        tile = true, tileSize = 32, edgeSize = 32,
        insets = { left = 11, right = 12, top = 12, bottom = 11 }
    })

    local title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
    title:SetPoint("TOP", 0, -16)
    title:SetText("ExtraResourcePlate v1.0")
    
    local closeBtn = CreateFrame("Button", nil, f, "UIPanelCloseButton")
    closeBtn:SetPoint("TOPRIGHT", -8, -8)

    -- Zoom Controls
    local btnZoomOut = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    btnZoomOut:SetSize(20, 20); btnZoomOut:SetPoint("TOPRIGHT", -100, -12); btnZoomOut:SetText("-")
    local btnZoomIn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    btnZoomIn:SetSize(20, 20); btnZoomIn:SetPoint("LEFT", btnZoomOut, "RIGHT", 5, 0); btnZoomIn:SetText("+")
    btnZoomOut:SetScript("OnClick", function() 
        ExtraResourcePlateCharDB.menuScale = math.max(0.6, (ExtraResourcePlateCharDB.menuScale or 1) - 0.1)
        f:SetScale(ExtraResourcePlateCharDB.menuScale)
    end)
    btnZoomIn:SetScript("OnClick", function() 
        ExtraResourcePlateCharDB.menuScale = math.min(2.0, (ExtraResourcePlateCharDB.menuScale or 1) + 0.1)
        f:SetScale(ExtraResourcePlateCharDB.menuScale)
    end)

    -- PREVIEW BOX
    local previewBox = CreateFrame("Frame", nil, f, "BackdropTemplate")
    previewBox:SetSize(400, 70)
    previewBox:SetPoint("TOP", 0, -50)
    previewBox:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8X8", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = false, edgeSize = 16, insets = { left = 4, right = 4, top = 4, bottom = 4 }
    })
    previewBox:SetBackdropColor(0.1, 0.1, 0.1, 0.8)
    local pLabel = previewBox:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    pLabel:SetPoint("BOTTOMRIGHT", -5, 5); pLabel:SetText(L.PREVIEW)
    f.previewContainer = previewBox
    
    local function UpdatePreview() DrawResourcePoints(f.previewContainer, 5, 5, true) end
    f:SetScript("OnShow", UpdatePreview)

    -- TABS
    local tabs = {}
    local panels = {}
    local tabNames = { L.TAB_GENERAL, L.TAB_DESIGN, L.TAB_ALERTS, L.TAB_COLORS, L.TAB_PROFILE }
    
    local function SelectTab(id)
        for i, panel in ipairs(panels) do if i == id then panel:Show() else panel:Hide() end end
        for i, tab in ipairs(tabs) do if i == id then tab:SetEnabled(false) else tab:SetEnabled(true) end end
    end

    for i, name in ipairs(tabNames) do
        local t = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
        t:SetSize(80, 24)
        if i == 1 then t:SetPoint("TOPLEFT", 20, -130) else t:SetPoint("LEFT", tabs[i-1], "RIGHT", 5, 0) end
        t:SetText(name)
        t:SetScript("OnClick", function() SelectTab(i) end)
        table.insert(tabs, t)
        
        local p = CreateFrame("Frame", nil, f)
        p:SetSize(460, 500); p:SetPoint("TOP", 0, -160); p:Hide()
        table.insert(panels, p)
    end

    -- --- TAB 1: GENERAL ---
    local p1 = panels[1]
    local cbEnable = CreateFrame("CheckButton", nil, p1, "UICheckButtonTemplate")
    cbEnable:SetPoint("TOPLEFT", 20, 0)
    cbEnable.text:SetText(L.ENABLED)
    cbEnable:SetChecked(ExtraResourcePlateCharDB.enabled)
    cbEnable:SetScript("OnClick", function(self) 
        ExtraResourcePlateCharDB.enabled = self:GetChecked()
        UpdateDisplay(true) 
    end)

    local cbContBorder = CreateFrame("CheckButton", nil, p1, "UICheckButtonTemplate")
    cbContBorder:SetPoint("TOPLEFT", 200, 0) 
    cbContBorder.text:SetText(L.CONTAINER_BORDER)
    cbContBorder:SetChecked(ExtraResourcePlateCharDB.showContainerBorder)
    cbContBorder:SetScript("OnClick", function(self) 
        ExtraResourcePlateCharDB.showContainerBorder = self:GetChecked()
        UpdateDisplay(true) 
    end)
    
    local function CreateSlider(parent, label, key, min, max, step, y)
        local s = CreateFrame("Slider", "ERP_Slider_"..key, parent, "OptionsSliderTemplate")
        s:SetWidth(180); s:SetPoint("TOPLEFT", 20, y); s:SetMinMaxValues(min, max); s:SetValueStep(step); s:SetObeyStepOnDrag(true)
        local val = ExtraResourcePlateCharDB[key] or defaults[key] or min
        s:SetValue(val)
        _G[s:GetName().."Text"]:SetText(label .. ": " .. s:GetValue())
        _G[s:GetName().."Low"]:SetText(min); _G[s:GetName().."High"]:SetText(max)
        s:SetScript("OnValueChanged", function(self, v)
            v = math.floor(v*100+0.5)/100
            ExtraResourcePlateCharDB[key] = v
            _G[self:GetName().."Text"]:SetText(label .. ": " .. v)
            if UnitExists("target") then UpdateDisplay(true); AttachToTargetNameplate() end
            UpdatePreview()
        end)
    end
    
    CreateSlider(p1, L.SIZE .. " (" .. L.WIDTH .. ")", "width", 5, 50, 1, -40)
    CreateSlider(p1, L.SIZE .. " (" .. L.HEIGHT .. ")", "height", 5, 50, 1, -80)
    CreateSlider(p1, L.SPACING, "spacing", 0, 20, 1, -120)
    
    local lblPos = p1:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    lblPos:SetPoint("TOPRIGHT", -150, -40); lblPos:SetText(L.POSITION)
    local cbTop = CreateFrame("CheckButton", nil, p1, "UICheckButtonTemplate")
    cbTop:SetPoint("TOP", lblPos, "BOTTOM", 0, -5); cbTop.text:SetText(L.POS_TOP)
    local cbBot = CreateFrame("CheckButton", nil, p1, "UICheckButtonTemplate")
    cbBot:SetPoint("TOP", cbTop, "BOTTOM", 0, 0); cbBot.text:SetText(L.POS_BOTTOM)
    local function UpdPos() cbTop:SetChecked(ExtraResourcePlateCharDB.position == "TOP"); cbBot:SetChecked(ExtraResourcePlateCharDB.position == "BOTTOM") end
    cbTop:SetScript("OnClick", function() ExtraResourcePlateCharDB.position="TOP"; UpdPos(); AttachToTargetNameplate() end)
    cbBot:SetScript("OnClick", function() ExtraResourcePlateCharDB.position="BOTTOM"; UpdPos(); AttachToTargetNameplate() end)
    UpdPos()
    
    CreateSlider(p1, L.OFFSET_Y, "yOffset", -50, 150, 1, -180)
    CreateSlider(p1, L.OFFSET_X, "xOffset", -100, 100, 1, -220)
    CreateSlider(p1, L.BG_OPACITY, "bgAlpha", 0, 1, 0.1, -280)
    
    local lblBg = p1:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    lblBg:SetPoint("TOPRIGHT", -100, -285); lblBg:SetText(L.BG_STYLE)
    local btnBgL = CreateFrame("Button", nil, p1, "UIPanelButtonTemplate"); btnBgL:SetSize(20,20); btnBgL:SetPoint("RIGHT", lblBg, "LEFT", -10, -20); btnBgL:SetText("<")
    local txtBg = p1:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); txtBg:SetPoint("LEFT", btnBgL, "RIGHT", 5, 0); txtBg:SetWidth(100); txtBg:SetText(BG_STYLES[1].name)
    local btnBgR = CreateFrame("Button", nil, p1, "UIPanelButtonTemplate"); btnBgR:SetSize(20,20); btnBgR:SetPoint("LEFT", txtBg, "RIGHT", 5, 0); btnBgR:SetText(">")
    local function UpdBgTxt() local i = ExtraResourcePlateCharDB.bgStyle or 1; txtBg:SetText(BG_STYLES[i].name); UpdateDisplay(true) end
    UpdBgTxt()
    btnBgL:SetScript("OnClick", function() local i = ExtraResourcePlateCharDB.bgStyle or 1; i=i-1; if i<1 then i=#BG_STYLES end; ExtraResourcePlateCharDB.bgStyle=i; UpdBgTxt() end)
    btnBgR:SetScript("OnClick", function() local i = ExtraResourcePlateCharDB.bgStyle or 1; i=i+1; if i>#BG_STYLES then i=1 end; ExtraResourcePlateCharDB.bgStyle=i; UpdBgTxt() end)

    -- --- TAB 2: DESIGN ---
    local p2 = panels[2]
    local cbBorder = CreateFrame("CheckButton", nil, p2, "UICheckButtonTemplate")
    cbBorder:SetPoint("TOPLEFT", 20, -10)
    cbBorder.text:SetText(L.BORDER)
    cbBorder:SetChecked(ExtraResourcePlateCharDB.showBorder)
    cbBorder:SetScript("OnClick", function(self) ExtraResourcePlateCharDB.showBorder = self:GetChecked(); UpdatePreview(); if UnitExists("target") then UpdateDisplay(true) end end)
    
    local lblDesign = p2:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    lblDesign:SetPoint("TOPLEFT", 20, -50); lblDesign:SetText(L.SHAPE)
    local lastBtn = nil
    for i, style in ipairs(STYLES) do
        local btn = CreateFrame("Button", nil, p2, "UIPanelButtonTemplate")
        btn:SetSize(130, 25)
        if i % 3 == 1 then btn:SetPoint("TOPLEFT", 20, -80 - (math.floor((i-1)/3)*30)) else btn:SetPoint("LEFT", lastBtn, "RIGHT", 10, 0) end
        lastBtn = btn
        btn:SetText(L[style.name] or style.name)
        btn:SetScript("OnClick", function() ExtraResourcePlateCharDB.design = i; UpdatePreview(); if UnitExists("target") then UpdateDisplay(true) end end)
    end
    
    -- --- TAB 3: ALERTS ---
    local p3 = panels[3]
    
    local function CreateAnimSlot(parent, label, key, y, list, db_key)
        local lbl = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        lbl:SetPoint("TOPLEFT", 30, y); lbl:SetText(label)
        
        local btnL = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate"); btnL:SetSize(20,20); btnL:SetPoint("LEFT", lbl, "RIGHT", 10, 0); btnL:SetText("<")
        local txt = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal"); txt:SetPoint("LEFT", btnL, "RIGHT", 5, 0); txt:SetWidth(140); txt:SetJustifyH("CENTER")
        local btnR = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate"); btnR:SetSize(20,20); btnR:SetPoint("LEFT", txt, "RIGHT", 5, 0); btnR:SetText(">")
        
        local function Upd(playSound)
            local idx = ExtraResourcePlateCharDB[db_key] or 1
            local item = list[idx] or list[1]
            txt:SetText(L[item.key] or item.key)
            if playSound and list == SOUNDS and item.file then
                PlaySound(item.file, "Master")
            elseif list == ANIMATIONS then
                UpdatePreview()
                UpdateDisplay(true) -- Force update for animation changes
            end
        end
        Upd(false)
        
        btnL:SetScript("OnClick", function() local i = ExtraResourcePlateCharDB[db_key] or 1; i=i-1; if i<1 then i=#list end; ExtraResourcePlateCharDB[db_key]=i; Upd(true) end)
        btnR:SetScript("OnClick", function() local i = ExtraResourcePlateCharDB[db_key] or 1; i=i+1; if i>#list then i=1 end; ExtraResourcePlateCharDB[db_key]=i; Upd(true) end)
    end
    
    local hdrVisual = p3:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    hdrVisual:SetPoint("TOPLEFT", 20, -10); hdrVisual:SetText(L.SECTION_ANIMATIONS)

    local lblS1 = p3:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    lblS1:SetPoint("TOPLEFT", 20, -40); lblS1:SetText(L.ANIM_TRIGGER_1)
    local sTrig = CreateFrame("Slider", "ERP_AnimSlider_Trigger", p3, "OptionsSliderTemplate")
    sTrig:SetWidth(100); sTrig:SetPoint("LEFT", lblS1, "RIGHT", 20, 0)
    sTrig:SetMinMaxValues(1, 10); sTrig:SetValueStep(1); sTrig:SetObeyStepOnDrag(true)
    local val = ExtraResourcePlateCharDB.anim1_trigger or 1; sTrig:SetValue(val)
    _G[sTrig:GetName().."Text"]:SetText(val); _G[sTrig:GetName().."Low"]:SetText("1"); _G[sTrig:GetName().."High"]:SetText("10")
    sTrig:SetScript("OnValueChanged", function(self, v) 
        ExtraResourcePlateCharDB.anim1_trigger = math.floor(v)
        _G[self:GetName().."Text"]:SetText(math.floor(v))
        UpdateDisplay(true) 
    end)
    
    CreateAnimSlot(p3, L.ANIM_SLOT_1, "anim1_type_a", -70, ANIMATIONS, "anim1_type_a")
    CreateAnimSlot(p3, L.ANIM_SLOT_2, "anim1_type_b", -100, ANIMATIONS, "anim1_type_b")
    
    local lblS2 = p3:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    lblS2:SetPoint("TOPLEFT", 20, -140); lblS2:SetText(L.ANIM_TRIGGER_2)
    CreateAnimSlot(p3, L.ANIM_SLOT_1, "anim2_type_a", -170, ANIMATIONS, "anim2_type_a")
    CreateAnimSlot(p3, L.ANIM_SLOT_2, "anim2_type_b", -200, ANIMATIONS, "anim2_type_b")

    local hdrSound = p3:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    hdrSound:SetPoint("TOPLEFT", 20, -240); hdrSound:SetText(L.SECTION_SOUNDS)

    local lblSnd1 = p3:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    lblSnd1:SetPoint("TOPLEFT", 20, -270); lblSnd1:SetText(L.ANIM_TRIGGER_1 .. " (Sound)")
    CreateAnimSlot(p3, "Sound:", "sound1_id", -300, SOUNDS, "sound1_id")

    local lblSnd2 = p3:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    lblSnd2:SetPoint("TOPLEFT", 20, -340); lblSnd2:SetText(L.ANIM_TRIGGER_2 .. " (Sound)")
    CreateAnimSlot(p3, "Sound:", "sound2_id", -370, SOUNDS, "sound2_id")

    local disclaimer = p3:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    disclaimer:SetPoint("TOP", 0, -420) 
    disclaimer:SetWidth(400); disclaimer:SetJustifyH("CENTER")
    disclaimer:SetText(L.ANIM_DISCLAIMER); disclaimer:SetTextColor(0.8, 0.5, 0.5, 1) 

    -- --- TAB 4: COLORS ---
    local p4 = panels[4]
    local cbClass = CreateFrame("CheckButton", nil, p4, "UICheckButtonTemplate")
    cbClass:SetPoint("TOPLEFT", 20, -20); cbClass.text:SetText(L.COLOR_CLASS); cbClass:SetChecked(ExtraResourcePlateCharDB.useClassColor)
    
    local btnPick = CreateFrame("Button", nil, p4, "UIPanelButtonTemplate")
    btnPick:SetSize(120, 25); btnPick:SetPoint("TOPLEFT", 20, -60); btnPick:SetText(L.COLOR_PICK)
    local swatch = p4:CreateTexture(nil, "ARTWORK"); swatch:SetSize(20, 20); swatch:SetPoint("LEFT", btnPick, "RIGHT", 10, 0); swatch:SetColorTexture(1, 1, 1, 1)
    
    local function UpdColorUI()
        local use = ExtraResourcePlateCharDB.useClassColor
        cbClass:SetChecked(use)
        if use then btnPick:Disable(); swatch:SetDesaturated(true) else btnPick:Enable(); swatch:SetDesaturated(false); local c = ExtraResourcePlateCharDB.customColor; swatch:SetColorTexture(c.r, c.g, c.b, c.a) end
        UpdatePreview(); if UnitExists("target") then UpdateDisplay(true) end
    end
    cbClass:SetScript("OnClick", function(self) ExtraResourcePlateCharDB.useClassColor = self:GetChecked(); UpdColorUI() end)
    btnPick:SetScript("OnClick", function()
        local c = ExtraResourcePlateCharDB.customColor
        local function OnColorSelect()
            local r, g, b = ColorPickerFrame:GetColorRGB(); local a = ColorPickerFrame:GetColorAlpha()
            ExtraResourcePlateCharDB.customColor = {r=r, g=g, b=b, a=a}
            UpdColorUI()
        end
        if ColorPickerFrame.SetupColorPickerAndShow then
            ColorPickerFrame:SetupColorPickerAndShow({swatchFunc=OnColorSelect, opacityFunc=OnColorSelect, cancelFunc=function(v) ExtraResourcePlateCharDB.customColor={r=v.r,g=v.g,b=v.b,a=v.a} UpdColorUI() end, r=c.r, g=c.g, b=c.b, opacity=c.a, hasOpacity=true})
        else
            ColorPickerFrame:SetColorRGB(c.r, c.g, c.b); ColorPickerFrame.hasOpacity, ColorPickerFrame.opacity = true, c.a; ColorPickerFrame.func, ColorPickerFrame.opacityFunc = OnColorSelect, OnColorSelect; ColorPickerFrame:Show()
        end
    end)
    UpdColorUI()

    -- --- TAB 5: PROFILE ---
    local p5 = panels[5]
    
    -- Section: Manage Profiles (FIX 4)
    local hdrManage = p5:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    hdrManage:SetPoint("TOPLEFT", 20, -10); hdrManage:SetText(L.SECTION_MANAGE_PROFILES)
    
    local ebName = CreateFrame("EditBox", nil, p5, "InputBoxTemplate")
    ebName:SetSize(200, 30); ebName:SetPoint("TOPLEFT", 20, -40)
    ebName:SetAutoFocus(false)
    ebName:SetText(L.PROFILE_NAME_HINT)
    ebName:SetScript("OnEnterPressed", function(self) self:ClearFocus() end)
    ebName:SetScript("OnEditFocusGained", function(self) if self:GetText() == L.PROFILE_NAME_HINT then self:SetText("") end end)
    
    local btnSave = CreateFrame("Button", nil, p5, "UIPanelButtonTemplate")
    btnSave:SetSize(100, 25); btnSave:SetPoint("LEFT", ebName, "RIGHT", 10, 0); btnSave:SetText(L.SAVE_PROFILE)
    btnSave:SetScript("OnClick", function()
        local name = ebName:GetText()
        if name and name ~= "" and name ~= L.PROFILE_NAME_HINT then
            SaveProfile(name)
            print("|cff00ff00" .. L.PROFILE_SAVED .. name .. "|r")
        else
            print("|cffff0000" .. L.NO_PROFILE_NAME .. "|r")
        end
    end)

    -- Dropdown Logic (Pseudo Dropdown for Simplicity)
    local dropFrame = CreateFrame("Frame", nil, p5, "BackdropTemplate")
    dropFrame:SetSize(200, 150); dropFrame:SetPoint("TOPLEFT", 20, -100)
    dropFrame:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
        tile = true, tileSize = 16, edgeSize = 16, insets = { left = 4, right = 4, top = 4, bottom = 4 }
    })
    dropFrame:Hide()
    dropFrame:SetFrameStrata("DIALOG")
    
    local scrollF = CreateFrame("ScrollFrame", nil, dropFrame, "UIPanelScrollFrameTemplate")
    scrollF:SetPoint("TOPLEFT", 5, -5); scrollF:SetPoint("BOTTOMRIGHT", -25, 5)
    local scrollChild = CreateFrame("Frame"); scrollChild:SetSize(170, 300)
    scrollF:SetScrollChild(scrollChild)
    
    local function RefreshProfileList()
        local children = { scrollChild:GetChildren() }
        for _, child in ipairs(children) do child:Hide() end
        
        if not ExtraResourcePlateCharDB.savedProfiles then return end
        
        local y = 0
        for name, _ in pairs(ExtraResourcePlateCharDB.savedProfiles) do
            local b = CreateFrame("Button", nil, scrollChild)
            b:SetSize(160, 20); b:SetPoint("TOPLEFT", 5, -y)
            local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            t:SetPoint("LEFT", 5, 0); t:SetText(name)
            
            local del = CreateFrame("Button", nil, b, "UIPanelButtonTemplate")
            del:SetSize(16,16); del:SetPoint("RIGHT", -2, 0); del:SetText("X")
            del:SetScript("OnClick", function() 
                ExtraResourcePlateCharDB.savedProfiles[name] = nil
                print(L.PROFILE_DELETED .. name)
                RefreshProfileList()
            end)
            
            b:SetScript("OnClick", function()
                LoadProfile(name)
                print("|cff00ff00" .. L.PROFILE_LOADED .. name .. "|r")
                dropFrame:Hide()
                f:Hide(); f:Show() -- Refresh UI
                UpdateDisplay(true)
                if UnitExists("target") then AttachToTargetNameplate() end
            end)
            
            b:Show()
            y = y + 22
        end
        scrollChild:SetHeight(math.max(y, 100))
    end

    local btnLoad = CreateFrame("Button", nil, p5, "UIPanelButtonTemplate")
    btnLoad:SetSize(150, 25); btnLoad:SetPoint("TOPLEFT", 20, -80); btnLoad:SetText(L.LOAD_PROFILE .. " (Select)")
    btnLoad:SetScript("OnClick", function()
        if dropFrame:IsShown() then dropFrame:Hide() else 
            RefreshProfileList()
            dropFrame:Show() 
        end
    end)
    
    -- Section: Import/Export
    local hdrImport = p5:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    hdrImport:SetPoint("TOPLEFT", 20, -180); hdrImport:SetText(L.SECTION_PROFILE)

    local lblExp = p5:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    lblExp:SetPoint("TOPLEFT", 20, -210); lblExp:SetText(L.EXPORT_DESC)
    
    local ebExport = CreateFrame("EditBox", nil, p5, "InputBoxTemplate")
    ebExport:SetSize(400, 30); ebExport:SetPoint("TOPLEFT", 20, -230)
    ebExport:SetAutoFocus(false)
    
    local btnExport = CreateFrame("Button", nil, p5, "UIPanelButtonTemplate")
    btnExport:SetSize(120, 25); btnExport:SetPoint("TOPLEFT", 20, -265); btnExport:SetText(L.BTN_EXPORT)
    btnExport:SetScript("OnClick", function()
        local code = ExportProfile()
        ebExport:SetText(code)
        ebExport:HighlightText()
        ebExport:SetFocus()
    end)
    
    local lblImp = p5:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    lblImp:SetPoint("TOPLEFT", 20, -310); lblImp:SetText(L.IMPORT_DESC)
    
    local ebImport = CreateFrame("EditBox", nil, p5, "InputBoxTemplate")
    ebImport:SetSize(400, 30); ebImport:SetPoint("TOPLEFT", 20, -330)
    ebImport:SetAutoFocus(false)
    
    local btnImport = CreateFrame("Button", nil, p5, "UIPanelButtonTemplate")
    btnImport:SetSize(120, 25); btnImport:SetPoint("TOPLEFT", 20, -365); btnImport:SetText(L.BTN_IMPORT)
    btnImport:SetScript("OnClick", function()
        local code = ebImport:GetText()
        if ImportProfile(code) then
            print("|cff00ff00" .. L.IMPORT_SUCCESS .. "|r")
            f:Hide() -- Hide to reset UI state properly
            f:Show() -- Show again to refresh values
            UpdateDisplay(true)
            if UnitExists("target") then AttachToTargetNameplate() end
        else
            print("|cffff0000" .. L.IMPORT_FAIL .. "|r")
        end
    end)

    local footer = f:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall")
    footer:SetPoint("BOTTOM", 0, 15); footer:SetText(L.FOOTER)
    SelectTab(1)
    optionsFrame = f
end

-- =========================================================================
-- 6. INIT & EVENTS
-- =========================================================================

local function InitializeDB()
    if not ExtraResourcePlateCharDB then ExtraResourcePlateCharDB = CopyTable(defaults) else for k, v in pairs(defaults) do if ExtraResourcePlateCharDB[k] == nil then ExtraResourcePlateCharDB[k] = v end end end
end

SLASH_EXTRARESOURCEPLATE1 = "/erp"
SLASH_EXTRARESOURCEPLATE2 = "/extraresourceplate"
SlashCmdList["EXTRARESOURCEPLATE"] = function(msg) if not optionsFrame then CreateOptionsFrame() end; if optionsFrame:IsShown() then optionsFrame:Hide() else optionsFrame:Show() end end

local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("PLAYER_LOGIN")
eventFrame:RegisterEvent("PLAYER_TARGET_CHANGED")
eventFrame:RegisterEvent("NAME_PLATE_UNIT_ADDED")
eventFrame:RegisterEvent("NAME_PLATE_UNIT_REMOVED")
eventFrame:RegisterEvent("UNIT_POWER_UPDATE")
eventFrame:RegisterEvent("UNIT_MAXPOWER")
eventFrame:RegisterEvent("UNIT_DISPLAYPOWER")
eventFrame:RegisterEvent("ADDON_LOADED")

eventFrame:SetScript("OnEvent", function(self, event, arg1, arg2)
    if event == "ADDON_LOADED" and arg1 == addonName then
        InitializeDB()
        print("|cff00ff00" .. L.LOADED_MSG .. "|r")
        if not _G["ExtraResourcePlateMinimapButton"] then
             local btn = CreateFrame("Button", "ExtraResourcePlateMinimapButton", Minimap)
             btn:SetFrameStrata("MEDIUM"); btn:SetSize(31, 31); btn:SetFrameLevel(8); btn:EnableMouse(true); btn:SetMovable(true)
             
             local icon = btn:CreateTexture(nil, "BACKGROUND")
             icon:SetTexture("Interface\\AddOns\\ExtraResourcePlate\\ExtraResourcePlate_Logo.tga")
             icon:SetSize(20, 20); icon:SetPoint("CENTER", 0, 0)
             
             local border = btn:CreateTexture(nil, "OVERLAY"); border:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder"); border:SetSize(52,52); border:SetPoint("TOPLEFT",0,0)
             btn:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
             local function UpdBtn() local a = math.rad(ExtraResourcePlateCharDB.minimapPos or 45); local r = (Minimap:GetWidth()/2)+10; btn:SetPoint("CENTER", Minimap, "CENTER", math.cos(a)*r, math.sin(a)*r) end
             btn:RegisterForDrag("LeftButton")
             btn:SetScript("OnDragStart", function() btn:SetScript("OnUpdate", function() local mx, my = Minimap:GetCenter(); local cx, cy = GetCursorPosition(); local s = Minimap:GetEffectiveScale(); ExtraResourcePlateCharDB.minimapPos = math.deg(math.atan2((cy/s)-my, (cx/s)-mx)); UpdBtn() end) end)
             btn:SetScript("OnDragStop", function() btn:SetScript("OnUpdate", nil) end)
             btn:SetScript("OnClick", function() if not optionsFrame then CreateOptionsFrame() end; if optionsFrame:IsShown() then optionsFrame:Hide() else optionsFrame:Show() end end)
             btn:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_LEFT"); GameTooltip:SetText(L.MINIMAP_TOOLTIP, 1, 1, 1, 1, true); GameTooltip:Show() end)
             btn:SetScript("OnLeave", function() GameTooltip:Hide() end)
             UpdBtn()
        end
    elseif event == "PLAYER_TARGET_CHANGED" then AttachToTargetNameplate()
    elseif event == "NAME_PLATE_UNIT_ADDED" and UnitIsUnit(arg1, "target") then AttachToTargetNameplate()
    elseif event == "NAME_PLATE_UNIT_REMOVED" and UnitIsUnit(arg1, "target") then containerFrame:Hide()
    elseif event == "UNIT_POWER_UPDATE" or event == "UNIT_MAXPOWER" or event == "UNIT_DISPLAYPOWER" then if arg1 == "player" then UpdateDisplay() end
    end
end)