setfenv(1, VoiceOver)
Options = {}

local AceGUI = LibStub("AceGUI-3.0")
local AceConfigDialog = LibStub("AceConfigDialog-3.0")
local AceDBOptions = LibStub("AceDBOptions-3.0")

-- ============================================================
-- VALORES PREDETERMINADOS CENTRALIZADOS PARA ALTERNATIVEPORTRAIT
-- Todos los lugares deben usar estas constantes
-- ============================================================
AlternativePortraitDefaults = {
    -- Posiciones para eventos normales (Quests, Gossip, etc.)
    normal = {
        title = { x = -93, y = 1 },
        desc = { x = -40, y = -67 },
        icon = { x = -62, y = -16 },
        model = { x = -229, y = 1, size = 136 },
    },
    -- Posiciones para Gossip, Items, Dialogues y GameObjects
    itemsAndDialogues = {
        title = { x = -97, y = 16 },
        desc = { x = -68, y = -46 },
    },
}

------------------------------------------------------------
-- Construction of the options table for AceConfigDialog --

local function SortAceConfigOptions(a, b)
    return (a.order or 100) < (b.order or 100)
end

-- Needed to preserve order (modern AceGUI has support for custom sorting of dropdown items, but old versions don't)
local FRAME_STRATAS =
{
    "BACKGROUND",
    "LOW",
    "MEDIUM",
    "HIGH",
    "DIALOG",
}

local slashCommandsHandler = {}
function slashCommandsHandler:values(info)
    if not self.indexToName then
        self.indexToName = { "Nothing" }
        self.indexToCommand = { "" }
        self.commandToIndex = { [""] = 1 }
        for command, handler in Utils:Ordered(Options.table.args.SlashCommands.args, SortAceConfigOptions) do
            if not handler.dropdownHidden then
                table.insert(self.indexToName, handler.name)
                table.insert(self.indexToCommand, command)
                self.commandToIndex[command] = getn(self.indexToCommand)
            end
        end
    end
    return self.indexToName
end

function slashCommandsHandler:get(info)
    local config, key = info.arg()
    return self.commandToIndex[config[key]]
end

function slashCommandsHandler:set(info, value)
    local config, key = info.arg()
    config[key] = self.indexToCommand[value]
end

-- General Tab
---@type AceConfigOptionsTable
local GeneralTab =
{
    name = "General",
    type = "group",
    order = 10,
    args = {
        MinimapButton = {
            type = "group",
            order = 2,
            inline = true,
            name = "Minimap Button",
            args = {
                MinimapButtonShow = {
                    type = "toggle",
                    order = 1,
                    name = "Show Minimap Button",
                    get = function(info) return not Addon.db.profile.MinimapButton.LibDBIcon.hide end,
                    set = function(info, value)
                        Addon.db.profile.MinimapButton.LibDBIcon.hide = not value
                        if value then
                            LibStub("LibDBIcon-1.0"):Show("VoiceOver")
                        else
                            LibStub("LibDBIcon-1.0"):Hide("VoiceOver")
                        end
                    end,
                },
                MinimapButtonLock = {
                    type = "toggle",
                    order = 2,
                    name = "Lock Position",
                    get = function(info) return Addon.db.profile.MinimapButton.LibDBIcon.lock end,
                    set = function(info, value)
                        if value then
                            LibStub("LibDBIcon-1.0"):Lock("VoiceOver")
                        else
                            LibStub("LibDBIcon-1.0"):Unlock("VoiceOver")
                        end
                    end,
                },
                LineBreak1 = { type = "description", name = "", order = 3 },
                MinimapButtons = {
                    type = "group",
                    inline = true,
                    name = "",
                    handler = slashCommandsHandler,
                    args = {
                        MinimapButtonLeftClick = {
                            type = "select",
                            order = 4,
                            name = "Left Click",
                            desc = "Action performed by left-clicking the minimap button.",
                            values = "values",
                            get = "get",
                            set = "set",
                            arg = function(value) return Addon.db.profile.MinimapButton.Commands, "LeftButton" end,
                        },
                        MinimapButtonMiddleClick = {
                            type = "select",
                            order = 4,
                            name = "Middle Click",
                            desc = "Action performed by middle-clicking the minimap button.",
                            values = "values",
                            get = "get",
                            set = "set",
                            arg = function(value) return Addon.db.profile.MinimapButton.Commands, "MiddleButton" end,
                        },
                        MinimapButtonRightClick = {
                            type = "select",
                            order = 4,
                            name = "Right Click",
                            desc = "Action performed by right-clicking the minimap button.",
                            values = "values",
                            get = "get",
                            set = "set",
                            arg = function(value) return Addon.db.profile.MinimapButton.Commands, "RightButton" end,
                        }
                    }
                }
            }
        },
        Frame = {
            type = "group",
            order = 3,
            inline = true,
            name = "Frame",
            disabled = function(info) return Addon.db.profile.SoundQueueUI.HideFrame end,
            args = {
                LockFrame = {
                    type = "toggle",
                    order = 1,
                    name = "Lock Frame",
                    desc = "Prevent the frame from being moved or resized.",
                    get = function(info) return Addon.db.profile.SoundQueueUI.LockFrame end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.LockFrame = value
                        SoundQueueUI:RefreshConfig()
                    end,
                },
                ResetFrame = {
                    type = "execute",
                    order = 2,
                    name = "Reset Frame",
                    desc = "Resets frame position and size back to default.",
                    func = function(info)
                        SoundQueueUI.frame:Reset()
                    end,
                },
                LineBreak1 = { type = "description", name = "", order = 3 },
                FrameStrata = {
                    type = "select",
                    order = 5,
                    name = "Frame Strata",
                    desc =
                    "Changes the \"depth\" of the frame, determining which other frames will it overlap or fall behind.",
                    values = FRAME_STRATAS,
                    get = function(info)
                        for k, v in ipairs(FRAME_STRATAS) do
                            if v == Addon.db.profile.SoundQueueUI.FrameStrata then
                                return k;
                            end
                        end
                    end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.FrameStrata = FRAME_STRATAS[value]
                        SoundQueueUI.frame:SetFrameStrata(Addon.db.profile.SoundQueueUI.FrameStrata)
                    end,
                },
                FrameScale = {
                    type = "range",
                    order = 4,
                    name = "Frame Scale",
                    softMin = 0.5,
                    softMax = 2,
                    bigStep = 0.05,
                    isPercent = true,
                    get = function(info) return Addon.db.profile.SoundQueueUI.FrameScale end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.FrameScale = value
                        SoundQueueUI:RefreshConfig()
                    end,
                },
                LineBreak2 = { type = "description", name = "", order = 6 },
                HidePortrait = {
                    type = "toggle",
                    order = 7,
                    name = "Hide NPC Portrait",
                    desc = "Talking NPC portrait will not appear when voice over audio is played.\n\n" ..
                        Utils:ColorizeText(
                            "This might be useful when using other addons that replace the dialog experience, such as " ..
                            Utils:ColorizeText("Immersion", NORMAL_FONT_COLOR_CODE) .. ".",
                            GRAY_FONT_COLOR_CODE),
                    get = function(info) return Addon.db.profile.SoundQueueUI.HidePortrait end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.HidePortrait = value
                        SoundQueueUI:RefreshConfig()
                    end,
                },
                HideFrame = {
                    type = "toggle",
                    order = 8,
                    name = "Hide Entirely",
                    desc = "Play voiceovers without ever displaying the frame.",
                    disabled = false,
                    get = function(info) return Addon.db.profile.SoundQueueUI.HideFrame end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.HideFrame = value
                        SoundQueueUI:RefreshConfig()
                    end,
                },
            }
        },
        AdvancedPlayback = {
            type = "group",
            order = 3.5,
            inline = true,
            name = function()
                local iconString = "|TInterface\\AddOns\\AI_VoiceOver\\Textures\\UI-ChatIcon-Share:14:14:0:0|t"
                return iconString .. " Advanced Playback"
            end,
            args = {
                ObjectiveTrackerButton = {
                    type = "toggle",
                    order = 1,
                    name = "Show Objective Tracker Buttons",
                    desc = "Toggle visibility of play buttons in the Objective Tracker",
                    get = function(info) return Addon.db.profile.ShowObjectiveTrackerButtons end,
                    set = function(info, value)
                        Addon.db.profile.ShowObjectiveTrackerButtons = value
                        QuestOverlayUI:UpdateAllButtonsVisibility()
                    end,
                },
                ManualMode = {
                    type = "toggle",
                    order = 2,
                    name = "Play Manual Mode",
                    desc = "Disable automatic playback when interacting with NPCs",
                    get = function(info) return Addon.db.profile.ManualMode end,
                    set = function(info, value)
                        Addon.db.profile.ManualMode = value
                        print("ManualMode set to:", value) -- Debug
                    end,
                },
                ShowQuestFrameButton = {
                    type = "toggle",
                    order = 3,
                    name = "Show Quest Frame Button",
                    desc = "Show a button below Accept/Complete in the quest frame to manually play quest text",
                    get = function(info) return Addon.db.profile.ShowQuestFrameButton end,
                    set = function(info, value)
                        Addon.db.profile.ShowQuestFrameButton = value
                        if value then
                            -- Si se activa la opción, inicializamos el botón si aún no existe
                            if not QuestFrameAudioButton.playButton then
                                QuestFrameAudioButton:Initialize()
                            end
                        end
                        -- Actualizamos la visibilidad del botón
                        if QuestFrameAudioButton and QuestFrameAudioButton.UpdateButtonVisibility then
                            QuestFrameAudioButton:UpdateButtonVisibility()
                        else
                            DebugPrint("QuestFrameAudioButton no está disponible o no tiene UpdateButtonVisibility")
                        end
                    end,
                },
                EnableSoundControl = {
                    type = "toggle",
                    order = 4,
                    name = "Enable Sound Control",
                    desc = "Enable automatic volume adjustment for other sound channels when VoiceOver is playing",
                    get = function(info) return Addon.db.profile.EnableSoundControl end,
                    set = function(info, value)
                        Addon.db.profile.EnableSoundControl = value
                        if value then
                            Debug:Print("Sound Control Enabled", "SoundControlUI")
                            -- Aquí puedes añadir lógica adicional si es necesario
                        else
                            Debug:Print("Sound Control Disabled", "SoundControlUI")
                            -- Restaurar volúmenes si está deshabilitado
                            if SoundControlUI and SoundControlUI.RestoreVolumes then
                                SoundControlUI:RestoreVolumes()
                            end
                        end
                    end,
                },
            },
        },
        Audio = {
            type = "group",
            order = 4,
            inline = true,
            name = "Audio",
            args = {
                SoundChannel = {
                    type = "select",
                    width = 0.75,
                    order = 1,
                    name = "Sound Channel",
                    desc = "Controls which sound channel VoiceOver will play in.",
                    values = Enums.SoundChannel:GetValueToNameMap(),
                    get = function(info) return Addon.db.profile.Audio.SoundChannel end,
                    set = function(info, value)
                        Addon.db.profile.Audio.SoundChannel = value
                        SoundQueueUI:RefreshConfig()
                    end,
                },
                LineBreak = { type = "description", name = "", order = 2 },
                GossipFrequency = {
                    type = "select",
                    width = 1.1,
                    order = 3,
                    name = "NPC Greeting Playback Frequency",
                    desc = "Controls how often VoiceOver will play NPC greeting dialog.",
                    values = {
                        [Enums.GossipFrequency.Always] = "Always",
                        [Enums.GossipFrequency.OncePerQuestNPC] = "Play Once for Quest NPCs",
                        [Enums.GossipFrequency.OncePerNPC] = "Play Once for All NPCs",
                        [Enums.GossipFrequency.Never] = "Never",
                    },
                    get = function(info) return Addon.db.profile.Audio.GossipFrequency end,
                    set = function(info, value)
                        Addon.db.profile.Audio.GossipFrequency = value
                        SoundQueueUI:RefreshConfig()
                    end,
                },
                AutoToggleDialog = {
                    type = "toggle",
                    width = 2.25,
                    order = 4,
                    name = "Mute Vocal NPCs Greetings While VoiceOver is Playing",
                    desc = "While VoiceOver is playing, the Dialog channel will be muted.",
                    disabled = function()
                        return Addon.db.profile.Audio.SoundChannel == Enums.SoundChannel.Dialog
                    end,
                    get = function(info) return Addon.db.profile.Audio.AutoToggleDialog end,
                    set = function(info, value)
                        Addon.db.profile.Audio.AutoToggleDialog = value
                        SoundQueueUI:RefreshConfig()
                        if Addon.db.profile.Audio.AutoToggleDialog then
                            SetCVar("Sound_EnableDialog", 1)
                        end
                    end,
                },
                LineBreak2 = { type = "description", name = "", order = 5 },
                ToggleSyncToWindowState = {
                    type = "toggle",
                    order = 6,
                    width = 2,
                    name = "Sync Dialog to Window State",
                    desc = "VoiceOver dialog will automatically stop when the gossip/quest window is closed.",
                    get = function(info) return Addon.db.profile.Audio.StopAudioOnDisengage end,
                    set = function(info, value)
                        Addon.db.profile.Audio.StopAudioOnDisengage = value
                    end,
                },
            }
        },
        Debug = {
            type = "group",
            order = 5,
            inline = true,
            name = "Debugging Tools",
            args = {
                DebugEnabled = {
                    type = "toggle",
                    order = 1,
                    width = 1.25,
                    name = "Enable Debug Messages",
                    desc = "Enables printing of some \"useful\" debug messages to the chat window.",
                    get = function(info) return Addon.db.profile.DebugEnabled end,
                    set = function(info, value) Addon.db.profile.DebugEnabled = value end,
                }
            }
        }
    }
}

-- Visual Effects Tab
---@type AceConfigOptionsTable
local VisualEffectsTab = {
    name = "Visual Effects",
    type = "group",
    order = 15,
    args = {
        PortraitStyleGroup = {
            type = "group",
            order = 0,
            inline = true,
            name = "Portrait Style",
            args = {
                PortraitStyle = {
                    type = "select",
                    order = 1,
                    width = 1.5,
                    name = "Portrait Style",
                    desc = "Choose between the classic 3D portrait or the new Midnight style frame.",
                    values = {
                        [0] = "Classic (3D Portrait)",
                        [1] = "Midnight (Beta)",
                    },
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitStyle or 0 end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitStyle = value
                        SoundQueueUI:RefreshConfig()
                        if AlternativePortrait then
                            AlternativePortrait:RefreshConfig()
                        end
                    end,
                },
                StyleDescription = {
                    type = "description",
                    order = 2,
                    name = "\n|cff888888Classic: Shows the NPC 3D model in a circular frame.\nMidnight: Shows a cinematic-style frame with quest info and logo.|r\n",
                },
            }
        },
        MidnightControls = {
            type = "group",
            order = 0.5,
            inline = true,
            name = "Midnight Style Position Controls",
            hidden = function(info) return Addon.db.profile.SoundQueueUI.PortraitStyle ~= 1 end,
            args = {
                InfoText = {
                    type = "description",
                    order = 0,
                    name = "|cff00ff00Adjust the position of all Midnight style elements. You can also drag elements in-game with left-click.|r\n",
                },
                ResetButton = {
                    type = "execute",
                    order = 1,
                    name = "Reset All Positions",
                    desc = "Reset all element positions to default",
                    func = function()
                        Addon.db.profile.AlternativePortrait = {}
                        local defaults = AlternativePortraitDefaults.normal
                        if AlternativePortrait and AlternativePortrait.frame then
                            -- Reset main frame
                            AlternativePortrait.frame:ClearAllPoints()
                            AlternativePortrait.frame:SetPoint("CENTER", UIParent, "CENTER", 0, -150)
                            
                            -- Reset model frame
                            if AlternativePortrait.frame.modelFrame then
                                AlternativePortrait.frame.modelFrame:ClearAllPoints()
                                AlternativePortrait.frame.modelFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", defaults.model.x, defaults.model.y)
                                AlternativePortrait.frame.modelFrame:SetSize(defaults.model.size, defaults.model.size)
                            end
                            
                            -- Reset title frame
                            if AlternativePortrait.frame.titleFrame then
                                AlternativePortrait.frame.titleFrame:ClearAllPoints()
                                AlternativePortrait.frame.titleFrame:SetPoint("LEFT", AlternativePortrait.frame, "CENTER", defaults.title.x, defaults.title.y)
                                AlternativePortrait.frame.titleFrame:SetSize(330, 60)
                            end
                            
                            -- Reset description frame
                            if AlternativePortrait.frame.descFrame then
                                AlternativePortrait.frame.descFrame:ClearAllPoints()
                                AlternativePortrait.frame.descFrame:SetPoint("LEFT", AlternativePortrait.frame, "CENTER", defaults.desc.x, defaults.desc.y)
                                AlternativePortrait.frame.descFrame:SetSize(280, 120)
                            end
                            
                            -- Reset icon frame
                            if AlternativePortrait.frame.iconFrame then
                                AlternativePortrait.frame.iconFrame:ClearAllPoints()
                                AlternativePortrait.frame.iconFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", defaults.icon.x, defaults.icon.y)
                                AlternativePortrait.frame.iconFrame:SetSize(26, 26)
                            end
                            
                            -- Reset logo frame
                            if AlternativePortrait.frame.logoFrame then
                                AlternativePortrait.frame.logoFrame:ClearAllPoints()
                                AlternativePortrait.frame.logoFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", -234, -71)
                                AlternativePortrait.frame.logoFrame:SetSize(126, 126)
                            end
                            
                            -- Reset background frame
                            if AlternativePortrait.frame.bgFrame then
                                AlternativePortrait.frame.bgFrame:ClearAllPoints()
                                AlternativePortrait.frame.bgFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", -229, 0)
                                AlternativePortrait.frame.bgFrame:SetSize(150, 150)
                            end
                            
                            print("|cFF00FF00[VoiceOver]|r Midnight style positions reset to default")
                        end
                    end,
                },
                LineBreak0 = { type = "description", name = "", order = 2 },
                
                -- General Settings Header
                GeneralHeader = {
                    type = "header",
                    order = 5,
                    name = "General Settings",
                },
                FrameScale = {
                    type = "range",
                    order = 6,
                    name = "Frame Scale",
                    desc = "Scale the entire Midnight frame",
                    min = 0.5,
                    max = 2.0,
                    step = 0.05,
                    isPercent = true,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.frameScale) or 1.0
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.frameScale = value
                        if AlternativePortrait and AlternativePortrait.frame then
                            AlternativePortrait.frame:SetScale(value)
                        end
                    end,
                },
                ShowLogo = {
                    type = "toggle",
                    order = 7,
                    name = "Show Logo",
                    desc = "Show or hide the VoiceOver logo",
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        if config and config.showLogo ~= nil then
                            return config.showLogo
                        end
                        return true -- Default: show logo
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.showLogo = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.logoFrame then
                            if value then
                                AlternativePortrait.frame.logoFrame:Show()
                            else
                                AlternativePortrait.frame.logoFrame:Hide()
                            end
                        end
                    end,
                },
                LineBreak1 = { type = "description", name = "", order = 9 },
                
                -- Model 3D Controls
                ModelHeader = {
                    type = "header",
                    order = 10,
                    name = "3D Model Position",
                },
                ModelX = {
                    type = "range",
                    order = 11,
                    name = "Model X Position",
                    desc = "Horizontal position of the 3D model",
                    min = -400,
                    max = 400,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.modelPosition and config.modelPosition.x) or AlternativePortraitDefaults.normal.model.x
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.modelPosition = Addon.db.profile.AlternativePortrait.modelPosition or {}
                        Addon.db.profile.AlternativePortrait.modelPosition.x = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.modelFrame then
                            local y = Addon.db.profile.AlternativePortrait.modelPosition.y or AlternativePortraitDefaults.normal.model.y
                            AlternativePortrait.frame.modelFrame:ClearAllPoints()
                            AlternativePortrait.frame.modelFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", value, y)
                        end
                    end,
                },
                ModelY = {
                    type = "range",
                    order = 12,
                    name = "Model Y Position",
                    desc = "Vertical position of the 3D model",
                    min = -200,
                    max = 200,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.modelPosition and config.modelPosition.y) or AlternativePortraitDefaults.normal.model.y
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.modelPosition = Addon.db.profile.AlternativePortrait.modelPosition or {}
                        Addon.db.profile.AlternativePortrait.modelPosition.y = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.modelFrame then
                            local x = Addon.db.profile.AlternativePortrait.modelPosition.x or AlternativePortraitDefaults.normal.model.x
                            AlternativePortrait.frame.modelFrame:ClearAllPoints()
                            AlternativePortrait.frame.modelFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", x, value)
                        end
                    end,
                },
                ModelSize = {
                    type = "range",
                    order = 13,
                    name = "Model Size",
                    desc = "Size of the 3D model frame",
                    min = 50,
                    max = 300,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.modelSize) or AlternativePortraitDefaults.normal.model.size
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.modelSize = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.modelFrame then
                            AlternativePortrait.frame.modelFrame:SetSize(value, value)
                        end
                    end,
                },
                LineBreak1 = { type = "description", name = "", order = 14 },
                
                -- Title (NPC Name) Controls
                TitleHeader = {
                    type = "header",
                    order = 20,
                    name = "NPC Name Position",
                },
                TitleX = {
                    type = "range",
                    order = 21,
                    name = "Title X Position",
                    desc = "Horizontal position of the NPC name",
                    min = -400,
                    max = 400,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.titlePosition and config.titlePosition.x) or -93
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.titlePosition = Addon.db.profile.AlternativePortrait.titlePosition or {}
                        Addon.db.profile.AlternativePortrait.titlePosition.x = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.titleFrame then
                            local y = Addon.db.profile.AlternativePortrait.titlePosition.y or 16
                            AlternativePortrait.frame.titleFrame:ClearAllPoints()
                            AlternativePortrait.frame.titleFrame:SetPoint("LEFT", AlternativePortrait.frame, "CENTER", value, y)
                        end
                    end,
                },
                TitleY = {
                    type = "range",
                    order = 22,
                    name = "Title Y Position",
                    desc = "Vertical position of the NPC name",
                    min = -200,
                    max = 200,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.titlePosition and config.titlePosition.y) or 16
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.titlePosition = Addon.db.profile.AlternativePortrait.titlePosition or {}
                        Addon.db.profile.AlternativePortrait.titlePosition.y = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.titleFrame then
                            local x = Addon.db.profile.AlternativePortrait.titlePosition.x or -93
                            AlternativePortrait.frame.titleFrame:ClearAllPoints()
                            AlternativePortrait.frame.titleFrame:SetPoint("LEFT", AlternativePortrait.frame, "CENTER", x, value)
                        end
                    end,
                },
                LineBreak2 = { type = "description", name = "", order = 23 },
                
                -- Description (Quest Title) Controls
                DescHeader = {
                    type = "header",
                    order = 30,
                    name = "Quest Title Position",
                },
                DescX = {
                    type = "range",
                    order = 31,
                    name = "Quest Title X Position",
                    desc = "Horizontal position of the quest title",
                    min = -400,
                    max = 400,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.descPosition and config.descPosition.x) or -40
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.descPosition = Addon.db.profile.AlternativePortrait.descPosition or {}
                        Addon.db.profile.AlternativePortrait.descPosition.x = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.descFrame then
                            local y = Addon.db.profile.AlternativePortrait.descPosition.y or -22
                            AlternativePortrait.frame.descFrame:ClearAllPoints()
                            AlternativePortrait.frame.descFrame:SetPoint("LEFT", AlternativePortrait.frame, "CENTER", value, y)
                        end
                    end,
                },
                DescY = {
                    type = "range",
                    order = 32,
                    name = "Quest Title Y Position",
                    desc = "Vertical position of the quest title",
                    min = -200,
                    max = 200,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.descPosition and config.descPosition.y) or -22
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.descPosition = Addon.db.profile.AlternativePortrait.descPosition or {}
                        Addon.db.profile.AlternativePortrait.descPosition.y = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.descFrame then
                            local x = Addon.db.profile.AlternativePortrait.descPosition.x or -40
                            AlternativePortrait.frame.descFrame:ClearAllPoints()
                            AlternativePortrait.frame.descFrame:SetPoint("LEFT", AlternativePortrait.frame, "CENTER", x, value)
                        end
                    end,
                },
                LineBreak3 = { type = "description", name = "", order = 33 },
                
                -- Icon Controls
                IconHeader = {
                    type = "header",
                    order = 40,
                    name = "Quest Icon Position",
                },
                IconX = {
                    type = "range",
                    order = 41,
                    name = "Icon X Position",
                    desc = "Horizontal position of the quest icon",
                    min = -400,
                    max = 400,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.iconPosition and config.iconPosition.x) or -62
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.iconPosition = Addon.db.profile.AlternativePortrait.iconPosition or {}
                        Addon.db.profile.AlternativePortrait.iconPosition.x = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.iconFrame then
                            local y = Addon.db.profile.AlternativePortrait.iconPosition.y or -22
                            AlternativePortrait.frame.iconFrame:ClearAllPoints()
                            AlternativePortrait.frame.iconFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", value, y)
                        end
                    end,
                },
                IconY = {
                    type = "range",
                    order = 42,
                    name = "Icon Y Position",
                    desc = "Vertical position of the quest icon",
                    min = -200,
                    max = 200,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.iconPosition and config.iconPosition.y) or -22
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.iconPosition = Addon.db.profile.AlternativePortrait.iconPosition or {}
                        Addon.db.profile.AlternativePortrait.iconPosition.y = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.iconFrame then
                            local x = Addon.db.profile.AlternativePortrait.iconPosition.x or -62
                            AlternativePortrait.frame.iconFrame:ClearAllPoints()
                            AlternativePortrait.frame.iconFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", x, value)
                        end
                    end,
                },
                LineBreak4 = { type = "description", name = "", order = 43 },
                
                -- Logo Controls
                LogoHeader = {
                    type = "header",
                    order = 50,
                    name = "Logo Position",
                },
                LogoX = {
                    type = "range",
                    order = 51,
                    name = "Logo X Position",
                    desc = "Horizontal position of the logo",
                    min = -400,
                    max = 400,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.logoPosition and config.logoPosition.x) or -234
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.logoPosition = Addon.db.profile.AlternativePortrait.logoPosition or {}
                        Addon.db.profile.AlternativePortrait.logoPosition.x = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.logoFrame then
                            local y = Addon.db.profile.AlternativePortrait.logoPosition.y or -71
                            AlternativePortrait.frame.logoFrame:ClearAllPoints()
                            AlternativePortrait.frame.logoFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", value, y)
                        end
                    end,
                },
                LogoY = {
                    type = "range",
                    order = 52,
                    name = "Logo Y Position",
                    desc = "Vertical position of the logo",
                    min = -200,
                    max = 200,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.logoPosition and config.logoPosition.y) or -71
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.logoPosition = Addon.db.profile.AlternativePortrait.logoPosition or {}
                        Addon.db.profile.AlternativePortrait.logoPosition.y = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.logoFrame then
                            local x = Addon.db.profile.AlternativePortrait.logoPosition.x or -234
                            AlternativePortrait.frame.logoFrame:ClearAllPoints()
                            AlternativePortrait.frame.logoFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", x, value)
                        end
                    end,
                },
                LineBreak5 = { type = "description", name = "", order = 53 },
                
                -- Background Controls
                BgHeader = {
                    type = "header",
                    order = 60,
                    name = "Background Position",
                },
                BgX = {
                    type = "range",
                    order = 61,
                    name = "Background X Position",
                    desc = "Horizontal position of the background",
                    min = -400,
                    max = 400,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.bgPosition and config.bgPosition.x) or -229
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.bgPosition = Addon.db.profile.AlternativePortrait.bgPosition or {}
                        Addon.db.profile.AlternativePortrait.bgPosition.x = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.bgFrame then
                            local y = Addon.db.profile.AlternativePortrait.bgPosition.y or 0
                            AlternativePortrait.frame.bgFrame:ClearAllPoints()
                            AlternativePortrait.frame.bgFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", value, y)
                        end
                    end,
                },
                BgY = {
                    type = "range",
                    order = 62,
                    name = "Background Y Position",
                    desc = "Vertical position of the background",
                    min = -200,
                    max = 200,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.bgPosition and config.bgPosition.y) or 0
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.bgPosition = Addon.db.profile.AlternativePortrait.bgPosition or {}
                        Addon.db.profile.AlternativePortrait.bgPosition.y = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.bgFrame then
                            local x = Addon.db.profile.AlternativePortrait.bgPosition.x or -229
                            AlternativePortrait.frame.bgFrame:ClearAllPoints()
                            AlternativePortrait.frame.bgFrame:SetPoint("CENTER", AlternativePortrait.frame, "CENTER", x, value)
                        end
                    end,
                },
                BgSize = {
                    type = "range",
                    order = 63,
                    name = "Background Size",
                    desc = "Size of the background frame",
                    min = 50,
                    max = 300,
                    step = 1,
                    get = function(info)
                        local config = Addon.db.profile.AlternativePortrait
                        return (config and config.bgSize) or 150
                    end,
                    set = function(info, value)
                        Addon.db.profile.AlternativePortrait = Addon.db.profile.AlternativePortrait or {}
                        Addon.db.profile.AlternativePortrait.bgSize = value
                        if AlternativePortrait and AlternativePortrait.frame and AlternativePortrait.frame.bgFrame then
                            AlternativePortrait.frame.bgFrame:SetSize(value, value)
                        end
                    end,
                },
            }
        },
        PortraitBackground = {
            type = "group",
            order = 1,
            inline = true,
            name = "Portrait Background",
            hidden = function(info) return Addon.db.profile.SoundQueueUI.PortraitStyle == 1 end,
            disabled = function(info) return Addon.db.profile.SoundQueueUI.HideFrame or Addon.db.profile.SoundQueueUI.HidePortrait end,
            args = {
                BackgroundTexture = {
                    type = "select",
                    order = 1,
                    name = "Background Style",
                    desc = "Choose the background texture for the portrait frame.",
                    values = {
                        [0] = "Style 0",
                        [1] = "Style 1",
                        [2] = "Style 2",
                        [3] = "Style 3",
                    },
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitBackgroundTexture end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitBackgroundTexture = value
                        SoundQueueUI:RefreshConfig()
                    end,
                },
                LineBreak = { type = "description", name = "", order = 2 },
                Preview = {
                    type = "execute",
                    order = 3,
                    name = "",
                    image = function()
                        local textureIndex = Addon.db.profile.SoundQueueUI.PortraitBackgroundTexture or 0
                        return [[Interface\AddOns\AI_VoiceOver\Textures\PortraitFrameBackground]] .. textureIndex
                    end,
                    imageWidth = 120,
                    imageHeight = 120,
                    func = function() end,
                },
            }
        },
        PortraitFrameStyle = {
            type = "group",
            order = 2,
            inline = true,
            name = "Portrait Frame Style",
            hidden = function(info) return Addon.db.profile.SoundQueueUI.PortraitStyle == 1 end,
            disabled = function(info) return Addon.db.profile.SoundQueueUI.HideFrame or Addon.db.profile.SoundQueueUI.HidePortrait end,
            args = {
                FrameAtlas = {
                    type = "select",
                    order = 1,
                    name = "Frame Style",
                    desc = "Choose the frame border and button style for the portrait.",
                    values = {
                        [1] = "Style 1",
                        [2] = "Style 2",
                        [3] = "Style 3",
                    },
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitFrameAtlas end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitFrameAtlas = value
                        SoundQueueUI:RefreshConfig()
                    end,
                },
                LineBreak = { type = "description", name = "", order = 2 },
                PreviewAtlas = {
                    type = "execute",
                    order = 3,
                    name = "",
                    image = function()
                        local atlasIndex = Addon.db.profile.SoundQueueUI.PortraitFrameAtlas or 0
                        local atlasPath = [[Interface\AddOns\AI_VoiceOver\Textures\PortraitFrameAtlas]]
                        if atlasIndex > 0 then
                            atlasPath = atlasPath .. atlasIndex
                        end
                        return atlasPath
                    end,
                    imageWidth = 120,
                    imageHeight = 120,
                    func = function() end,
                },
            }
        },
        PortraitEffectSettings = {
            type = "group",
            order = 3,
            inline = true,
            name = "Portrait Visual Effect",
            hidden = function(info) return Addon.db.profile.SoundQueueUI.PortraitStyle == 1 end,
            disabled = function(info) return Addon.db.profile.SoundQueueUI.HideFrame or Addon.db.profile.SoundQueueUI.HidePortrait end,
            args = {
                EffectEnabled = {
                    type = "toggle",
                    order = 0,
                    name = "Enable Visual Effect",
                    desc = "Enable or disable the visual effect overlay on the portrait",
                    width = "full",
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitEffectEnabled end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitEffectEnabled = value
                        if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait and SoundQueueUI.frame.portrait.effectModel then
                            local effectModel = SoundQueueUI.frame.portrait.effectModel
                            if value then
                                effectModel:Show()
                            else
                                effectModel:Hide()
                            end
                        end
                    end,
                },
                LineBreak0 = { type = "description", name = "", order = 0.5 },
                EffectFileID = {
                    type = "input",
                    order = 1,
                    name = "Effect FileDataID",
                    desc = "Enter the FileDataID of the visual effect model (e.g., 5868339 for green infusion)",
                    width = "full",
                    get = function(info) return tostring(Addon.db.profile.SoundQueueUI.PortraitEffectFileID or 5868339) end,
                    set = function(info, value)
                        local fileID = tonumber(value)
                        if fileID and fileID > 0 then
                            Addon.db.profile.SoundQueueUI.PortraitEffectFileID = fileID
                            -- Reload the effect model with new FileDataID
                            if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait and SoundQueueUI.frame.portrait.effectModel then
                                local effectModel = SoundQueueUI.frame.portrait.effectModel
                                local success = pcall(effectModel.SetModel, effectModel, fileID)
                                if success then
                                    effectModel:SetPortraitZoom(0)
                                    effectModel:ClearTransform()
                                    effectModel:SetPosition(0, 0, 0)
                                    effectModel:SetFacing(0)
                                    effectModel:SetAnimation(0)
                                    local effectScale = Addon.db.profile.SoundQueueUI.PortraitEffectScale or 1.0
                                    effectModel:SetScale(effectScale)
                                    print("|cFF00FF00[VoiceOver]|r Effect model updated to FileDataID:", fileID)
                                else
                                    print("|cFFFF0000[VoiceOver]|r Failed to load FileDataID:", fileID)
                                end
                            end
                        else
                            print("|cFFFF0000[VoiceOver]|r Invalid FileDataID. Please enter a valid number.")
                        end
                    end,
                },
                LineBreak1 = { type = "description", name = "", order = 2 },
                EffectDetached = {
                    type = "toggle",
                    order = 3,
                    name = "Detach Effect from Portrait",
                    desc = "When enabled, the effect can be moved independently from the portrait frame",
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitEffectDetached or false end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitEffectDetached = value
                        if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait and SoundQueueUI.frame.portrait.effectModel then
                            local effectModel = SoundQueueUI.frame.portrait.effectModel
                            local portrait = SoundQueueUI.frame.portrait
                            if value then
                                -- Detach: make it movable
                                effectModel:ClearAllPoints()
                                effectModel:SetParent(UIParent)
                                effectModel:SetMovable(true)
                                effectModel:EnableMouse(true)
                                effectModel:RegisterForDrag("LeftButton")
                                effectModel:SetScript("OnDragStart", function(self) self:StartMoving() end)
                                effectModel:SetScript("OnDragStop", function(self)
                                    self:StopMovingOrSizing()
                                    -- Save position
                                    local point, _, relativePoint, x, y = self:GetPoint()
                                    Addon.db.profile.SoundQueueUI.PortraitEffectPosition = {
                                        point = point,
                                        relativePoint = relativePoint,
                                        x = x,
                                        y = y
                                    }
                                end)
                                -- Restore saved position or default
                                local pos = Addon.db.profile.SoundQueueUI.PortraitEffectPosition
                                if pos then
                                    effectModel:SetPoint(pos.point, UIParent, pos.relativePoint, pos.x, pos.y)
                                else
                                    effectModel:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
                                end
                                local frameSize = Addon.db.profile.SoundQueueUI.PortraitEffectFrameSize or 120
                                effectModel:SetSize(frameSize, frameSize)

                                -- Hook visibility to portrait
                                portrait:HookScript("OnShow", function()
                                    if effectModel then effectModel:Show() end
                                end)
                                portrait:HookScript("OnHide", function()
                                    if effectModel then effectModel:Hide() end
                                end)

                                -- Set initial visibility
                                if portrait:IsShown() then
                                    effectModel:Show()
                                else
                                    effectModel:Hide()
                                end
                            else
                                -- Attach back to portrait
                                effectModel:SetMovable(false)
                                effectModel:EnableMouse(false)
                                effectModel:SetScript("OnDragStart", nil)
                                effectModel:SetScript("OnDragStop", nil)
                                effectModel:ClearAllPoints()
                                effectModel:SetAllPoints(portrait)
                                effectModel:SetParent(portrait)
                                -- Attached mode: always visible with portrait (parent handles visibility)
                                effectModel:Show()
                            end
                        end
                    end,
                },
                LineBreak2 = { type = "description", name = "", order = 4 },
                EffectFrameSize = {
                    type = "range",
                    order = 5,
                    name = "Frame Size",
                    desc = "Size of the frame container when detached",
                    min = 50,
                    max = 500,
                    step = 10,
                    disabled = function(info) return not Addon.db.profile.SoundQueueUI.PortraitEffectDetached end,
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitEffectFrameSize or 120 end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitEffectFrameSize = value
                        if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait and SoundQueueUI.frame.portrait.effectModel then
                            if Addon.db.profile.SoundQueueUI.PortraitEffectDetached then
                                SoundQueueUI.frame.portrait.effectModel:SetSize(value, value)
                            end
                        end
                    end,
                },
                LineBreak3 = { type = "description", name = "", order = 6 },
                EffectPositionX = {
                    type = "range",
                    order = 7,
                    name = "Position X",
                    desc = "Horizontal position offset of the model (left/right)",
                    min = -10,
                    max = 10,
                    step = 0.1,
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitEffectX or 0 end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitEffectX = value
                        if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait and SoundQueueUI.frame.portrait.effectModel then
                            local x = Addon.db.profile.SoundQueueUI.PortraitEffectX or 0
                            local y = Addon.db.profile.SoundQueueUI.PortraitEffectY or 0
                            local z = Addon.db.profile.SoundQueueUI.PortraitEffectZ or 0
                            SoundQueueUI.frame.portrait.effectModel:SetPosition(z, x, y)
                        end
                    end,
                },
                EffectPositionY = {
                    type = "range",
                    order = 8,
                    name = "Position Y",
                    desc = "Vertical position offset of the model (up/down)",
                    min = -10,
                    max = 10,
                    step = 0.1,
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitEffectY or 0 end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitEffectY = value
                        if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait and SoundQueueUI.frame.portrait.effectModel then
                            local x = Addon.db.profile.SoundQueueUI.PortraitEffectX or 0
                            local y = Addon.db.profile.SoundQueueUI.PortraitEffectY or 0
                            local z = Addon.db.profile.SoundQueueUI.PortraitEffectZ or 0
                            SoundQueueUI.frame.portrait.effectModel:SetPosition(z, x, y)
                        end
                    end,
                },
                EffectPositionZ = {
                    type = "range",
                    order = 9,
                    name = "Position Z (Zoom)",
                    desc = "Depth/zoom of the model (closer/farther)",
                    min = -10,
                    max = 10,
                    step = 0.1,
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitEffectZ or 0 end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitEffectZ = value
                        if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait and SoundQueueUI.frame.portrait.effectModel then
                            local x = Addon.db.profile.SoundQueueUI.PortraitEffectX or 0
                            local y = Addon.db.profile.SoundQueueUI.PortraitEffectY or 0
                            local z = Addon.db.profile.SoundQueueUI.PortraitEffectZ or 0
                            SoundQueueUI.frame.portrait.effectModel:SetPosition(z, x, y)
                        end
                    end,
                },
                EffectRotation = {
                    type = "range",
                    order = 10,
                    name = "Rotation",
                    desc = "Rotation angle of the model in degrees",
                    min = 0,
                    max = 360,
                    step = 1,
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitEffectRotation or 0 end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitEffectRotation = value
                        if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait and SoundQueueUI.frame.portrait.effectModel then
                            local radians = math.rad(value)
                            SoundQueueUI.frame.portrait.effectModel:SetFacing(radians)
                        end
                    end,
                },
                LineBreak4 = { type = "description", name = "", order = 11 },
                EffectScale = {
                    type = "range",
                    order = 12,
                    name = "Effect Scale",
                    desc = "Scale/size of the visual effect model",
                    min = 0.1,
                    max = 5.0,
                    step = 0.1,
                    get = function(info) return Addon.db.profile.SoundQueueUI.PortraitEffectScale or 1.0 end,
                    set = function(info, value)
                        Addon.db.profile.SoundQueueUI.PortraitEffectScale = value
                        if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait and SoundQueueUI.frame.portrait.effectModel then
                            SoundQueueUI.frame.portrait.effectModel:SetScale(value)
                        end
                    end,
                },
            }
        },
    }
}

---@type AceConfigOptionsTable
local AdvanceToolsTab = {
    name = "AdvanceTools",
    type = "group",
    order = 25,
    args = {
        QuestProgressModule = {
            type = "group",
            order = 1,
            name = "Quest Progress",
            inline = true,
            args = {
                EnableModule = {
                    type = "toggle",
                    order = 1,
                    width = 1.50,
                    name = "Enable Quest Progress",
                    desc =
                    "Activa o desactiva el módulo que reproduce el texto de progreso cuando alcanzas el 50% de una misión.",
                    get = function(info) return Addon.db.profile.QuestProgressEnabled end,
                    set = function(info, value)
                        Addon.db.profile.QuestProgressEnabled = value
                        if value then
                            VoiceOver.MissionProgress.Activate()
                        else
                            Addon.db.profile.QuestProgressDebugEnabled = false
                            VoiceOver.MissionProgress.Deactivate()
                        end
                    end,
                },
                QuestProgressDebugEnabled = {
                    type = "toggle",
                    order = 2,
                    width = 0.75,
                    name = "DebugMode",
                    desc = "Enables debug messages specifically for Quest Progress module.",
                    disabled = function() return not Addon.db.profile.QuestProgressEnabled end,
                    get = function(info) return Addon.db.profile.QuestProgressDebugEnabled end,
                    set = function(info, value)
                        Addon.db.profile.QuestProgressDebugEnabled = value
                        if value then
                            print("|cffff0000Debug Mode for Quest Progress Activated|r")
                        else
                            print("|cffff0000Debug Mode for Quest Progress Deactivated|r")
                        end
                    end,
                },
                Description = {
                    type = "description",
                    order = 3,
                    name =
                    "\nEl módulo Quest Progress reproduce el texto de progreso cuando alcanzas el 50% de una misión, sin importar dónde te encuentres.\n",
                },
            },
        },
        RareAnnounceModule = {
            type = "group",
            order = 2,
            name = "Rare Announce",
            inline = true,
            args = {
                EnableModule = {
                    type = "toggle",
                    order = 1,
                    width = 1.50,
                    name = "Enable Rare Announce",
                    desc = "Activa o desactiva el narrador que te avisa cuando hay un rare cerca.",
                    get = function(info) return Addon.db.profile.RareAnnounceEnabled end,
                    set = function(info, value)
                        Addon.db.profile.RareAnnounceEnabled = value
                        if value then
                            VoiceOver.RareAnnounce.Activate()
                        else
                            Addon.db.profile.RareAnnounceDebugEnabled = false
                            VoiceOver.RareAnnounce.Deactivate()
                        end
                    end,
                },
                RareAnnounceDebugEnabled = {
                    type = "toggle",
                    order = 2,
                    width = 0.75,
                    name = "DebugMode",
                    desc = "Enables debug messages specifically for Rare Announce module.",
                    disabled = function() return not Addon.db.profile.RareAnnounceEnabled end,
                    get = function(info) return Addon.db.profile.RareAnnounceDebugEnabled end,
                    set = function(info, value)
                        Addon.db.profile.RareAnnounceDebugEnabled = value
                        if value then
                            print("|cffff0000Debug Mode for Rare Announce Activated|r")
                        else
                            print("|cffff0000Debug Mode for Rare Announce Deactivated|r")
                        end
                        isDebugEnabled = value
                    end,
                },
                Description = {
                    type = "description",
                    order = 3,
                    name =
                    "\nEl módulo Rare Announce te avisa cuando hay un rare cerca, mejorando tu experiencia al explorar.\n",
                },
            },
        },
    },
}




-- LegacyWrathTab removed - no longer needed for Midnight

-- Pestaña Agradecimientos
---@type AceConfigOptionsTable
local AcknowledgementsTab = {
    name = "Colaboradores",
    type = "group",
    order = 30,
    args = {
        Header = {
            type = "header",
            order = 1,
            name = "|cFFFFD700Creadores de Contenido y Colaboradores|r",
        },
        CreatorList = {
            type = "group",
            order = 2,
            inline = true,
            name = "Colaboradores",
            args = {
                Creator1 = {
                    type = "group",
                    order = 1, -- Ajustado a 1
                    inline = true,
                    name = "",
                    args = {
                        Icon = {
                            type = "execute",
                            order = 1,
                            name = "",
                            width = 0.4,
                            image = "Interface\\AddOns\\AI_VoiceOver\\Icons\\Deiris",
                            imageWidth = 64,
                            imageHeight = 64,
                            func = function()
                                if _G["LinkFrame"] then
                                    _G["LinkFrame"]:Hide()
                                    _G["LinkFrame"] = nil
                                end

                                local f = CreateFrame("Frame", "LinkFrame", UIParent, "BasicFrameTemplateWithInset")
                                f:SetSize(400, 150)
                                f:SetPoint("CENTER")
                                f:SetFrameStrata("TOOLTIP")

                                f.title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                                f.title:SetPoint("TOP", 0, -5)
                                f.title:SetText("Canal de Deiris")

                                local eb = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
                                eb:SetSize(300, 20)
                                eb:SetPoint("CENTER", 0, 0)
                                eb:SetText("https://www.youtube.com/@Deiris")
                                eb:SetAutoFocus(true)
                                eb:HighlightText()

                                local closeButton = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
                                closeButton:SetText("Cerrar")
                                closeButton:SetSize(100, 25)
                                closeButton:SetPoint("BOTTOM", 0, 15)
                                closeButton:SetScript("OnClick", function()
                                    f:Hide(); _G["LinkFrame"] = nil
                                end)

                                f:Show()
                            end,
                        },
                        Info = {
                            type = "description",
                            order = 2,
                            fontSize = "medium",
                            name = "|cFF9966CCDeiris|r\n|cFF00CCFFhttps://www.youtube.com/@Deiris|r",
                            width = 2.6,
                        },
                    },
                },
                Creator2 = {
                    type = "group",
                    order = 2, -- Ajustado a 2
                    inline = true,
                    name = "",
                    args = {
                        Icon = {
                            type = "execute",
                            order = 1,
                            name = "",
                            width = 0.4,
                            image = "Interface\\AddOns\\AI_VoiceOver\\Icons\\Andtres",
                            imageWidth = 64,
                            imageHeight = 64,
                            func = function()
                                if _G["LinkFrame"] then
                                    _G["LinkFrame"]:Hide()
                                    _G["LinkFrame"] = nil
                                end

                                local f = CreateFrame("Frame", "LinkFrame", UIParent, "BasicFrameTemplateWithInset")
                                f:SetSize(400, 150)
                                f:SetPoint("CENTER")
                                f:SetFrameStrata("TOOLTIP")

                                f.title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                                f.title:SetPoint("TOP", 0, -5)
                                f.title:SetText("Canal de Andtres")

                                local eb = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
                                eb:SetSize(300, 20)
                                eb:SetPoint("CENTER", 0, 0)
                                eb:SetText("https://www.twitch.tv/andtres")
                                eb:SetAutoFocus(true)
                                eb:HighlightText()

                                local closeButton = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
                                closeButton:SetText("Cerrar")
                                closeButton:SetSize(100, 25)
                                closeButton:SetPoint("BOTTOM", 0, 15)
                                closeButton:SetScript("OnClick", function()
                                    f:Hide(); _G["LinkFrame"] = nil
                                end)

                                f:Show()
                            end,
                        },
                        Info = {
                            type = "description",
                            order = 2,
                            fontSize = "medium",
                            name = "|cFF9966CCAndtres|r\n|cFF00CCFFhttps://www.twitch.tv/andtres|r",
                            width = 2.6,
                        },
                    },
                },
                Creator3 = {
                    type = "group",
                    order = 3, -- Ajustado a 3
                    inline = true,
                    name = "",
                    args = {
                        Icon = {
                            type = "execute",
                            order = 1,
                            name = "",
                            width = 0.4,
                            image = "Interface\\AddOns\\AI_VoiceOver\\Icons\\Dantaes",
                            imageWidth = 64,
                            imageHeight = 64,
                            func = function()
                                if _G["LinkFrame"] then
                                    _G["LinkFrame"]:Hide()
                                    _G["LinkFrame"] = nil
                                end

                                local f = CreateFrame("Frame", "LinkFrame", UIParent, "BasicFrameTemplateWithInset")
                                f:SetSize(400, 150)
                                f:SetPoint("CENTER")
                                f:SetFrameStrata("TOOLTIP")

                                f.title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                                f.title:SetPoint("TOP", 0, -5)
                                f.title:SetText("Canal de FARMERS DE AZEROTH")

                                local eb = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
                                eb:SetSize(300, 20)
                                eb:SetPoint("CENTER", 0, 0)
                                eb:SetText("https://www.youtube.com/@dantaes")
                                eb:SetAutoFocus(true)
                                eb:HighlightText()

                                local closeButton = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
                                closeButton:SetText("Cerrar")
                                closeButton:SetSize(100, 25)
                                closeButton:SetPoint("BOTTOM", 0, 15)
                                closeButton:SetScript("OnClick", function()
                                    f:Hide(); _G["LinkFrame"] = nil
                                end)

                                f:Show()
                            end,
                        },
                        Info = {
                            type = "description",
                            order = 2,
                            fontSize = "medium",
                            name = "|cFF9966CCFARMERS DE AZEROTH|r\n|cFF00CCFFhttps://www.youtube.com/@dantaes|r",
                            width = 2.6,
                        },
                    },
                },
                Creator4 = {
                    type = "group",
                    order = 4, -- Ajustado a 4
                    inline = true,
                    name = "",
                    args = {
                        Icon = {
                            type = "execute",
                            order = 1,
                            name = "",
                            width = 0.4,
                            image = "Interface\\AddOns\\AI_VoiceOver\\Icons\\Karlana",
                            imageWidth = 64,
                            imageHeight = 66,
                            func = function()
                                if _G["LinkFrame"] then
                                    _G["LinkFrame"]:Hide()
                                    _G["LinkFrame"] = nil
                                end

                                local f = CreateFrame("Frame", "LinkFrame", UIParent, "BasicFrameTemplateWithInset")
                                f:SetSize(400, 150)
                                f:SetPoint("CENTER")
                                f:SetFrameStrata("TOOLTIP")

                                f.title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                                f.title:SetPoint("TOP", 0, -5)
                                f.title:SetText("Canal de El Diario de Karlana")

                                local eb = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
                                eb:SetSize(300, 20)
                                eb:SetPoint("CENTER", 0, 0)
                                eb:SetText("https://www.youtube.com/@ElDiarioDeKarlana")
                                eb:SetAutoFocus(true)
                                eb:HighlightText()

                                local closeButton = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
                                closeButton:SetText("Cerrar")
                                closeButton:SetSize(100, 25)
                                closeButton:SetPoint("BOTTOM", 0, 15)
                                closeButton:SetScript("OnClick", function()
                                    f:Hide(); _G["LinkFrame"] = nil
                                end)

                                f:Show()
                            end,
                        },
                        Info = {
                            type = "description",
                            order = 2,
                            fontSize = "medium",
                            name =
                            "|cFF9966CCEl Diario de Karlana|r\n|cFF00CCFFhttps://www.youtube.com/@ElDiarioDeKarlana|r",
                            width = 2.6,
                        },
                    },
                },
                Creator5 = {
                    type = "group",
                    order = 5, -- Ajustado a 5
                    inline = true,
                    name = "",
                    args = {
                        Icon = {
                            type = "execute",
                            order = 1,
                            name = "",
                            width = 0.4,
                            image = "Interface\\AddOns\\AI_VoiceOver\\Icons\\Moverlorde",
                            imageWidth = 64,
                            imageHeight = 64,
                            func = function()
                                if _G["LinkFrame"] then
                                    _G["LinkFrame"]:Hide()
                                    _G["LinkFrame"] = nil
                                end

                                local f = CreateFrame("Frame", "LinkFrame", UIParent, "BasicFrameTemplateWithInset")
                                f:SetSize(400, 150)
                                f:SetPoint("CENTER")
                                f:SetFrameStrata("TOOLTIP")

                                f.title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                                f.title:SetPoint("TOP", 0, -5)
                                f.title:SetText("Canal de Moverlorde")

                                local eb = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
                                eb:SetSize(300, 20)
                                eb:SetPoint("CENTER", 0, 0)
                                eb:SetText("https://www.youtube.com/@Moverlorde")
                                eb:SetAutoFocus(true)
                                eb:HighlightText()

                                local closeButton = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
                                closeButton:SetText("Cerrar")
                                closeButton:SetSize(100, 25)
                                closeButton:SetPoint("BOTTOM", 0, 15)
                                closeButton:SetScript("OnClick", function()
                                    f:Hide(); _G["LinkFrame"] = nil
                                end)

                                f:Show()
                            end,
                        },
                        Info = {
                            type = "description",
                            order = 2,
                            fontSize = "medium",
                            name = "|cFF9966CCMoverlorde|r\n|cFF00CCFFhttps://www.youtube.com/@Moverlorde|r",
                            width = 2.6,
                        },
                    },
                },
                Creator6 = {
                    type = "group",
                    order = 6, -- Ajustado a 6
                    inline = true,
                    name = "",
                    args = {
                        Icon = {
                            type = "execute",
                            order = 1,
                            name = "",
                            width = 0.4,
                            image = "Interface\\AddOns\\AI_VoiceOver\\Icons\\ZNoF354",
                            imageWidth = 64,
                            imageHeight = 64,
                            func = function()
                                if _G["LinkFrame"] then
                                    _G["LinkFrame"]:Hide()
                                    _G["LinkFrame"] = nil
                                end

                                local f = CreateFrame("Frame", "LinkFrame", UIParent, "BasicFrameTemplateWithInset")
                                f:SetSize(400, 150)
                                f:SetPoint("CENTER")
                                f:SetFrameStrata("TOOLTIP")

                                f.title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                                f.title:SetPoint("TOP", 0, -5)
                                f.title:SetText("Canal de ZNoF354")

                                local eb = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
                                eb:SetSize(300, 20)
                                eb:SetPoint("CENTER", 0, 0)
                                eb:SetText("https://www.youtube.com/@ZNoF354")
                                eb:SetAutoFocus(true)
                                eb:HighlightText()

                                local closeButton = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
                                closeButton:SetText("Cerrar")
                                closeButton:SetSize(100, 25)
                                closeButton:SetPoint("BOTTOM", 0, 15)
                                closeButton:SetScript("OnClick", function()
                                    f:Hide(); _G["LinkFrame"] = nil
                                end)

                                f:Show()
                            end,
                        },
                        Info = {
                            type = "description",
                            order = 2,
                            fontSize = "medium",
                            name = "|cFF9966CCZNoF354|r\n|cFF00CCFFhttps://www.youtube.com/@ZNoF354|r",
                            width = 2.6,
                        },
                    },
                },
                Creator7 = {
                    type = "group",
                    order = 7, -- Ajustado a 7
                    inline = true,
                    name = "",
                    args = {
                        Icon = {
                            type = "execute",
                            order = 1,
                            name = "",
                            width = 0.4,
                            image = "Interface\\AddOns\\AI_VoiceOver\\Icons\\Saiztico",
                            imageWidth = 64,
                            imageHeight = 64,
                            func = function()
                                if _G["LinkFrame"] then
                                    _G["LinkFrame"]:Hide()
                                    _G["LinkFrame"] = nil
                                end

                                local f = CreateFrame("Frame", "LinkFrame", UIParent, "BasicFrameTemplateWithInset")
                                f:SetSize(400, 150)
                                f:SetPoint("CENTER")
                                f:SetFrameStrata("TOOLTIP")

                                f.title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                                f.title:SetPoint("TOP", 0, -5)
                                f.title:SetText("Canal de Saiztico")

                                local eb = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
                                eb:SetSize(300, 20)
                                eb:SetPoint("CENTER", 0, 0)
                                eb:SetText("https://www.youtube.com/@saiztico")
                                eb:SetAutoFocus(true)
                                eb:HighlightText()

                                local closeButton = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
                                closeButton:SetText("Cerrar")
                                closeButton:SetSize(100, 25)
                                closeButton:SetPoint("BOTTOM", 0, 15)
                                closeButton:SetScript("OnClick", function()
                                    f:Hide(); _G["LinkFrame"] = nil
                                end)

                                f:Show()
                            end,
                        },
                        Info = {
                            type = "description",
                            order = 2,
                            fontSize = "medium",
                            name = "|cFF9966CCSaiztico|r\n|cFF00CCFFhttps://www.youtube.com/@saiztico|r",
                            width = 2.6,
                        },
                    },
                },
            },
        },
        Footer = {
            type = "description",
            order = 7, -- Ajustado para estar justo después de los creadores
            fontSize = "medium",
            name = "\n|cFFFFD700Estos creadores de contenido han apoyado y contribuido al crecimiento de VoiceOver.|r\n" ..
                "|cFFCCCCCCGracias por su apoyo continuo a la comunidad de WoW.|r",
        },
    },
}





-- Pestaña Donaciones
---@type AceConfigOptionsTable
-- Variables para los textos en diferentes idiomas
-- Variables para los textos en diferentes idiomas
local donationTexts = {
    es =
    "|cffffffffLas donaciones serán usadas para crear la versión en Español Latino y Español de España, y a medida que avance el proyecto, se extenderá a todos los idiomas.|r",
    en =
    "|cffffffffDonations will be used to create the Latin American Spanish and European Spanish versions, and as the project progresses, it will expand to all languages.|r",
    fr =
    "|cffffffffLes dons seront utilisés pour créer les versions espagnoles d'Amérique latine et d'Espagne, et à mesure que le projet avancera, il s'étendra à toutes les langues.|r",
    it =
    "|cffffffffLe donazioni saranno utilizzate per creare le versioni spagnole latinoamericane e spagnole europee e, man mano che il progetto progredirà, si espanderà a tutte le lingue.|r",
    pt =
    "|cffffffffAs doações serão usadas para criar as versões em espanhol latino-americano e espanhol europeu e, à medida que o projeto avança, expandir-se-ão para todos os idiomas.|r",
}

-- Variable para almacenar el idioma seleccionado
local selectedLanguage = "es"

-- Función auxiliar para cargar el archivo de donadores de forma segura
local function LoadAddOnSafelyAndReturnDonors()
    if not VoiceOver_DonorsList then
        return "|cFFFF0000No donors list available|r"
    end

    -- Orden de los niveles (de más alto a más bajo)
    local levels = {
        {
            key = "LEGENDARY",
            name = "Legendary Donors",
            color = "|cffff8000",
            icon = "|TInterface\\Icons\\INV_Hammer_Unique_Sulfuras:16:16|t"
        },
        {
            key = "EPIC",
            name = "Epic Donors",
            color = "|cFFA335EE",
            icon = "|TInterface\\Icons\\INV_Enchant_VoidCrystal:16:16|t"
        },
        {
            key = "RARE",
            name = "Rare Donors",
            color = "|cFF0070DD",
            icon = "|TInterface\\Icons\\INV_Enchant_ShardBrilliantSmall:16:16|t"
        },
        {
            key = "UNCOMMON",
            name = "Uncommon Donors",
            color = "|cFF1EFF00",
            icon = "|TInterface\\Icons\\INV_Enchant_ShardGlowingSmall:16:16|t"
        }
    }

    local donorsStr = ""

    -- Agregar encabezado con explicación de rangos
    donorsStr = donorsStr .. "|cFFFFD700Donor Ranks:|r\n\n"

    for _, level in ipairs(levels) do
        if VoiceOver_DonorsList[level.key] and #VoiceOver_DonorsList[level.key] > 0 then
            -- Agregar encabezado de nivel con icono
            donorsStr = donorsStr .. level.icon .. " " .. level.color .. level.name .. "|r\n"

            -- Agregar donadores de este nivel
            for _, donor in ipairs(VoiceOver_DonorsList[level.key]) do
                donorsStr = donorsStr .. level.color .. "    • " .. donor .. "|r\n"
            end

            donorsStr = donorsStr .. "\n"
        end
    end

    return donorsStr
end

-- Pestaña Donaciones
local DonationsTab = {
    name = "Donations",
    type = "group",
    order = 35,
    childGroups = "tab",
    args = {
        donorsList = {
            name = "Donors List",
            type = "group",
            order = 1,
            args = {
                Header = {
                    type = "header",
                    order = 1,
                    name = "|cFFFFD700Our Donors|r",
                },
                Description = {
                    type = "description",
                    order = 2,
                    fontSize = "medium",
                    name = "Thanks to all these amazing people who support VoiceOver development:",
                },
                Donors = {
                    type = "description",
                    order = 3,
                    fontSize = "medium",
                    name = function()
                        return LoadAddOnSafelyAndReturnDonors()
                    end
                }
            }
        },
        supportInfo = {
            name = "Support Us",
            type = "group",
            order = 2,
            args = {
                DiscordSection = {
                    type = "group",
                    order = 1,
                    inline = true,
                    name = "Community",
                    args = {
                        DiscordHeader = {
                            type = "header",
                            order = 1,
                            name = "Join Our Discord Community",
                        },
                        DiscordDescription = {
                            type = "description",
                            order = 2,
                            fontSize = "medium",
                            name = "Join our community to get support, updates and participate in development:",
                        },
                        DiscordLink = {
                            type = "input",
                            order = 3,
                            width = "full",
                            name = "|cff7289DADiscord Server|r",
                            get = function() return "https://discord.gg/jHPsF2dt9y" end,
                            set = function() end,
                        },
                    }
                },
                DonationSection = {
                    type = "group",
                    order = 2,
                    inline = true,
                    name = "Support Options",
                    args = {
                        LanguageSelection = {
                            type = "select",
                            order = 1,
                            name = "Language",
                            desc = "Select your language",
                            values = {
                                es = "Español",
                                en = "English",
                                fr = "Français",
                                it = "Italiano",
                                pt = "Português",
                            },
                            get = function() return selectedLanguage end,
                            set = function(_, newValue)
                                selectedLanguage = newValue
                            end,
                        },
                        Description = {
                            type = "description",
                            order = 2,
                            name = function()
                                return donationTexts[selectedLanguage]
                            end,
                        },
                        PayPalLink = {
                            type = "input",
                            order = 3,
                            width = "full",
                            name = "|cff0079C1PayPal|r",
                            desc = "Support via PayPal",
                            get = function() return "neo4400@hotmail.com" end,
                            set = function() end,
                        },
                        PatreonLink = {
                            type = "input",
                            order = 4,
                            width = "full",
                            name = "|cff3399FFPatreon|r",
                            desc = "Become a Patron",
                            get = function() return "https://patreon.com/NeoAuras" end,
                            set = function() end,
                        },
                    }
                }
            }
        }
    }
}


---@type AceConfigOptionsTable
local DataModulesTab =
{
    name = function()
        return format("Data Modules%s",
            next(Options.table.args.DataModules.args.Available.args) and "|cFF00CCFF (NEW)|r" or "")
    end,
    type = "group",
    childGroups = "tree",
    order = 20,
    args = {
        DescriptionHeader = {
            type = "header",
            order = 1,
            name = "Data Modules Information / Información de Módulos de Datos",
        },
        Description = {
            type = "description",
            order = 2,
            name =
                "This module ensures that available packs in the addons folder are loaded. The voice pack does not need to be activated in the game like other addons, Voice Over Mod recognizes it just by installing it.\n\n" ..
                "Este módulo asegura que los paquetes disponibles en la carpeta de addons sean cargados. El paquete de voz no necesita ser activado en el juego como otros addons, Voice Over Mod lo reconoce con solo instalarlo.",
            fontSize = "medium",
        },
        ReloadAllModules = {
            type = "execute",
            order = 2.5,
            name = "Reload UI",
            desc = "Reload the user interface to apply changes in enabled/disabled status",
            width = "full",
            func = function()
                ReloadUI()
            end,
        },
        LoadedPacksHeader = {
            type = "header",
            order = 3,
            name = "Loaded Sound Packages",
        },
        LoadedPacks = {
            type = "group",
            name = "",
            order = 4,
            inline = true,
            args = {}
        },
        Available = {
            type = "group",
            name = "|cFF00CCFFMore Sound Packs|r",
            order = 100000,
            hidden = function(info) return not next(Options.table.args.DataModules.args.Available.args) end,
            args = {}
        }
    }
}

---@type AceConfigOptionsTable
local SlashCommands = {
    type = "group",
    name = "Commands",
    order = 110,
    inline = true,
    dialogHidden = true,
    args = {
        PlayPause = {
            type = "execute",
            order = 1,
            name = "Play/Pause Audio",
            desc = "Play/Pause voiceovers",
            hidden = true,
            func = function(info)
                SoundQueue:TogglePauseQueue()
            end
        },
        Play = {
            type = "execute",
            order = 2,
            name = "Play Audio",
            desc = "Resume the playback of voiceovers",
            func = function(info)
                SoundQueue:ResumeQueue()
            end
        },
        Pause = {
            type = "execute",
            order = 3,
            name = "Pause Audio",
            desc = "Pause the playback of voiceovers",
            func = function(info)
                SoundQueue:PauseQueue()
            end
        },
        Skip = {
            type = "execute",
            order = 4,
            name = "Skip Line",
            desc = "Skip the currently played voiceover",
            func = function(info)
                local soundData = SoundQueue:GetCurrentSound()
                if soundData then
                    SoundQueue:RemoveSoundFromQueue(soundData)
                end
            end
        },
        Clear = {
            type = "execute",
            order = 5,
            name = "Clear Queue",
            desc = "Stop the playback and clears the voiceovers queue",
            func = function(info)
                SoundQueue:RemoveAllSoundsFromQueue()
            end
        },
        Options = {
            type = "execute",
            order = 100,
            name = "Open Options",
            desc = "Open the options panel",
            func = function(info)
                Options:OpenConfigWindow()
            end
        },
    }
}

---@type AceConfigOptionsTable
Options.table = {
    name = "Voice Over Mod 2.0",
    type = "group",
    childGroups = "tab",
    args = {
        General = GeneralTab,
        VisualEffects = VisualEffectsTab, -- Nueva pestaña Visual Effects
        AdvanceTools = AdvanceToolsTab, -- Añadido AdvanceToolsTab aquí
        DataModules = DataModulesTab,
        Acknowledgements = AcknowledgementsTab,
        Donations = DonationsTab,
        Profiles = nil, -- Filled in Options:OnInitialize, order is implicitly 100
        SlashCommands = SlashCommands,
    }
}
------------------------------------------------------------

---@param module DataModuleMetadata
---@param order number
function Options:AddDataModule(module, order)
    local descriptionOrder = 0
    local function GetNextOrder()
        descriptionOrder = descriptionOrder + 1
        return descriptionOrder
    end
    local function MakeDescription(header, text)
        return {
            type = "description",
            order = GetNextOrder(),
            name = function()
                return format("%s%s: |r%s",
                    NORMAL_FONT_COLOR_CODE, header, type(text) == "function" and text() or text)
            end
        }
    end

    local name, title, notes, loadable, reason = DataModules:GetModuleAddOnInfo(module)
    if reason == "DEMAND_LOADED" or reason == "INTERFACE_VERSION" then
        reason = nil
    end
    DataModulesTab.args[module.AddonName] = {
        name = function()
            local isLoaded = C_AddOns.IsAddOnLoaded(module.AddonName)
            local isDisabled = DataModules:IsModuleDisabled(module.AddonName)
            return format("%d. %s%s%s|r",
                order,
                reason and RED_FONT_COLOR_CODE or isLoaded and HIGHLIGHT_FONT_COLOR_CODE or GRAY_FONT_COLOR_CODE,
                string.gsub(module.Title, "VoiceOver Data %- ", ""),
                isLoaded and "" or (isDisabled and " (disabled)" or " (not loaded)"))
        end,
        type = "group",
        order = order,
        args = {
            AddonName = MakeDescription("Addon Name", module.AddonName),
            Title = MakeDescription("Title", module.Title),
            ModuleVersion = MakeDescription("Module Data Format Version", module.ModuleVersion),
            ModulePriority = MakeDescription("Module Priority", module.ModulePriority),
            ContentVersion = MakeDescription("Content Version", module.ContentVersion),
            LoadOnDemand = MakeDescription("Load on Demand", module.LoadOnDemand and "Yes" or "No"),
            Loaded = MakeDescription("Is Loaded",
                function() return C_AddOns.IsAddOnLoaded(module.AddonName) and "Yes" or "No" end),
            Enabled = {
                type = "toggle",
                order = GetNextOrder(),
                name = "Enable Module",
                desc = "Enable or disable this data module. When disabled, the module will not be loaded until re-enabled.",
                width = "full",
                get = function() return not DataModules:IsModuleDisabled(module.AddonName) end,
                set = function(info, value)
                    DataModules:SetModuleDisabled(module.AddonName, not value)
                    -- Actualizar la interfaz para reflejar el cambio
                    AceConfigDialog:SelectGroup("VoiceOver", "DataModules")
                end,
            },
            NotLoadableReason = {
                type = "description",
                order = GetNextOrder(),
                name = format("%sReason: |r%s%s|r", NORMAL_FONT_COLOR_CODE, RED_FONT_COLOR_CODE,
                    reason and _G["ADDON_" .. reason] or ""),
                hidden = not reason,
            },
            Load = {
                type = "execute",
                order = GetNextOrder(),
                name = "Load",
                hidden = function() 
                    return reason or 
                           not module.LoadOnDemand or 
                           C_AddOns.IsAddOnLoaded(module.AddonName) or
                           DataModules:IsModuleDisabled(module.AddonName)
                end,
                func = function()
                    local loaded, reason = DataModules:LoadModule(module)
                    if not loaded then
                        StaticPopup_Show("VOICEOVER_ERROR",
                            format([[Failed to load data module "%s". Reason: %s]], module.AddonName,
                                reason and _G["ADDON_" .. reason] or "Unknown"))
                    end
                end,
            },
        }
    }
end

---@param module AvailableDataModule
---@param order number
---@param update boolean Data module has update
function Options:AddAvailableDataModule(module, order, update)
    local descriptionOrder = 0
    local function GetNextOrder()
        descriptionOrder = descriptionOrder + 1
        return descriptionOrder
    end
    local function MakeDescription(header, text)
        return {
            type = "description",
            order = GetNextOrder(),
            name = function()
                return format("%s%s: |r%s",
                    NORMAL_FONT_COLOR_CODE, header, type(text) == "function" and text() or text)
            end
        }
    end

    DataModulesTab.args.Available.args[module.AddonName] = {
        name = Utils:ColorizeText(
            format(update and "%s (Update)" or "%s", string.gsub(module.Title, "VoiceOver Data %- ", "")), "|cFF00CCFF"),
        type = "group",
        order = order,
        args = {
            AddonName = MakeDescription("Addon Name", module.AddonName),
            Title = MakeDescription("Title", module.Title),
            ContentVersion = MakeDescription("Content Version",
                format(update and "%2$s -> |cFF00CCFF%1$s|r" or "%s", module.ContentVersion,
                    update and DataModules:GetPresentModule(module.AddonName).ContentVersion)),
            URL = {
                type = "input",
                order = GetNextOrder(),
                width = "full",
                name = "Download URL",
                get = function(info) return module.URL end,
                set = function(info) end,
            },
        }
    }
end

---Initialization of opens panel
function Options:Initialize()
    self.table.args.Profiles = AceDBOptions:GetOptionsTable(Addon.db)

    -- Create options table
    Debug:Print("Registering options table...", "Options")
    local AceConfig = LibStub("AceConfig-3.0")
    AceConfig:RegisterOptionsTable("VoiceOver", self.table, "vo")
    AceConfigDialog:AddToBlizOptions("VoiceOver")
    for key, tab in Utils:Ordered(Options.table.args, SortAceConfigOptions) do
        if not tab.hidden and not tab.dialogHidden then
            AceConfigDialog:AddToBlizOptions("VoiceOver", type(tab.name) == "function" and tab.name() or tab.name,
                "VoiceOver", key)
        end
    end
    Debug:Print("Done!", "Options")

    -- Create the option frame
    ---@type AceGUIFrame|AceGUIWidget
    self.frame = AceGUI:Create("Frame")
    --AceConfigDialog:SetDefaultSize("VoiceOver", 640, 780) -- Let it be auto-sized
    AceConfigDialog:Open("VoiceOver", self.frame)
    self.frame:SetLayout("Fill")
    self.frame:Hide()

    -- Enable the frame to be closed with Escape key
    _G["VoiceOverOptions"] = self.frame.frame
    tinsert(UISpecialFrames, "VoiceOverOptions")
end

function Options:OpenConfigWindow()
    if self.frame:IsShown() then
        PlaySound(SOUNDKIT.IG_MAINMENU_CLOSE)
        self.frame:Hide()
    else
        PlaySound(SOUNDKIT.IG_MAINMENU_OPEN)
        self.frame:Show()
        AceConfigDialog:Open("VoiceOver", self.frame)
    end
end
