-- FullSteel.lua
-- Warrior ability sound addon with Diablo 2 Barbarian sounds

-- =========================================================================
-- 1. INITIALIZATION & DEFAULTS
-- =========================================================================
local db = {}
local playerGUID = nil
local originalVolume = nil
local restoreTimer = nil
local uiLoaded = false

-- Define defaults here for easy maintenance
local defaults = {
    enabled = true, debug = false,
    charge = true, intercept = true, intervene = true, execute = true, whirlwind = true,
    battleshout = true, demoshout = true, challengeshout = true, intimidateshout = true, taunt = true,
    chargeVolume = 100, executeVolume = 100, shoutVolume = 100, whirlwindVolume = 100,
    chargeSound = 1, executeSound = 0, whirlwindSound = 0, battleshoutSound = 0,
    demoshoutSound = 0, challengeshoutSound = 0, intimidateshoutSound = 0, tauntSound = 0
}

local function dprint(...)
    if db.debug then print("FullSteel:", ...) end
end

-- Optimization: Safe Sound Player (Prevents Volume Bugs)
local function PlaySafeSound(soundFile, volumePercent)
    if not soundFile then return end
    volumePercent = volumePercent or 100
    if volumePercent <= 0 then return end

    -- 1. Save original volume if not already tracked
    if not originalVolume then
        originalVolume = tonumber(GetCVar("Sound_SFXVolume")) or 1.0
    end

    -- 2. Set temp volume (Clamped 0-1)
    local newVolume = originalVolume * (volumePercent / 100.0)
    newVolume = math.max(0, math.min(1.0, newVolume))
    SetCVar("Sound_SFXVolume", tostring(newVolume))

    -- 3. Play
    PlaySoundFile(soundFile, "SFX")

    -- 4. Reset Timer (Cancel old one if exists)
    if restoreTimer then restoreTimer:Cancel() end
    restoreTimer = C_Timer.NewTimer(2.0, function()
        if originalVolume then
            SetCVar("Sound_SFXVolume", tostring(originalVolume))
            originalVolume = nil
            restoreTimer = nil
        end
    end)
end

-- =========================================================================
-- 2. SOUND DATA
-- =========================================================================
local chargeSounds = {
    { "Interface\\AddOns\\FullSteel\\varian_colossus_smash01.ogg" },
    { "Interface\\AddOns\\FullSteel\\skill\\paladin\\charge.ogg" },
}
local chargeSoundNames = { [0] = "Random", [1] = "Colossus Smash", [2] = "Charge" }
local chargeRandomPool = {
    "Interface\\AddOns\\FullSteel\\varian_colossus_smash01.ogg",
    "Interface\\AddOns\\FullSteel\\skill\\paladin\\charge.ogg",
}
local lastSoundTime = {}
local soundCooldown = 1.5

local soundGroups = {
    battlecry = {
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\battlecry1.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\battlecry2.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\battlecry3.ogg",
    },
    battleorders = {
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\command1.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\command2.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\command3.ogg",
    },
    battlecommand = {
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\order1.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\order2.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\order3.ogg",
    },
    howl = {
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\howl1.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\howl2.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\howl3.ogg",
    },
    shout = {
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\shout1.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\shout2.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\shout3.ogg",
    },
    taunt = {
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\taunt1.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\taunt2.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\taunt3.ogg",
    },
    grunt = {
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\grunt101.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\grunt102.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\grunt103.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\grunt201.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\grunt202.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\grunt203.ogg"
    },
    warcry = {
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\warcry1.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\warcry2.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\warcry3.ogg",
    },
    corpseexplosion = {
        "Interface\\AddOns\\FullSteel\\skill\\necromancer\\corpseexplodecast.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\necromancer\\corpse_explode_1.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\necromancer\\corpse_explode_2.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\necromancer\\corpse_explode_3.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\necromancer\\corpse_explode_4.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\necromancer\\corpse_explode_5.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\necromancer\\corpse_explode_6.ogg",
    },
    lightningfury = {
        "Interface\\AddOns\\FullSteel\\skill\\amazon\\zeus1.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\amazon\\zeus2.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\amazon\\zeus3.ogg",
    },
    whirlwind = {
        "Interface\\AddOns\\FullSteel\\skill\\barbarian\\whirlwind1.ogg",
    },
    bladefury = {
        "Interface\\AddOns\\FullSteel\\skill\\assassin\\bladefury1.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\assassin\\bladefury2.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\assassin\\bladefury3.ogg",
        "Interface\\AddOns\\FullSteel\\skill\\assassin\\bladefuryhit.ogg",
    },
}

local shoutSounds = {}
local shoutSoundNames = { [0] = "Random" }

table.insert(shoutSounds, soundGroups.battlecry); shoutSoundNames[#shoutSounds] = "Battle Cry"
table.insert(shoutSounds, soundGroups.battleorders); shoutSoundNames[#shoutSounds] = "Battle Orders"
table.insert(shoutSounds, soundGroups.battlecommand); shoutSoundNames[#shoutSounds] = "Battle Command"
table.insert(shoutSounds, soundGroups.howl); shoutSoundNames[#shoutSounds] = "Howl"
table.insert(shoutSounds, soundGroups.shout); shoutSoundNames[#shoutSounds] = "Shout"
table.insert(shoutSounds, soundGroups.taunt); shoutSoundNames[#shoutSounds] = "Taunt"
table.insert(shoutSounds, soundGroups.warcry); shoutSoundNames[#shoutSounds] = "War Cry"

local executeSounds = {}
local executeSoundNames = { [0] = "Random" }

table.insert(executeSounds, soundGroups.corpseexplosion); executeSoundNames[#executeSounds] = "Corpse Explosion"
table.insert(executeSounds, soundGroups.lightningfury); executeSoundNames[#executeSounds] = "Lightning Fury"

local shoutRandomPool = {}
local shoutGroups = {soundGroups.battlecry, soundGroups.battleorders, soundGroups.battlecommand, soundGroups.howl, soundGroups.shout, soundGroups.taunt, soundGroups.warcry}
for _, group in ipairs(shoutGroups) do
    for _, sound in ipairs(group) do table.insert(shoutRandomPool, sound) end
end

local executeRandomPool = {}
for _, sound in ipairs(soundGroups.corpseexplosion) do table.insert(executeRandomPool, sound) end
for _, sound in ipairs(soundGroups.lightningfury) do table.insert(executeRandomPool, sound) end

local whirlwindSounds = {}
local whirlwindSoundNames = { [0] = "Random" }
table.insert(whirlwindSounds, soundGroups.whirlwind); whirlwindSoundNames[#whirlwindSounds] = "Whirlwind"
table.insert(whirlwindSounds, soundGroups.bladefury); whirlwindSoundNames[#whirlwindSounds] = "Blade Fury"

-- REND SOUNDS
local rendSounds = {
    { "Interface\\AddOns\\FullSteel\\skill\\new-rend-v3.ogg" },
    soundGroups.grunt,
}
local rendSoundNames = { [0] = "Random", [1] = "New Rend", [2] = "Grunt (Random)" }
local rendRandomPool = {
    "Interface\\AddOns\\FullSteel\\skill\\new-rend-v3.ogg",
    unpack(soundGroups.grunt)
}

local whirlwindRandomPool = {}
for _, sound in ipairs(soundGroups.whirlwind) do table.insert(whirlwindRandomPool, sound) end
for _, sound in ipairs(soundGroups.bladefury) do table.insert(whirlwindRandomPool, sound) end

local spellConfig = {
    ["Charge"] = { key = "charge", volume = "chargeVolume", soundKey = "chargeSound", sounds = chargeSounds, randomPool = chargeRandomPool },
    ["Intercept"] = { key = "intercept", volume = "chargeVolume", soundKey = "chargeSound", sounds = chargeSounds, randomPool = chargeRandomPool },
    ["Intervene"] = { key = "intervene", volume = "chargeVolume", soundKey = "chargeSound", sounds = chargeSounds, randomPool = chargeRandomPool },
    ["Execute"] = { key = "execute", volume = "executeVolume", soundKey = "executeSound", sounds = executeSounds, randomPool = executeRandomPool },
    ["Sudden Death"] = { key = "execute", volume = "executeVolume", soundKey = "executeSound", sounds = executeSounds, randomPool = executeRandomPool },
    ["Whirlwind"] = { key = "whirlwind", volume = "whirlwindVolume", soundKey = "whirlwindSound", sounds = whirlwindSounds, randomPool = whirlwindRandomPool },
    ["Battle Shout"] = { key = "battleshout", volume = "shoutVolume", soundKey = "battleshoutSound", sounds = shoutSounds, randomPool = shoutRandomPool },
    ["Demoralizing Shout"] = { key = "demoshout", volume = "shoutVolume", soundKey = "demoshoutSound", sounds = shoutSounds, randomPool = shoutRandomPool },
    ["Challenging Shout"] = { key = "challengeshout", volume = "shoutVolume", soundKey = "challengeshoutSound", sounds = shoutSounds, randomPool = shoutRandomPool },
    ["Intimidating Shout"] = { key = "intimidateshout", volume = "shoutVolume", soundKey = "intimidateshoutSound", sounds = shoutSounds, randomPool = shoutRandomPool },
    ["Taunt"] = { key = "taunt", volume = "shoutVolume", soundKey = "tauntSound", sounds = shoutSounds, randomPool = shoutRandomPool },
    ["Rend"] = { key = "rend", volume = "shoutVolume", soundKey = "rendSound", sounds = rendSounds, randomPool = rendRandomPool },
}

-- =========================================================================
-- 3. UI GENERATION
-- =========================================================================
function FullSteel_LoadUI()
    local panel = CreateFrame("Frame")
    panel.name = "FullSteel"
    panel.parent = nil
    panel:Hide()

    local scrollFrame = CreateFrame("ScrollFrame", "FullSteelScrollFrame", panel, "UIPanelScrollFrameTemplate")
    scrollFrame:SetPoint("TOPLEFT", 3, -4)
    scrollFrame:SetPoint("BOTTOMRIGHT", -27, 4)

    -- Mouse wheel scroll amount (higher = more scroll per tick)
    local scrollBar = _G.FullSteelScrollFrameScrollBar
    if scrollBar then
        scrollBar:SetValueStep(35)
        scrollBar.scrollStep = 35
    end

    local content = CreateFrame("Frame", nil, scrollFrame)
    content:SetSize(780, 1200)
    scrollFrame:SetScrollChild(content)

    -- QR code: interactive button
    local qrPadding = 60
    local qrButton = CreateFrame("Button", nil, panel)
    qrButton:SetSize(64, 64)
    qrButton:SetPoint("TOPRIGHT", panel, "TOPRIGHT", -qrPadding, -qrPadding + 10)
    
    local qrTexture = qrButton:CreateTexture(nil, "ARTWORK")
    qrTexture:SetTexture("Interface\\AddOns\\FullSteel\\qrcode.tga")
    qrTexture:SetAllPoints(qrButton)
    qrButton:SetNormalTexture(qrTexture)

    -- Opacity Support: 50% hidden normally, 100% on hover
    qrButton:SetAlpha(0.1)
    qrButton:SetScript("OnEnter", function(self) self:SetAlpha(1.0) end)
    qrButton:SetScript("OnLeave", function(self) self:SetAlpha(0.1) end)

    -- Click Support: Popup with text highlighted
    StaticPopupDialogs["FULLSTEEL_COPY_URL"] = {
        text = "Press Ctrl+C to copy URL:",
        button1 = "Close",
        hasEditBox = true,
        editBoxWidth = 250,
        OnShow = function(self)
            self.EditBox:SetText("https://maggew.com/wow")
            self.EditBox:SetFocus()
            self.EditBox:HighlightText()
        end,
        EditBoxOnEnterPressed = function(self) self:GetParent():Hide() end,
        EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
        timeout = 0,
        whileDead = true,
        hideOnEscape = true,
        preferredIndex = 3,
    }

    qrButton:SetScript("OnClick", function()
        StaticPopup_Show("FULLSTEEL_COPY_URL")
    end)

    -- Header: single title line
    local title = content:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    title:SetPoint("TOPLEFT", 20, -16)
    title:SetText("FullSteel by Maggew.com")
    title:SetTextColor(1, 1, 1)

    -- UI Helper Functions
    local function CreateAbilityRow(parent, yOffset, label, enableKey, soundKey, sounds, soundNames, volumeKey, randomPool)
        local cb = CreateFrame("CheckButton", nil, parent, "InterfaceOptionsCheckButtonTemplate")
        cb:SetPoint("TOPLEFT", 20, yOffset)
        cb.Text:SetText(label)
        cb.Text:SetWidth(180)
        cb.Text:SetJustifyH("LEFT")
        cb:SetChecked(db[enableKey])
        cb:SetScript("OnClick", function(self)
            db[enableKey] = self:GetChecked()
            FullSteelDB[enableKey] = self:GetChecked()
        end)

        if sounds and #sounds > 1 and soundKey and soundNames then
            local dropdown = CreateFrame("Frame", nil, parent, "UIDropDownMenuTemplate")
            dropdown:SetPoint("LEFT", cb, "RIGHT", 185, -2)
            UIDropDownMenu_SetWidth(dropdown, 140)
            dropdown:EnableMouse(true)
            dropdown:SetScript("OnMouseDown", function() ToggleDropDownMenu(1, nil, dropdown) end)

            UIDropDownMenu_Initialize(dropdown, function(self)
                local randomInfo = UIDropDownMenu_CreateInfo()
                randomInfo.text = "Random"
                randomInfo.func = function()
                    db[soundKey] = 0
                    FullSteelDB[soundKey] = 0
                    UIDropDownMenu_SetText(dropdown, "Random")
                    if randomPool and #randomPool > 0 then
                        local randomSound = randomPool[math.random(1, #randomPool)]
                        local vol = db[volumeKey] or 100
                        PlaySafeSound(randomSound, vol)
                    end
                end
                randomInfo.checked = (db[soundKey] == 0)
                UIDropDownMenu_AddButton(randomInfo)

                for i = 1, #sounds do
                    local info = UIDropDownMenu_CreateInfo()
                    info.text = soundNames[i]
                    info.func = function()
                        db[soundKey] = i
                        FullSteelDB[soundKey] = i
                        UIDropDownMenu_SetText(dropdown, soundNames[i])
                        local soundGroup = sounds[i]
                        if type(soundGroup) == "table" and #soundGroup > 0 then
                             local variant = soundGroup[math.random(1, #soundGroup)]
                             local vol = db[volumeKey] or 100
                             PlaySafeSound(variant, vol)
                        end
                    end
                    info.checked = (db[soundKey] == i)
                    UIDropDownMenu_AddButton(info)
                end
            end)
            UIDropDownMenu_SetText(dropdown, soundNames[db[soundKey]] or "Random")
        end
        return cb
    end

    local function CreateThreeColumnRow(parent, yOffset, label1, key1, label2, key2, label3, key3)
        local function makeCb(lbl, k, x, relativeTo)
            local cb = CreateFrame("CheckButton", nil, parent, "InterfaceOptionsCheckButtonTemplate")
            if relativeTo then cb:SetPoint("LEFT", relativeTo, "RIGHT", x, 0)
            else cb:SetPoint("TOPLEFT", 20, yOffset) end
            cb.Text:SetText(lbl)
            cb:SetChecked(db[k])
            cb:SetScript("OnClick", function(self)
                db[k] = self:GetChecked()
                FullSteelDB[k] = self:GetChecked()
            end)
            return cb
        end
        local cb1 = makeCb(label1, key1, 0, nil)
        local cb2 = makeCb(label2, key2, 120, cb1)
        local cb3 = makeCb(label3, key3, 120, cb2)
    end

    local function CreateVolumeDropdown(parent, yOffset, label, dbKey, testSounds)
        local container = CreateFrame("Frame", nil, parent)
        container:SetPoint("TOPLEFT", 20, yOffset)
        container:SetSize(400, 40)
        
        local labelText = container:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
        labelText:SetPoint("TOPLEFT", 0, 0)
        labelText:SetText(label)

        local dropdownName = "FullSteelVolumeDropdown_" .. dbKey
        local dropdown = CreateFrame("Frame", dropdownName, container, "UIDropDownMenuTemplate")
        dropdown:SetPoint("TOPLEFT", 0, -20)
        UIDropDownMenu_SetWidth(dropdown, 120)

        local button = _G[dropdownName .. "Button"]
        if button then
            button:SetHitRectInsets(0, 0, 0, 0)
            dropdown:EnableMouse(true)
            dropdown:SetScript("OnMouseDown", function() ToggleDropDownMenu(1, nil, dropdown) end)
        end

        local volumeOptions = {0, 25, 50, 75, 100}
        UIDropDownMenu_Initialize(dropdown, function(self)
            for _, vol in ipairs(volumeOptions) do
                local info = UIDropDownMenu_CreateInfo()
                info.text = vol .. "%"
                info.func = function()
                    db[dbKey] = vol
                    FullSteelDB[dbKey] = vol
                    UIDropDownMenu_SetText(dropdown, vol .. "%")
                end
                info.checked = (db[dbKey] == vol)
                UIDropDownMenu_AddButton(info)
            end
        end)
        UIDropDownMenu_SetText(dropdown, (db[dbKey] or 100) .. "%")

        if testSounds then
            local testBtn = CreateFrame("Button", nil, container, "UIPanelButtonTemplate")
            testBtn:SetPoint("LEFT", dropdown, "RIGHT", 10, 2)
            testBtn:SetSize(80, 22)
            testBtn:SetText("Test")
            testBtn:SetScript("OnClick", function()
                local sound
                if type(testSounds[1]) == "table" then
                     local g = testSounds[math.random(1, #testSounds)]
                     sound = g[math.random(1, #g)]
                else
                     sound = testSounds[math.random(1, #testSounds)]
                end
                local vol = db[dbKey] or 100
                PlaySafeSound(sound, vol)
                print("FullSteel: Testing sound at " .. vol .. "%")
            end)
        end
        return container
    end

    -- Build Layout (fixed y below header, equal spacing between sections)
    local sectionGap = 85  -- space between each section (Addon Controls, Ability Sounds, Volume Controls, Warrior Facts)
    local y = -50
    local controlsHeader = content:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    controlsHeader:SetPoint("TOPLEFT", 20, y)
    controlsHeader:SetText("Addon Controls")
    controlsHeader:SetTextColor(1, 0.82, 0)  -- yellow to match options section headers
    y = y - 35
    
    local masterToggle = CreateFrame("CheckButton", nil, content, "InterfaceOptionsCheckButtonTemplate")
    masterToggle:SetPoint("TOPLEFT", 20, y)
    masterToggle.Text:SetText("Enable FullSteel (Master Toggle)")
    masterToggle:SetChecked(db.enabled)
    masterToggle:SetScript("OnClick", function(self)
        db.enabled = self:GetChecked()
        FullSteelDB.enabled = self:GetChecked()
        print(db.enabled and "FullSteel: ENABLED" or "FullSteel: DISABLED")
    end)
    
    local masterDesc = content:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    masterDesc:SetPoint("TOPLEFT", masterToggle, "BOTTOMLEFT", 25, -2)
    masterDesc:SetText("Uncheck to completely disable all addon sounds")
    masterDesc:SetTextColor(0.7, 0.7, 0.7)
    y = y - 55

    local resetBtn = CreateFrame("Button", nil, content, "UIPanelButtonTemplate")
    resetBtn:SetPoint("TOPLEFT", 20, y); resetBtn:SetSize(120, 25); resetBtn:SetText("Reset to Defaults")
    resetBtn:SetScript("OnClick", function()
        for k, v in pairs(defaults) do db[k] = v end
        FullSteelDB = db
        ReloadUI()
    end)
    
    local debugCb = CreateFrame("CheckButton", nil, content, "InterfaceOptionsCheckButtonTemplate")
    debugCb:SetPoint("LEFT", resetBtn, "RIGHT", 40, 0)
    debugCb.Text:SetText("Debug Mode")
    debugCb:SetChecked(db.debug)
    debugCb:SetScript("OnClick", function(self)
        db.debug = self:GetChecked()
        FullSteelDB.debug = self:GetChecked()
    end)
    y = y - sectionGap

    local abilityHeader = content:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    abilityHeader:SetPoint("TOPLEFT", 20, y); abilityHeader:SetText("Ability Sounds")
    abilityHeader:SetTextColor(1, 0.82, 0)
    y = y - 40
    CreateAbilityRow(content, y, "Charge", "charge", "chargeSound", chargeSounds, chargeSoundNames, "chargeVolume", chargeRandomPool)
    y = y - 40
    -- Intercept and Intervene on sub-row with simple checkboxes (no dropdown repeating)
    local interceptCb = CreateFrame("CheckButton", nil, content, "InterfaceOptionsCheckButtonTemplate")
    interceptCb:SetPoint("TOPLEFT", 60, y) -- Indented
    interceptCb.Text:SetText("Intercept")
    interceptCb:SetChecked(db.intercept)
    interceptCb:SetScript("OnClick", function(self) db.intercept = self:GetChecked(); FullSteelDB.intercept = self:GetChecked() end)
    
    local interveneCb = CreateFrame("CheckButton", nil, content, "InterfaceOptionsCheckButtonTemplate")
    interveneCb:SetPoint("LEFT", interceptCb, "RIGHT", 120, 0)
    interveneCb.Text:SetText("Intervene")
    interveneCb:SetChecked(db.intervene)
    interveneCb:SetScript("OnClick", function(self) db.intervene = self:GetChecked(); FullSteelDB.intervene = self:GetChecked() end)
    y = y - 40
    CreateAbilityRow(content, y, "Execute", "execute", "executeSound", executeSounds, executeSoundNames, "executeVolume", executeRandomPool)
    y = y - 40
    CreateAbilityRow(content, y, "Battle Shout", "battleshout", "battleshoutSound", shoutSounds, shoutSoundNames, "shoutVolume", randomPool)
    y = y - 40
    CreateAbilityRow(content, y, "Demoralizing Shout", "demoshout", "demoshoutSound", shoutSounds, shoutSoundNames, "shoutVolume", randomPool)
    y = y - 40
    CreateAbilityRow(content, y, "Challenging Shout", "challengeshout", "challengeshoutSound", shoutSounds, shoutSoundNames, "shoutVolume", randomPool)
    y = y - 40
    CreateAbilityRow(content, y, "Intimidating Shout", "intimidateshout", "intimidateshoutSound", shoutSounds, shoutSoundNames, "shoutVolume", randomPool)
    y = y - 40
    CreateAbilityRow(content, y, "Taunt", "taunt", "tauntSound", shoutSounds, shoutSoundNames, "shoutVolume", randomPool)
    y = y - 40
    CreateAbilityRow(content, y, "Whirlwind", "whirlwind", "whirlwindSound", whirlwindSounds, whirlwindSoundNames, "whirlwindVolume", whirlwindRandomPool)
    y = y - 40
    -- REND
    CreateAbilityRow(content, y, "Rend", "rend", "rendSound", rendSounds, rendSoundNames, "shoutVolume", rendRandomPool)
    y = y - sectionGap

    local volumeHeader = content:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    volumeHeader:SetPoint("TOPLEFT", 20, y); volumeHeader:SetText("Volume Controls")
    volumeHeader:SetTextColor(1, 0.82, 0)
    y = y - 35
    CreateVolumeDropdown(content, y, "Charge/Intercept/Intervene", "chargeVolume", chargeSounds)
    y = y - 55
    CreateVolumeDropdown(content, y, "Execute", "executeVolume", executeSounds)
    y = y - 55
    CreateVolumeDropdown(content, y, "Whirlwind", "whirlwindVolume", whirlwindSounds)
    y = y - 55
    CreateVolumeDropdown(content, y, "Shouts", "shoutVolume", shoutSounds)
    y = y - sectionGap

    -- Warrior Facts (match Volume Controls style: same header + label font/size)
    local warriorFactsHeader = content:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    warriorFactsHeader:SetPoint("TOPLEFT", 20, y)
    warriorFactsHeader:SetText("Warrior Facts")
    warriorFactsHeader:SetTextColor(1, 0.82, 0)  -- matching yellow section header
    y = y - 35

local warriorFactsWidth = 480
    local facts = {
        "Rage is gained from damage dealt and damage taken.",
        "Execute has no cooldown.",
        "Demo shout is great for pulling stealth units out.",
        "Don't play Arms unless > 50ms.",
        "Learn mechanics so you can solve gear questions yourself.",
        "Stay behind when possible: back attacks avoid parries and blocks, so fewer wasted globals, more rage.",
        "White attacks can miss, be dodged, be glancing, crit, or hit; yellow (special) attacks behave like white but cannot glance.",
        "Prioritize Bloodthirst. With 30 rage and 2000 AP, Bloodthirst matches Execute damage.",
        "Mighty Rage Potion: every 2 minutes, grants 45–75 rage and +60 strength (+120 AP) for 20 seconds.",
        "Get on target: Charge or Intercept, then immediately hamstring and start white swings for rage.",
        "Use Heroic Strike sparingly, because it removes rage gain from your next swing; in PvP you want that rage for Pummel and Intercept..",
        "Pummel any big heal or Polymorph-like spell; do not trade Pummel for low-impact casts.",
        "Avoid spamming HS at low rage.",
        "Keep main instant (Bloodthirst/MS) on cooldown, as its DPR and AP scaling are the best for single target.",
        "Execute has the best DPR at low rage, but gets worse as you dump more rage into a single cast.",
        "Whirlwind: Hits up to 4 targets with your main-hand weapon.",
        "Flurry: 5 points gives 30% attack-speed for the next 3 swings after a crit; uptime.",
        "Heroic strike/cleave remove the offhand miss penalty while queued.",
        "Fury is the top Warrior DPS spec in TBC, and it focuses on dual-wielding.",
        "People like to make fun of Undead Warriors.",
        "Fury has very high cleave and AoE potential, and is often strongest in cleave.",
        "(3) into Improved Rend is not very exciting.",
        "Fury is extremely gear-dependent, and weak in early content.",
        "Once you go below 35% HP, never leave Defensive Stance in PVP."
    }

    for _, fact in ipairs(facts) do
        local bullet = content:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
        bullet:SetPoint("TOPLEFT", 20, y)
        bullet:SetText("•")
        bullet:SetTextColor(1, 1, 1)

        local text = content:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
        text:SetPoint("TOPLEFT", 35, y)
        text:SetWidth(warriorFactsWidth)
        text:SetJustifyH("LEFT")
        text:SetWordWrap(true)
        text:SetNonSpaceWrap(true)
        text:SetText(fact)
        text:SetTextColor(1, 1, 1)

        -- Calculate height for next item
        local height = text:GetStringHeight()
        y = y - height - 10
    end

    y = y - 20

    -- Special Thanks/Credits
    local creditsHeader = content:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    creditsHeader:SetPoint("TOPLEFT", 20, y)
    creditsHeader:SetText("Special Thanks/Credits")
    creditsHeader:SetTextColor(1, 0.82, 0)
    y = y - 35

    local creditsText = content:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
    creditsText:SetPoint("TOPLEFT", 20, y)
    creditsText:SetWidth(warriorFactsWidth + 15)
    creditsText:SetJustifyH("LEFT")
    creditsText:SetWordWrap(true)
    creditsText:SetText("Thanks to all the United Gamers homies for the inspiration and good vibes. Shoutout WUG. Shoutout Panda. Shoutout Haboon. Shoutout Goro. Shout Vallon. Shoutout IronPhill. Best for last. Shoutout Bzul. Bless Up.")
    creditsText:SetTextColor(1, 1, 1)

    panel:SetScript("OnShow", function(self) self:SetWidth(820); self:SetHeight(600) end)
    local category = Settings.RegisterCanvasLayoutCategory(panel, panel.name)
    category.ID = panel.name
    Settings.RegisterAddOnCategory(category)

    SLASH_FULLSTEEL1 = "/fullsteel"
    SLASH_FULLSTEEL2 = "/fs"
    SlashCmdList["FULLSTEEL"] = function(msg)
        msg = (msg or ""):lower():match("^%s*(.-)%s*$")
        if msg == "debug" then
            db.debug = not db.debug
            FullSteelDB.debug = db.debug
            print("FullSteel: debug " .. (db.debug and "ON" or "OFF"))
            return
        end
        if msg == "status" then
            print("FullSteel: Current saved settings:")
            print(" executeSound:", db.executeSound)
            print(" battleshoutSound:", db.battleshoutSound)
            return
        end
        Settings.OpenToCategory(category.ID)
    end
end

-- =========================================================================
-- 4. EVENT HANDLING
-- =========================================================================
local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:RegisterEvent("PLAYER_LOGIN")
eventFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")

eventFrame:SetScript("OnEvent", function(self, event, arg1, ...)
    -- Handle Init
    if event == "ADDON_LOADED" and arg1 == "FullSteel" then
        FullSteelDB = FullSteelDB or {}
        db = FullSteelDB
        
        -- Apply Defaults
        for k, v in pairs(defaults) do
            if db[k] == nil then db[k] = v end
        end

        if not uiLoaded and FullSteel_LoadUI then
             FullSteel_LoadUI()
             uiLoaded = true
        end
        
        print("|cFF00FF00FullSteel loaded.|r Type /fs to configure.")

    -- Handle Login
    elseif event == "PLAYER_LOGIN" then
        playerGUID = UnitGUID("player")

    -- Handle Combat
    elseif event == "COMBAT_LOG_EVENT_UNFILTERED" then
        if not db.enabled then return end
        
        -- Safe check for GUID (Just in case LOGIN didn't fire yet)
        if not playerGUID then playerGUID = UnitGUID("player") end

        local _, subevent, _, sourceGUID, _, _, _, _, _, _, _, spellId, spellName = CombatLogGetCurrentEventInfo()

        if sourceGUID ~= playerGUID then return end

        local isValidEvent = false
        if subevent == "SPELL_CAST_SUCCESS" then
            isValidEvent = true
        elseif (subevent == "SPELL_DAMAGE" or subevent == "SWING_DAMAGE") and spellName == "Execute" then
            isValidEvent = true
        end

        if not isValidEvent then return end

        if db.debug then print("FullSteel DEBUG:", subevent, spellName) end

        local config = spellConfig[spellName]
        if not config then return end

        if not db[config.key] then return end

        local currentTime = GetTime()
        local lastTime = lastSoundTime[spellName] or 0
        if currentTime - lastTime < soundCooldown then return end
        lastSoundTime[spellName] = currentTime

        local soundIndex = db[config.soundKey]
        local sound
        
        -- Sound Selection
        if not soundIndex or soundIndex == 0 then
             if config.randomPool and #config.randomPool > 0 then
                 sound = config.randomPool[math.random(1, #config.randomPool)]
             end
        else
             local soundGroup = config.sounds[soundIndex]
             if type(soundGroup) == "table" then
                  sound = soundGroup[math.random(1, #soundGroup)]
             else
                  sound = soundGroup
             end
        end

        local vol = db[config.volume] or 100
        PlaySafeSound(sound, vol)
    end
end)
