-- ============================================================================
-- File: ArenaCore/Core/Pages/CastBars.lua (CLEAN REBUILD)
-- Purpose: Clean rebuild of Cast Bars settings page with single source of truth
-- ============================================================================

local AC = _G.ArenaCore
if not AC then return end

local V = AC.Vanity

local function CastBarsHairlineGroupBox(group)
    if not group then return end

    local fill = group:CreateTexture(nil, "BACKGROUND", nil, 2)
    local bgColor = AC.COLORS and AC.COLORS.HEADER_BG or {0.102, 0.102, 0.102, 1}
    fill:SetColorTexture(bgColor[1], bgColor[2], bgColor[3], bgColor[4] or 1)
    fill:SetPoint("TOPLEFT", 1, -1)
    fill:SetPoint("BOTTOMRIGHT", -1, 1)
    group.__acFill = fill
    group.__acFillIsGroupBox = true

    local borderFrame = CreateFrame("Frame", nil, group)
    borderFrame:SetAllPoints(group)

    local uniqueLevel = group:GetFrameLevel() + 1
    if group:GetParent() then
        uniqueLevel = uniqueLevel + (group:GetFrameLevel() % 3)
    end
    borderFrame:SetFrameLevel(uniqueLevel)

    local purpleTop = borderFrame:CreateTexture(nil, "BORDER", nil, 1)
    purpleTop:SetColorTexture(0.545, 0.271, 1.000, 1)
    purpleTop:SetPoint("TOPLEFT", group, "TOPLEFT", 0, 0)
    purpleTop:SetPoint("TOPRIGHT", group, "TOPRIGHT", 0, 0)
    purpleTop:SetHeight(1)
    if purpleTop.SetSnapToPixelGrid then purpleTop:SetSnapToPixelGrid(true) end
    if purpleTop.SetTexelSnappingBias then purpleTop:SetTexelSnappingBias(0) end

    local grayTop = borderFrame:CreateTexture(nil, "BORDER", nil, 0)
    grayTop:SetColorTexture(0.278, 0.278, 0.278, 0.9)
    grayTop:SetPoint("TOPLEFT", group, "TOPLEFT", 0, -1)
    grayTop:SetPoint("TOPRIGHT", group, "TOPRIGHT", 0, -1)
    grayTop:SetHeight(1)

    local grayBottom = borderFrame:CreateTexture(nil, "BORDER", nil, 0)
    grayBottom:SetColorTexture(0.278, 0.278, 0.278, 0.9)
    grayBottom:SetPoint("BOTTOMLEFT", group, "BOTTOMLEFT", 0, 0)
    grayBottom:SetPoint("BOTTOMRIGHT", group, "BOTTOMRIGHT", 0, 0)
    grayBottom:SetHeight(1)

    local grayLeft = borderFrame:CreateTexture(nil, "BORDER", nil, 0)
    grayLeft:SetColorTexture(0.278, 0.278, 0.278, 0.9)
    grayLeft:SetPoint("TOPLEFT", group, "TOPLEFT", 0, 0)
    grayLeft:SetPoint("BOTTOMLEFT", group, "BOTTOMLEFT", 0, 0)
    grayLeft:SetWidth(1)

    local grayRight = borderFrame:CreateTexture(nil, "BORDER", nil, 0)
    grayRight:SetColorTexture(0.278, 0.278, 0.278, 0.9)
    grayRight:SetPoint("TOPRIGHT", group, "TOPRIGHT", 0, 0)
    grayRight:SetPoint("BOTTOMRIGHT", group, "BOTTOMRIGHT", 0, 0)
    grayRight:SetWidth(1)

    group.__acBorderFrame = borderFrame
end

-- SINGLE SOURCE OF TRUTH: All defaults come from AC.DEFAULTS.castBars
-- CRITICAL: Fallback values MUST match Init.lua DEFAULTS.castBars exactly
local function GetDefaults()
    return AC.DEFAULTS and AC.DEFAULTS.castBars or {
        positioning = { horizontal = -4, vertical = -86 },
        sizing = { scale = 87, width = 220, height = 24 },
        spellSchoolColors = false,  -- Disabled: Not possible in Midnight due to secret values
        backgroundStyle = "Arena Core",
        -- Modern cast bar defaults
        useModernCastbars = true,
        simpleCastbar = true,
        keepDefaultModernTextures = true,
        recolorCastbar = false,
        hideBorderShield = false,
        hideCastbarSpark = false,
        spellIcons = {
            enabled = true,
            positioning = { horizontal = -4, vertical = 0 },
            sizing = { scale = 121 }
        }
    }
end

-- Get current database values with proper fallbacks
local function GetDB()
    if not AC.DB or not AC.DB.profile then return GetDefaults() end
    return AC.DB.profile.castBars or GetDefaults()
end

-- Update cast bars immediately when settings change
local function RefreshCastBars()
    -- Call CastBars module RefreshLayout (handles Midnight cast bars)
    if AC.CastBars and AC.CastBars.RefreshLayout then
        AC.CastBars:RefreshLayout()
    end
    
    -- Also call legacy RefreshCastBarsLayout for compatibility
    if AC.RefreshCastBarsLayout then
        AC:RefreshCastBarsLayout()
    end
end

-- Clean slider creation with no initialization conflicts
local function CreateCleanSlider(parent, label, y, dbPath, min, max, isPct)
    local row = CreateFrame("Frame", nil, parent)
    row:SetPoint("TOPLEFT", 20, y)
    row:SetPoint("TOPRIGHT", -20, y)
    row:SetHeight(26)

    -- Label
    local labelText = AC:CreateStyledText(row, label, 11, AC.COLORS.TEXT_2, "OVERLAY", "")
    labelText:SetPoint("LEFT", 0, 0)
    labelText:SetWidth(70)
    labelText:SetJustifyH("LEFT")

    -- Create DOWN arrow button for fine adjustment
    local downBtn = CreateFrame("Button", nil, row)
    downBtn:SetSize(16, 16)
    downBtn:SetPoint("LEFT", labelText, "RIGHT", 6, 0)
    
    -- Down arrow styling
    local downBg = downBtn:CreateTexture(nil, "BACKGROUND")
    downBg:SetAllPoints()
    downBg:SetColorTexture(0.2, 0.2, 0.2, 0.8)
    
    local downBorder = downBtn:CreateTexture(nil, "BORDER") 
    downBorder:SetAllPoints()
    downBorder:SetColorTexture(0.4, 0.4, 0.4, 1)
    downBorder:SetPoint("TOPLEFT", 1, -1)
    downBorder:SetPoint("BOTTOMRIGHT", -1, 1)
    
    local downText = downBtn:CreateFontString(nil, "OVERLAY")
    downText:SetFont("Interface/AddOns/ArenaCore/Media/Fonts/arenacore.ttf", 12, "")
    downText:SetText("-")
    downText:SetTextColor(0.8, 0.8, 0.8, 1)
    downText:SetPoint("CENTER")

    -- Min/Max labels
    local minText = AC:CreateStyledText(row, isPct and (min .. "%") or tostring(min), 9, AC.COLORS.TEXT_MUTED, "OVERLAY", "")
    minText:SetPoint("LEFT", downBtn, "RIGHT", 6, 0)
    minText:SetWidth(25)
    minText:SetJustifyH("RIGHT")

    -- Value display
    local valueText = AC:CreateStyledText(row, "", 11, AC.COLORS.TEXT_2, "OVERLAY", "")
    valueText:SetWidth(70)
    valueText:SetJustifyH("CENTER")

    -- Get current value from database
    local db = GetDB()
    local keys = {}
    for k in string.gmatch(dbPath, "([^%.]+)") do
        table.insert(keys, k)
    end
    
    local currentValue = db
    for _, key in ipairs(keys) do
        currentValue = currentValue and currentValue[key]
    end
    
    -- Use default if no value exists
    local defaults = GetDefaults()
    local defaultValue = defaults
    for _, key in ipairs(keys) do
        defaultValue = defaultValue and defaultValue[key]
    end
    currentValue = currentValue or defaultValue or (isPct and 100 or 0)

    -- OnChange function - ONLY called by user interaction
    local function OnChange(value)
        local fullPath = "castBars." .. dbPath
        if AC.ProfileManager and AC.ProfileManager.SetSetting then
            AC.ProfileManager:SetSetting(fullPath, value)
        else
            -- Fallback: direct write
            AC.DB = AC.DB or _G.ArenaCoreDB or {}
            AC.DB.profile = AC.DB.profile or {}
            AC.DB.profile.castBars = AC.DB.profile.castBars or {}

            local target = AC.DB.profile.castBars
            for i = 1, #keys - 1 do
                target[keys[i]] = target[keys[i]] or {}
                target = target[keys[i]]
            end
            target[keys[#keys]] = value

            if _G.ArenaCoreDB then
                _G.ArenaCoreDB.profile = _G.ArenaCoreDB.profile or {}
                _G.ArenaCoreDB.profile.castBars = AC.DB.profile.castBars
            end
        end

        -- Update display
        if isPct then
            valueText:SetText(string.format("%.0f%%", value))
        else
            valueText:SetText(string.format("%.0f", value))
        end

        -- Refresh cast bars
        RefreshCastBars()
    end

    -- Create slider
    local slider = AC:CreateFlatSlider(row, 120, 18, min, max, currentValue, isPct, OnChange)
    slider:SetPoint("LEFT", minText, "RIGHT", 10, 0)

    -- Create UP arrow button for fine adjustment  
    local upBtn = CreateFrame("Button", nil, row)
    upBtn:SetSize(16, 16)
    upBtn:SetPoint("LEFT", slider, "RIGHT", 4, 0)
    
    -- Up arrow styling
    local upBg = upBtn:CreateTexture(nil, "BACKGROUND")
    upBg:SetAllPoints()
    upBg:SetColorTexture(0.2, 0.2, 0.2, 0.8)
    
    local upBorder = upBtn:CreateTexture(nil, "BORDER")
    upBorder:SetAllPoints() 
    upBorder:SetColorTexture(0.4, 0.4, 0.4, 1)
    upBorder:SetPoint("TOPLEFT", 1, -1)
    upBorder:SetPoint("BOTTOMRIGHT", -1, 1)
    
    local upText = upBtn:CreateFontString(nil, "OVERLAY")
    upText:SetFont("Interface/AddOns/ArenaCore/Media/Fonts/arenacore.ttf", 12, "")
    upText:SetText("+")
    upText:SetTextColor(0.8, 0.8, 0.8, 1)
    upText:SetPoint("CENTER")

    -- Max label
    local maxText = AC:CreateStyledText(row, isPct and (max .. "%") or tostring(max), 9, AC.COLORS.TEXT_MUTED, "OVERLAY", "")
    maxText:SetPoint("LEFT", upBtn, "RIGHT", 6, 0)
    maxText:SetWidth(20)
    maxText:SetJustifyH("LEFT")

    -- Position value text
    valueText:SetPoint("LEFT", maxText, "RIGHT", 8, 0)

    -- Initialize display WITHOUT calling OnChange
    if isPct then
        valueText:SetText(string.format("%.0f%%", currentValue))
    else
        valueText:SetText(string.format("%.0f", currentValue))
    end

    -- Down arrow click handler
    downBtn:SetScript("OnClick", function()
        local currentVal = slider.slider:GetValue()
        local increment = isPct and 1 or 1
        local newVal = math.max(min, currentVal - increment)
        slider.slider:SetValue(newVal)
    end)

    -- Up arrow click handler
    upBtn:SetScript("OnClick", function()
        local currentVal = slider.slider:GetValue()
        local increment = isPct and 1 or 1
        local newVal = math.min(max, currentVal + increment)
        slider.slider:SetValue(newVal)
    end)

    -- Arrow hover effects
    downBtn:SetScript("OnEnter", function()
        downBg:SetColorTexture(0.3, 0.3, 0.3, 0.9)
        downText:SetTextColor(1, 1, 1, 1)
    end)
    downBtn:SetScript("OnLeave", function()
        downBg:SetColorTexture(0.2, 0.2, 0.2, 0.8)
        downText:SetTextColor(0.8, 0.8, 0.8, 1)
    end)
    
    upBtn:SetScript("OnEnter", function()
        upBg:SetColorTexture(0.3, 0.3, 0.3, 0.9)
        upText:SetTextColor(1, 1, 1, 1)
    end)
    upBtn:SetScript("OnLeave", function()
        upBg:SetColorTexture(0.2, 0.2, 0.2, 0.8)
        upText:SetTextColor(0.8, 0.8, 0.8, 1)
    end)

    return row
end

-- Clean checkbox creation
local function CreateCleanCheckbox(parent, label, y, dbPath)
    local row = CreateFrame("Frame", nil, parent)
    row:SetPoint("TOPLEFT", 20, y)
    row:SetPoint("TOPRIGHT", -20, y)
    row:SetHeight(26)

    local labelText = AC:CreateStyledText(row, label, 12, AC.COLORS.TEXT_2, "OVERLAY", "")
    labelText:SetPoint("LEFT", 0, 0)

    -- Get current value
    local db = GetDB()
    local keys = {}
    for k in string.gmatch(dbPath, "([^%.]+)") do
        table.insert(keys, k)
    end
    
    -- If dbPath begins with "castBars.", we must read from profile root.
    -- GetDB() returns only the castBars table, so using keys that include "castBars"
    -- would incorrectly traverse castBars.castBars.*
    local readRoot = db
    local defaultsRoot = GetDefaults()
    if keys[1] == "castBars" then
        readRoot = (AC.DB and AC.DB.profile) or {}
        defaultsRoot = { castBars = GetDefaults() }
    end
    
    local currentValue = readRoot
    for _, key in ipairs(keys) do
        currentValue = currentValue and currentValue[key]
    end
    
    -- Use default if no value exists
    local defaultValue = defaultsRoot
    for _, key in ipairs(keys) do
        defaultValue = defaultValue and defaultValue[key]
    end
    -- CRITICAL FIX: Don't use 'or' operator with boolean values
    -- When currentValue is false, 'false or X' evaluates to X, which is wrong
    if currentValue == nil then
        currentValue = defaultValue
    end

    local function OnChange(value)
        if AC.ProfileManager and AC.ProfileManager.SetSetting then
            AC.ProfileManager:SetSetting(dbPath, value)
        else
            AC.DB.profile = AC.DB.profile or {}

            local target
            if keys[1] == "castBars" then
                target = AC.DB.profile
            else
                AC.DB.profile.castBars = AC.DB.profile.castBars or {}
                target = AC.DB.profile.castBars
            end
            for i = 1, #keys - 1 do
                target[keys[i]] = target[keys[i]] or {}
                target = target[keys[i]]
            end
            target[keys[#keys]] = value
        end

        -- Refresh cast bars
        RefreshCastBars()
    end

    local checkbox = AC:CreateFlatCheckbox(row, 20, currentValue, OnChange)
    checkbox:SetPoint("RIGHT", -25, 0)

    return row
end

-- Reset function that uses DEFAULTS
local function ResetToDefaults()
    -- Reset database to defaults
    AC.DB.profile = AC.DB.profile or {}
    AC.DB.profile.castBars = {}
    
    -- Deep copy defaults
    local defaults = GetDefaults()
    local function DeepCopy(tbl)
        if type(tbl) ~= "table" then return tbl end
        local out = {}
        for k, v in pairs(tbl) do out[k] = DeepCopy(v) end
        return out
    end
    
    AC.DB.profile.castBars = DeepCopy(defaults)
    
    -- Refresh cast bars
    RefreshCastBars()
    
    -- Refresh page to update all controls
    C_Timer.After(0.1, function()
        if AC.ShowPage and AC.currentPage == "CastBars" then
            AC:ShowPage("CastBars")
        end
    end)
end

-- Main page creation function
local function CreateCleanCastBarsPage(parent)
    local db = GetDB()

    if V and V.EnsureMottoStrip then V:EnsureMottoStrip(parent) end
    
    -- Create the top button bar
    local buttonBar = CreateFrame("Frame", nil, parent)
    if parent._mottoStrip then
        buttonBar:SetPoint("TOPLEFT", parent._mottoStrip, "BOTTOMLEFT", 2, -8)
        buttonBar:SetPoint("TOPRIGHT", parent._mottoStrip, "BOTTOMRIGHT", -2, -8)
    else
        buttonBar:SetPoint("TOPLEFT", 10, -52)
        buttonBar:SetPoint("TOPRIGHT", -10, -52)
    end
    buttonBar:SetHeight(40)

    local sBorder = AC:CreateFlatTexture(buttonBar, "BACKGROUND", 1, AC.COLORS.BORDER_LIGHT, 0.6)
    sBorder:SetAllPoints()
    local sFill = AC:CreateFlatTexture(buttonBar, "BACKGROUND", 2, AC.COLORS.INPUT_DARK, 1)
    sFill:SetPoint("TOPLEFT", 1, -1); sFill:SetPoint("BOTTOMRIGHT", -1, 1)

    local function CreateCastBarsSubTabButton(parentFrame, text, width, height)
        local COLORS = AC.COLORS or {}

        local btn = CreateFrame("Button", nil, parentFrame)
        btn:SetSize(width or 102, height or 30)
        btn:SetFrameLevel(parentFrame:GetFrameLevel() + 1)

        local bg = AC:CreateFlatTexture(btn, "BACKGROUND", 0, {0.06, 0.06, 0.06, 1}, 1)
        bg:SetAllPoints()
        btn.bg = bg

        local hover = AC:CreateFlatTexture(btn, "ARTWORK", 1, COLORS.BORDER_LIGHT or {0.278, 0.278, 0.278, 1}, 0.15)
        hover:SetAllPoints()
        hover:Hide()
        btn.hover = hover

        local glow = btn:CreateTexture(nil, "OVERLAY")
        glow:SetTexture("Interface\\AddOns\\ArenaCore\\Media\\UI\\tab-purple-matte.tga")
        glow:SetAllPoints()
        glow:SetBlendMode("ADD")
        glow:SetAlpha(0)
        btn.glow = glow

        local function CreateGlowLine()
            local t = btn:CreateTexture(nil, "OVERLAY")
            local c = COLORS.PRIMARY or {0.545, 0.271, 1.000, 1}
            t:SetColorTexture(c[1], c[2], c[3], 1)
            t:SetDrawLayer("OVERLAY")
            if t.SetSnapToPixelGrid then
                t:SetTexelSnappingBias(0)
                t:SetSnapToPixelGrid(false)
            end
            t:Hide()
            return t
        end

        local outlineTop = CreateGlowLine()
        outlineTop:SetPoint("TOPLEFT", btn, "TOPLEFT", 1, 0)
        outlineTop:SetPoint("TOPRIGHT", btn, "TOPRIGHT", -1, 0)
        outlineTop:SetHeight(1)

        local outlineBottom = CreateGlowLine()
        outlineBottom:SetPoint("BOTTOMLEFT", btn, "BOTTOMLEFT", 1, 1)
        outlineBottom:SetPoint("BOTTOMRIGHT", btn, "BOTTOMRIGHT", -1, 1)
        outlineBottom:SetHeight(1)

        local outlineLeft = CreateGlowLine()
        outlineLeft:SetPoint("TOPLEFT", btn, "TOPLEFT", 1, -1)
        outlineLeft:SetPoint("BOTTOMLEFT", btn, "BOTTOMLEFT", 1, 1)
        outlineLeft:SetWidth(1)

        local outlineRight = CreateGlowLine()
        outlineRight:SetPoint("TOPRIGHT", btn, "TOPRIGHT", -1, -1)
        outlineRight:SetPoint("BOTTOMRIGHT", btn, "BOTTOMRIGHT", -1, 1)
        outlineRight:SetWidth(1)

        btn.outlineTop = outlineTop
        btn.outlineBottom = outlineBottom
        btn.outlineLeft = outlineLeft
        btn.outlineRight = outlineRight

        local label = AC:CreateStyledText(btn, text or "", 11, (COLORS.TEXT_2 or {0.706, 0.706, 0.706, 1}), "OVERLAY", "")
        label:SetPoint("CENTER", 0, 0)
        btn.label = label

        btn.isSelected = false
        function btn:SetSelected(selected)
            self.isSelected = selected and true or false
            if self.isSelected then
                self.bg:SetColorTexture(0.11, 0.11, 0.11, 1)
                self.hover:Hide()
                self.outlineTop:Show()
                self.outlineBottom:Show()
                self.outlineLeft:Show()
                self.outlineRight:Show()
                if self.glow then
                    self.glow:SetAlpha(0.22)
                end
                self.label:SetTextColor((COLORS.TEXT and COLORS.TEXT[1]) or 1, (COLORS.TEXT and COLORS.TEXT[2]) or 1, (COLORS.TEXT and COLORS.TEXT[3]) or 1, 1)
            else
                self.bg:SetColorTexture(0.06, 0.06, 0.06, 1)
                self.outlineTop:Hide()
                self.outlineBottom:Hide()
                self.outlineLeft:Hide()
                self.outlineRight:Hide()
                if self.glow then
                    self.glow:SetAlpha(0)
                end
                self.label:SetTextColor((COLORS.TEXT_2 and COLORS.TEXT_2[1]) or 0.706, (COLORS.TEXT_2 and COLORS.TEXT_2[2]) or 0.706, (COLORS.TEXT_2 and COLORS.TEXT_2[3]) or 0.706, 1)
            end
        end

        btn:SetScript("OnEnter", function(selfBtn)
            if not selfBtn.isSelected then
                selfBtn.hover:Show()
                selfBtn.outlineTop:Show()
                selfBtn.outlineBottom:Show()
                selfBtn.outlineLeft:Show()
                selfBtn.outlineRight:Show()
                if selfBtn.glow then
                    selfBtn.glow:SetAlpha(0.22)
                end
                selfBtn.label:SetTextColor((COLORS.TEXT and COLORS.TEXT[1]) or 1, (COLORS.TEXT and COLORS.TEXT[2]) or 1, (COLORS.TEXT and COLORS.TEXT[3]) or 1, 1)
            end
        end)

        btn:SetScript("OnLeave", function(selfBtn)
            if not selfBtn.isSelected then
                selfBtn.hover:Hide()
                selfBtn.outlineTop:Hide()
                selfBtn.outlineBottom:Hide()
                selfBtn.outlineLeft:Hide()
                selfBtn.outlineRight:Hide()
                if selfBtn.glow then
                    selfBtn.glow:SetAlpha(0)
                end
                selfBtn.label:SetTextColor((COLORS.TEXT_2 and COLORS.TEXT_2[1]) or 0.706, (COLORS.TEXT_2 and COLORS.TEXT_2[2]) or 0.706, (COLORS.TEXT_2 and COLORS.TEXT_2[3]) or 0.706, 1)
            end
        end)

        return btn
    end

    local contentRoot = CreateFrame("Frame", nil, parent)
    contentRoot:SetPoint("TOPLEFT", buttonBar, "BOTTOMLEFT", 0, -10)
    contentRoot:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", 0, 0)

    local function EnsureContentFrame(key)
        parent.__castBarsContentFrames = parent.__castBarsContentFrames or {}
        if parent.__castBarsContentFrames[key] then
            return parent.__castBarsContentFrames[key]
        end
        local f = CreateFrame("Frame", nil, contentRoot)
        f:SetAllPoints(contentRoot)
        f:Hide()
        parent.__castBarsContentFrames[key] = f
        return f
    end

    local tabs = {}
    local selectedTab

    local function HideAllContent()
        if not parent.__castBarsContentFrames then return end
        for _, f in pairs(parent.__castBarsContentFrames) do
            if f and f.Hide then
                f:Hide()
            end
        end
    end

    local function SelectTab(key)
        selectedTab = key
        for k, t in pairs(tabs) do
            t:SetSelected(k == key)
        end
        HideAllContent()
        local f = EnsureContentFrame(key)
        f:Show()
        if key == "positioning" then
            if not f.__built then
                -- Group 1: GENERAL
                local groupSchools = CreateFrame("Frame", nil, f)
                groupSchools:SetPoint("TOPLEFT", f, "TOPLEFT", 18, -18)
                groupSchools:SetPoint("TOPRIGHT", f, "TOPRIGHT", -18, -18)
                groupSchools:SetHeight(140)
                CastBarsHairlineGroupBox(groupSchools)

                -- Warning icon (like Midnight notice)
                local warningIcon = groupSchools:CreateTexture(nil, "ARTWORK")
                warningIcon:SetSize(32, 32)
                warningIcon:SetPoint("TOPLEFT", 20, -20)
                warningIcon:SetAtlas("Crosshair_Important_128")
                warningIcon:SetVertexColor(1, 0.6, 0, 1)

                local infoText = AC:CreateStyledText(groupSchools, "IMPORTANT: SIMPLIFIED FEATURES", 14, {1, 0.6, 0, 1}, "OVERLAY", "Interface\\AddOns\\ArenaCore\\Media\\Fonts\\arenacore.ttf")
                infoText:SetPoint("LEFT", warningIcon, "RIGHT", 10, 0)
                infoText:SetJustifyH("LEFT")

                local descText = AC:CreateStyledText(groupSchools, "Cast bar features have been simplified to ensure stability while we work around Blizzard's new API restrictions. Advanced customization options will return in future updates as we continue to refine the experience. Thank you for your patience! ™", 11, {0.9, 0.9, 0.9, 1}, "OVERLAY", "Interface\\AddOns\\ArenaCore\\Media\\Fonts\\arenacore.ttf")
                descText:SetPoint("TOPLEFT", warningIcon, "BOTTOMLEFT", 0, -10)
                descText:SetPoint("TOPRIGHT", groupSchools, "TOPRIGHT", -20, -92)
                descText:SetJustifyH("LEFT")
                descText:SetJustifyV("TOP")
                if descText.SetWordWrap then descText:SetWordWrap(true) end
                descText:SetSpacing(2)

                -- Group 2: POSITIONING
                local groupPos = CreateFrame("Frame", nil, f)
                groupPos:SetPoint("TOP", groupSchools, "BOTTOM", 0, -12)
                groupPos:SetPoint("LEFT", groupSchools, "LEFT", 0, 0)
                groupPos:SetPoint("RIGHT", groupSchools, "RIGHT", 0, 0)
                groupPos:SetHeight(110)
                CastBarsHairlineGroupBox(groupPos)
                local titlePos = AC:CreateStyledText(groupPos, "POSITIONING", 13, AC.COLORS.PRIMARY, "OVERLAY", "")
                titlePos:SetPoint("TOPLEFT", 20, -18)

                AC:CreateEnhancedSliderRow(groupPos, "Horizontal", -50, "castBars.positioning.horizontal", "positioning_horizontal_fine")
                AC:CreateEnhancedSliderRow(groupPos, "Vertical", -80, "castBars.positioning.vertical", "positioning_vertical_fine")

                f.__built = true
            end
        elseif key == "sizing" then
            if not f.__built then
                local groupSize = CreateFrame("Frame", nil, f)
                groupSize:SetPoint("TOPLEFT", f, "TOPLEFT", 18, -18)
                groupSize:SetPoint("TOPRIGHT", f, "TOPRIGHT", -18, -18)
                groupSize:SetHeight(140)
                CastBarsHairlineGroupBox(groupSize)
                local titleSize = AC:CreateStyledText(groupSize, "SIZING", 13, AC.COLORS.PRIMARY, "OVERLAY", "")
                titleSize:SetPoint("TOPLEFT", 20, -18)

                AC:CreateEnhancedSliderRow(groupSize, "Scale", -50, "castBars.sizing.scale", "sizing_scale")
                AC:CreateEnhancedSliderRow(groupSize, "Width", -80, "castBars.sizing.width", "sizing_width")
                AC:CreateEnhancedSliderRow(groupSize, "Height", -110, "castBars.sizing.height", "sizing_height")

                f.__built = true
            end
        elseif key == "icons" then
            if not f.__built then
                local groupIcons = CreateFrame("Frame", nil, f)
                groupIcons:SetPoint("TOPLEFT", f, "TOPLEFT", 18, -18)
                groupIcons:SetPoint("TOPRIGHT", f, "TOPRIGHT", -18, -18)
                groupIcons:SetHeight(200)
                CastBarsHairlineGroupBox(groupIcons)
                local titleIcons = AC:CreateStyledText(groupIcons, "SPELL ICONS", 13, AC.COLORS.PRIMARY, "OVERLAY", "")
                titleIcons:SetPoint("TOPLEFT", 20, -18)

                AC:CreateEnhancedSliderRow(groupIcons, "Horizontal", -50, "castBars.spellIcons.positioning.horizontal", "positioning_horizontal_fine")
                AC:CreateEnhancedSliderRow(groupIcons, "Vertical", -80, "castBars.spellIcons.positioning.vertical", "positioning_vertical_fine")
                AC:CreateEnhancedSliderRow(groupIcons, "Scale", -110, "castBars.spellIcons.sizing.scale", "sizing_scale")
                CreateCleanCheckbox(groupIcons, "Enable", -140, "castBars.spellIcons.enabled")

                f.__built = true
            end
        end
    end

    local tabPos = CreateCastBarsSubTabButton(buttonBar, "Positioning", 110, 30)
    tabPos:SetPoint("LEFT", buttonBar, "LEFT", 18, 0)
    tabs.positioning = tabPos

    local tabSize = CreateCastBarsSubTabButton(buttonBar, "Sizing", 90, 30)
    tabSize:SetPoint("LEFT", tabPos, "RIGHT", 8, 0)
    tabs.sizing = tabSize

    local tabIcons = CreateCastBarsSubTabButton(buttonBar, "Spell Icons", 110, 30)
    tabIcons:SetPoint("LEFT", tabSize, "RIGHT", 8, 0)
    tabs.icons = tabIcons

    tabPos:SetScript("OnClick", function() SelectTab("positioning") end)
    tabSize:SetScript("OnClick", function() SelectTab("sizing") end)
    tabIcons:SetScript("OnClick", function() SelectTab("icons") end)

    SelectTab("positioning")
end

-- Register the clean page
AC:RegisterPage("CastBars", CreateCleanCastBarsPage)
