-- [ OPTIONS ] Configuration panel for EPF Custom Skins.
-- Access: Esc → System → AddOns → EPF Custom Skins

local ADDON_NAME = "EPF Custom Skins"
local ADDON_LOADED_NAME = "ElitePlayerFrame_Enhanced_CustomSkins"

local L = EPF_CustomSkins_L or {}
local INFO_LOGS = false
local PAD = 16
local GROUP_SPACING = 20
local SECTION_PADDING = 10

local function Log(message)
    if INFO_LOGS and DEFAULT_CHAT_FRAME then
        DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00EPF Custom Skins Options:|r " .. tostring(message))
    end
end

-- SectionTextures label: read from locale table directly to avoid key lookup issues
local function getSectionTexturesLabel()
    local loc = (GetLocale and GetLocale()) or "enUS"
    if loc == "es" and EPF_CustomSkins_Locales and EPF_CustomSkins_Locales.esES then loc = "esES" end
    local locales = EPF_CustomSkins_Locales
    if not locales then return "Available textures" end
    local t = locales[loc]
    if t and t.SectionTextures then return t.SectionTextures end
    t = locales.enUS
    if t and t.SectionTextures then return t.SectionTextures end
    return "Available textures"
end

local panel = CreateFrame("Frame", "EPFCustomSkinsOptionsPanel", UIParent)
panel.name = ADDON_NAME
panel:Hide()

local TAB_BAR_HEIGHT = 26
local TAB_GAP = 10

local title = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
title:SetPoint("TOPLEFT", 16, -16)
title:SetText(ADDON_NAME)

local tabBar = CreateFrame("Frame", nil, panel)
tabBar:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -6)
tabBar:SetHeight(TAB_BAR_HEIGHT)
tabBar:SetPoint("RIGHT", panel, "RIGHT", -PAD, 0)

local contentPanel = CreateFrame("Frame", nil, panel)
-- Align tab content with the panel left edge (tab bar stays indented with the title).
contentPanel:SetPoint("TOPLEFT", tabBar, "BOTTOMLEFT", -PAD, -8)
contentPanel:SetPoint("BOTTOMRIGHT", panel, "BOTTOMRIGHT", 0, 0)

local activeTab = 1
local tabButtons = {}

local settingsPanel = CreateFrame("Frame", nil, contentPanel)
settingsPanel:SetAllPoints(contentPanel)

local overridesPanel
local overridesBuildError
if EPF_CustomSkins_OptionsOverrides and EPF_CustomSkins_OptionsOverrides.Build then
    local ok, built = pcall(EPF_CustomSkins_OptionsOverrides.Build, contentPanel)
    if ok and built then
        overridesPanel = built
        overridesPanel:SetAllPoints(contentPanel)
        overridesPanel:Hide()
    else
        overridesBuildError = built
    end
end

local function updateTabVisuals(tabIndex)
    for index, tab in ipairs(tabButtons) do
        local selected = (index == tabIndex)
        if tab.Text then
            tab.Text:SetFontObject(selected and "GameFontHighlight" or "GameFontNormal")
        end
        tab:SetEnabled(not selected)
    end
end

local function selectOptionsTab(tabIndex)
    activeTab = tabIndex
    settingsPanel:SetShown(tabIndex == 1)
    if overridesPanel then
        overridesPanel:SetShown(tabIndex == 2)
        if tabIndex == 2 and overridesPanel.Refresh then
            pcall(function() overridesPanel:Refresh() end)
        end
    end
    updateTabVisuals(tabIndex)
end

local function createOptionsTab(index, label, anchorTo)
    local tab = CreateFrame("Button", "EPFCustomSkinsOptionsTab" .. index, tabBar)
    tab:SetSize(120, TAB_BAR_HEIGHT)
    tab.Text = tab:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    tab.Text:SetPoint("CENTER")
    tab.Text:SetText(label)
    if index == 1 then
        tab:SetPoint("LEFT", tabBar, "LEFT", 0, 0)
    else
        tab:SetPoint("LEFT", anchorTo, "RIGHT", TAB_GAP, 0)
    end
    tab:SetID(index)
    tab:SetScript("OnClick", function()
        selectOptionsTab(index)
    end)
    tabButtons[index] = tab
    return tab
end

local tabSettings = createOptionsTab(1, L.TabSettings or "Settings")
local tabOverrides = createOptionsTab(2, L.TabOverrides or "Overrides", tabSettings)

if overridesBuildError and not overridesPanel then
    local errLabel = contentPanel:CreateFontString(nil, "ARTWORK", "GameFontRed")
    errLabel:SetPoint("TOPLEFT", contentPanel, "TOPLEFT", PAD, -PAD)
    errLabel:SetPoint("TOPRIGHT", contentPanel, "TOPRIGHT", -PAD, -PAD)
    errLabel:SetJustifyH("LEFT")
    errLabel:SetText(L.OverridePanelLoadError or "Overrides panel failed to load. Enable script errors and reload.")
end

selectOptionsTab(1)

local function getBaseAddon()
    return ElitePlayerFrame_Enhanced
end

local BASE_SETTINGS_GLOBAL = "ElitePlayerFrame_Enhanced_Settings"
local function getBaseSettings()
    local addon = getBaseAddon()
    if addon and addon.settings then
        return addon.settings
    end
    local sv = _G[BASE_SETTINGS_GLOBAL]
    if sv then return sv end
    return nil
end

local function getOutputLevels(addon)
    if not addon then return nil end
    if type(addon.GetOutputLevels) == "function" then
        local ok, levels = pcall(function() return addon:GetOutputLevels() end)
        if ok and type(levels) == "table" then return levels end
    end
    return addon.OUTPUT_LEVELS
end

local function getFrameModes(addon)
    if not addon then return nil end
    if type(addon.GetFrameModes) == "function" then
        local ok, modes = pcall(function() return addon:GetFrameModes() end)
        if ok and type(modes) == "table" then return modes end
    end
    return addon.FRAME_MODES
end

local function requestBaseUpdate(force)
    local addon = getBaseAddon()
    if addon and type(addon.Update) == "function" then
        pcall(function() addon:Update(force) end)
    end
end

local function setBaseSetting(setting, value)
    local addon = getBaseAddon()
    if addon and type(addon.SetSetting) == "function" then
        local ok = pcall(function() addon:SetSetting(setting, value) end)
        if ok then return true end
    end
    local settings = getBaseSettings()
    if settings then
        settings[setting] = value
        return true
    end
    return false
end

-- Section/list backdrop: ChatFrame background + Tooltip border, insets 3
local CONTAINER_BACKDROP = {
    bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true,
    tileSize = 16,
    edgeSize = 16,
    insets = { left = 3, right = 3, top = 3, bottom = 3 }
}

local function setSectionBackdrop(frame)
    if not frame.SetBackdrop and BackdropTemplateMixin then
        Mixin(frame, BackdropTemplateMixin)
    end
    if frame.SetBackdrop then
        frame:SetBackdrop(CONTAINER_BACKDROP)
        frame:SetBackdropColor(0.2, 0.2, 0.2, 0.5)
        if frame.SetBackdropBorderColor then
            frame:SetBackdropBorderColor(0.4, 0.4, 0.4, 1)
        end
    end
end

-- BackdropTemplate required on Retail (9.0+); setSectionBackdrop applies Mixin if missing
local BackdropTemplate = "BackdropTemplate"

-- Options column (right, 40%); position set in OnShow to the right of group3
local group1 = CreateFrame("Frame", nil, settingsPanel, BackdropTemplate)
group1:SetPoint("TOPRIGHT", settingsPanel, "TOPRIGHT", -PAD, 0)
group1:SetPoint("BOTTOMRIGHT", settingsPanel, "BOTTOMRIGHT", -PAD, 24)
setSectionBackdrop(group1)

local sectionMain = group1:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
sectionMain:SetPoint("TOPLEFT", SECTION_PADDING, -SECTION_PADDING)
sectionMain:SetText(L.SectionMainAddon or "Opciones")

local ROW_SPACING = 8
local checkDisplay = CreateFrame("CheckButton", nil, group1, "InterfaceOptionsCheckButtonTemplate")
checkDisplay:SetPoint("TOPLEFT", sectionMain, "BOTTOMLEFT", 0, -6)
local checkDisplayLabel = checkDisplay:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
checkDisplayLabel:SetPoint("LEFT", checkDisplay, "RIGHT", 4, 0)
checkDisplayLabel:SetText(L.Display or "Display")
checkDisplay.tooltipText = L.DisplayDesc or "Show or hide the player frame modifications."

local checkClass = CreateFrame("CheckButton", nil, group1, "InterfaceOptionsCheckButtonTemplate")
checkClass:SetPoint("TOPLEFT", checkDisplay, "BOTTOMLEFT", 0, -ROW_SPACING)
local checkClassLabel = checkClass:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
checkClassLabel:SetPoint("LEFT", checkClass, "RIGHT", 4, 0)
checkClassLabel:SetText(L.ClassSelection or "Class selection")
checkClass.tooltipText = L.ClassSelectionDesc or "In Auto mode, choose frame by class/spec."

local checkSex = CreateFrame("CheckButton", nil, group1, "InterfaceOptionsCheckButtonTemplate")
checkSex:SetPoint("TOPLEFT", checkClass, "BOTTOMLEFT", 0, -ROW_SPACING)
local checkSexLabel = checkSex:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
checkSexLabel:SetPoint("LEFT", checkSex, "RIGHT", 4, 0)
checkSexLabel:SetText(L.SexSelection or "Sex selection")
checkSex.tooltipText = L.SexSelectionDesc or "In Auto mode, choose frame by sex."

local checkFaction = CreateFrame("CheckButton", nil, group1, "InterfaceOptionsCheckButtonTemplate")
checkFaction:SetPoint("TOPLEFT", checkSex, "BOTTOMLEFT", 0, -ROW_SPACING)
local checkFactionLabel = checkFaction:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
checkFactionLabel:SetPoint("LEFT", checkFaction, "RIGHT", 4, 0)
checkFactionLabel:SetText(L.FactionSelection or "Faction selection")
checkFaction.tooltipText = L.FactionSelectionDesc or "In Auto mode, choose frame by faction."

local checkHideInInstance = CreateFrame("CheckButton", nil, group1, "InterfaceOptionsCheckButtonTemplate")
checkHideInInstance:SetPoint("TOPLEFT", checkFaction, "BOTTOMLEFT", 0, -12)
local checkHideInInstanceLabel = checkHideInInstance:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
checkHideInInstanceLabel:SetPoint("LEFT", checkHideInInstance, "RIGHT", 4, 0)
checkHideInInstanceLabel:SetText(L.HideInInstance or "Display in instances")
checkHideInInstance.tooltipText = L.HideInInstanceDesc or "Use custom frame in instances, raids, battlegrounds and arenas."

local outputLabel = group1:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
outputLabel:SetPoint("TOPLEFT", checkHideInInstance, "BOTTOMLEFT", 0, -14)
outputLabel:SetText(L.OutputLevel or "Message output level")
outputLabel:SetJustifyH("LEFT")

local outputDropdown = CreateFrame("Frame", "EPFCustomSkinsOutputDropdown", group1, "UIDropDownMenuTemplate")
outputDropdown:SetPoint("TOPLEFT", outputLabel, "BOTTOMLEFT", 0, -4)
outputDropdown.tooltipText = L.OutputLevelDesc or "Message verbosity (0 = critical, higher = more debug)."
if outputDropdown.SetWidth then outputDropdown:SetWidth(200) end
outputDropdown.initialize = function()
    local addon = getBaseAddon()
    local list = getOutputLevels(addon)
    if not list then return end
    local maxIdx = 0
    for k in pairs(list) do
        if type(k) == "number" and k > maxIdx then maxIdx = k end
    end
    for i = 0, maxIdx do
        local info = list[i]
        local nameStr = (info and info.name) and tostring(info.name) or tostring(i)
        local option = UIDropDownMenu_CreateInfo()
        option.text = nameStr
        option.value = i
        option.func = function(self)
            if setBaseSetting("outputLevel", self.value) then
                UIDropDownMenu_SetSelectedValue(outputDropdown, self.value)
                requestBaseUpdate(true)
            end
        end
        UIDropDownMenu_AddButton(option)
    end
end

local function setCheckFromSetting(btn, value)
    local checked = (value == true or value == 1)
    btn:SetChecked(checked)
    if InterfaceOptionsPanel_CheckButton_Update then
        InterfaceOptionsPanel_CheckButton_Update(btn)
    end
end

local function refreshMainAddonChecks()
    local settings = getBaseSettings()
    if settings then
        setCheckFromSetting(checkDisplay, settings.display)
        setCheckFromSetting(checkClass, settings.classSelection)
        setCheckFromSetting(checkSex, settings.sexSelection)
        setCheckFromSetting(checkFaction, settings.factionSelection)
        setCheckFromSetting(checkHideInInstance, settings.instances)
    end
    local addon = getBaseAddon()
    local outputLevels = getOutputLevels(addon)
    if settings and outputLevels and UIDropDownMenu_Initialize and UIDropDownMenu_SetSelectedValue then
        UIDropDownMenu_Initialize(outputDropdown, outputDropdown.initialize)
        UIDropDownMenu_SetSelectedValue(outputDropdown, settings.outputLevel)
        if UIDropDownMenu_Refresh then
            UIDropDownMenu_Refresh(outputDropdown)
        end
    end
end

local function updateUIFromDefaults(def)
    if not def then return end
    setCheckFromSetting(checkDisplay, def.display)
    setCheckFromSetting(checkClass, def.classSelection)
    setCheckFromSetting(checkSex, def.sexSelection)
    setCheckFromSetting(checkFaction, def.factionSelection)
    setCheckFromSetting(checkHideInInstance, def.instances)
    local addon = getBaseAddon()
    if addon and addon.OUTPUT_LEVELS and UIDropDownMenu_Initialize and UIDropDownMenu_SetSelectedValue then
        UIDropDownMenu_Initialize(outputDropdown, outputDropdown.initialize)
        UIDropDownMenu_SetSelectedValue(outputDropdown, def.outputLevel)
        if UIDropDownMenu_Refresh then
            UIDropDownMenu_Refresh(outputDropdown)
        end
    end
end

local btnReset = CreateFrame("Button", nil, settingsPanel, "UIPanelButtonTemplate")
btnReset:SetSize(100, 22)
btnReset:SetPoint("TOPRIGHT", settingsPanel, "TOPRIGHT", -24, -16)
btnReset:SetText(L.Reset or "Reset")
btnReset.tooltipText = L.ResetDesc or "Reset Elite Player Frame (Enhanced) settings to defaults."
btnReset:SetScript("OnClick", function()
    local addon = getBaseAddon()
    if addon and type(addon.Reset) == "function" then
        addon:Reset()
        if C_Timer and C_Timer.After then
            C_Timer.After(0, function()
                refreshMainAddonChecks()
                updateFrameModeList()
            end)
            C_Timer.After(0.1, function()
                refreshMainAddonChecks()
                updateFrameModeList()
            end)
        end
    end
end)

checkDisplay:SetScript("OnClick", function(self)
    if setBaseSetting("display", self:GetChecked() and true or false) then
        requestBaseUpdate(true)
    end
end)
checkClass:SetScript("OnClick", function(self)
    if setBaseSetting("classSelection", self:GetChecked() and true or false) then
        requestBaseUpdate(true)
    end
end)
checkSex:SetScript("OnClick", function(self)
    if setBaseSetting("sexSelection", self:GetChecked() and true or false) then
        requestBaseUpdate(true)
    end
end)
checkFaction:SetScript("OnClick", function(self)
    if setBaseSetting("factionSelection", self:GetChecked() and true or false) then
        requestBaseUpdate(true)
    end
end)
checkHideInInstance:SetScript("OnClick", function(self)
    if setBaseSetting("instances", self:GetChecked() and true or false) then
        requestBaseUpdate(true)
    end
end)

-- Textures column (left, 60%); position and width set in OnShow
local group3 = CreateFrame("Frame", nil, settingsPanel, BackdropTemplate)
group3:SetPoint("TOPLEFT", settingsPanel, "TOPLEFT", PAD, -8)
group3:SetPoint("BOTTOMLEFT", settingsPanel, "BOTTOMLEFT", PAD, 24)
setSectionBackdrop(group3)

local listLabel = group3:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
listLabel:SetPoint("TOPLEFT", SECTION_PADDING, -SECTION_PADDING)
listLabel:SetText(getSectionTexturesLabel())

local updateFrameModeList = function() end

local hasScrollBoxAPI = (CreateScrollBoxListLinearView or CreateScrollBoxListGridView) and ScrollUtil and ScrollUtil.InitScrollBoxListWithScrollBar and CreateDataProvider
if hasScrollBoxAPI then
    local searchBoxContainer = CreateFrame("Frame", nil, group3)
    searchBoxContainer:SetPoint("TOPLEFT", listLabel, "BOTTOMLEFT", 0, -6)
    searchBoxContainer:SetPoint("TOPRIGHT", group3, "TOPRIGHT", -SECTION_PADDING - 24, 0)
    searchBoxContainer:SetHeight(24)

    local searchEditBox, searchPlaceholder
    local currentSearchFilter = ""
    local okTemplate = pcall(function()
        searchEditBox = CreateFrame("EditBox", nil, searchBoxContainer, "SearchBoxTemplate")
    end)
    if okTemplate and searchEditBox then
        searchEditBox:SetPoint("LEFT", 6, 0)
        searchEditBox:SetPoint("RIGHT", -6, 0)
        searchEditBox:SetPoint("TOP", 0, 0)
        searchEditBox:SetPoint("BOTTOM", 0, 0)
        searchEditBox:SetMaxLetters(80)
        if searchEditBox.Instructions then
            searchEditBox.Instructions:SetText(EPF_CustomSkins_L and (EPF_CustomSkins_L.SearchFilter or "Filter...") or "Filter...")
        end
        searchEditBox:SetScript("OnTextChanged", function(self)
            if SearchBoxTemplate_OnTextChanged then SearchBoxTemplate_OnTextChanged(self) end
            local text = self:GetText()
            if text and text:len() > 0 then
                currentSearchFilter = text:gsub("^%s+", ""):gsub("%s+$", ""):lower()
            else
                currentSearchFilter = ""
            end
            if updateFrameModeList then updateFrameModeList() end
        end)
    else
        if searchEditBox then searchEditBox = nil end
        searchBoxContainer:SetBackdrop(BackdropTemplate and {
            bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
            edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
            tile = true, tileSize = 16, edgeSize = 8,
            insets = { left = 4, right = 4, top = 2, bottom = 2 }
        } or nil)
        if searchBoxContainer.SetBackdrop then
            searchBoxContainer:SetBackdropColor(0.15, 0.15, 0.15, 0.8)
            if searchBoxContainer.SetBackdropBorderColor then searchBoxContainer:SetBackdropBorderColor(0.35, 0.35, 0.35, 1) end
        end
        searchEditBox = CreateFrame("EditBox", nil, searchBoxContainer)
        searchEditBox:SetPoint("LEFT", 8, 0)
        searchEditBox:SetPoint("RIGHT", -8, 0)
        searchEditBox:SetPoint("TOP", 0, 0)
        searchEditBox:SetPoint("BOTTOM", 0, 0)
        searchEditBox:SetFontObject("GameFontHighlight")
        searchEditBox:SetAutoFocus(false)
        searchEditBox:SetMaxLetters(80)
        searchPlaceholder = searchEditBox:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
        searchPlaceholder:SetPoint("LEFT", searchEditBox, "LEFT", 0, 0)
        searchPlaceholder:SetText(EPF_CustomSkins_L and (EPF_CustomSkins_L.SearchFilter or "Filter...") or "Filter...")
        searchPlaceholder:SetTextColor(0.5, 0.5, 0.5, 0.8)
        searchEditBox:SetScript("OnEscapePressed", function(self)
            self:ClearFocus()
            self:SetText("")
            currentSearchFilter = ""
            if updateFrameModeList then updateFrameModeList() end
        end)
        searchEditBox:SetScript("OnTextChanged", function(self)
            local text = self:GetText()
            if searchPlaceholder then searchPlaceholder:SetShown(not text or text:len() == 0) end
            if text and text:len() > 0 then currentSearchFilter = text:gsub("^%s+", ""):gsub("%s+$", ""):lower()
            else currentSearchFilter = "" end
            if updateFrameModeList then updateFrameModeList() end
        end)
        searchEditBox:SetScript("OnEditFocusGained", function(self) if searchPlaceholder then searchPlaceholder:Hide() end end)
        searchEditBox:SetScript("OnEditFocusLost", function(self) if searchPlaceholder and (not self:GetText() or self:GetText():len() == 0) then searchPlaceholder:Show() end end)
    end
    searchEditBox:SetScript("OnEscapePressed", function(self)
        self:ClearFocus()
        self:SetText("")
        currentSearchFilter = ""
        if updateFrameModeList then updateFrameModeList() end
    end)

    local listContainer = CreateFrame("Frame", nil, group3, BackdropTemplate)
    listContainer:SetPoint("TOPLEFT", searchBoxContainer, "BOTTOMLEFT", 0, -6)
    listContainer:SetPoint("BOTTOMRIGHT", group3, "BOTTOMRIGHT", -24, 6)
    if listContainer.SetBackdrop then
        listContainer:SetBackdrop(CONTAINER_BACKDROP)
        listContainer:SetBackdropColor(0.2, 0.2, 0.2, 0.5)
        if listContainer.SetBackdropBorderColor then
            listContainer:SetBackdropBorderColor(0.4, 0.4, 0.4, 1)
        end
    end

    local scrollBox = CreateFrame("Frame", nil, listContainer, "WowScrollBoxList")
    scrollBox:SetPoint("TOPLEFT", 8, -8)
    scrollBox:SetPoint("BOTTOMRIGHT", -8, 8)

    local scrollBar = CreateFrame("EventFrame", nil, group3, "MinimalScrollBar")
    scrollBar:SetPoint("TOPLEFT", listContainer, "TOPRIGHT", 6, 0)
    scrollBar:SetPoint("BOTTOMLEFT", listContainer, "BOTTOMRIGHT", 6, 0)

    local function applyFrameMode(index)
        if not setBaseSetting("frameMode", index) then return end
        requestBaseUpdate(true)
        if C_Timer and C_Timer.After then
            C_Timer.After(0, function()
                requestBaseUpdate(true)
            end)
        end
        if scrollBox.GetDataProvider then
            scrollBox:ForEachFrame(function(button, elementData)
                local refreshedSettings = getBaseSettings()
                local isSelected = (refreshedSettings and refreshedSettings.frameMode == elementData.index)
                if button.SelectedTexture then
                    button.SelectedTexture:SetShown(isSelected)
                end
            end)
        end
    end

    local function getModeDisplayName(modes, i, L)
        local mode = modes[i]
        local displayName
        if i == 0 then
            displayName = L.DefaultNoTexture or "Default (no texture)"
        elseif mode and mode.name then
            displayName = tostring(mode.name)
        else
            displayName = (i == 1 and (L.Automatic or "Automatic")) or (L.Custom or "Custom")
        end
        if mode and mode.color and mode.color.GetRGB then
            local r, g, b = mode.color:GetRGB()
            return format("|cff%02x%02x%02x[%d] %s|r", r * 255, g * 255, b * 255, i, displayName)
        end
        return format("[%d] %s", i, displayName)
    end

    local function getModeDisplayNamePlain(modes, i, L)
        local raw = getModeDisplayName(modes, i, L)
        if not raw then return "" end
        return raw:gsub("|c%x%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):lower()
    end

    local function InitButton(button, elementData)
        if not button.Text then
            button.Text = button:CreateFontString(nil, "ARTWORK", "GameFontWhite")
            button.Text:SetPoint("LEFT", 10, 0)
            button.Text:SetPoint("RIGHT", -10, 0)
            button.Text:SetJustifyH("LEFT")

            local highlight = button:CreateTexture(nil, "HIGHLIGHT")
            highlight:SetAllPoints()
            local ok = pcall(function() highlight:SetAtlas("Options_List_Hover") end)
            if not ok or not highlight:GetAtlas() then
                highlight:SetColorTexture(1, 1, 1, 0.15)
            end
            button:SetHighlightTexture(highlight)

            local selected = button:CreateTexture(nil, "BACKGROUND")
            selected:SetAllPoints(button)
            pcall(function() selected:SetAtlas("Options_List_Active") end)
            button.SelectedTexture = selected
            selected:Hide()
        end

        local index = elementData.index
        local L = EPF_CustomSkins_L or {}
        local displayName = getModeDisplayName(elementData.allModes, index, L)
        button.Text:SetText(displayName)

        button:SetScript("OnClick", function()
            applyFrameMode(index)
        end)

        local addon = getBaseAddon()
        local settings = getBaseSettings()
        local isSelected = (settings and settings.frameMode == index)
        if button.SelectedTexture then
            button.SelectedTexture:SetShown(isSelected)
        end
    end

    updateFrameModeList = function()
        local addon = getBaseAddon()
        local modes = getFrameModes(addon)
        if not modes then
            Log(L.FrameModesUnavailable or "Texture list is empty: base addon or FRAME_MODES not available.")
            return
        end

        local dataProvider = CreateDataProvider()
        local maxIndex = 0
        for k in pairs(modes) do
            if type(k) == "number" and k > maxIndex then maxIndex = k end
        end

        local L = EPF_CustomSkins_L or {}
        local filter = currentSearchFilter
        local overrides_module = EPF_CustomSkins_Overrides
        for i = 0, maxIndex do
            local is_override_mode = overrides_module and overrides_module.IsOverrideModeId(i)
            if not is_override_mode and (filter == "" or (getModeDisplayNamePlain(modes, i, L):find(filter, 1, true))) then
                dataProvider:Insert({index = i, allModes = modes})
            end
        end

        scrollBox:SetDataProvider(dataProvider)
    end

    local view = CreateScrollBoxListLinearView and CreateScrollBoxListLinearView() or CreateScrollBoxListGridView(1)
    view:SetElementExtent(20)
    view:SetElementInitializer("Button", InitButton)
    view:SetPadding(5, 5, 5, 5, 5)

    ScrollUtil.InitScrollBoxListWithScrollBar(scrollBox, scrollBar, view)
else
    local errorLabel = group3:CreateFontString(nil, "ARTWORK", "GameFontRed")
    errorLabel:SetPoint("CENTER", 0, 0)
    errorLabel:SetText("ScrollBox API not available on this client version.")
end

panel:SetScript("OnShow", function()
    local L = EPF_CustomSkins_L or {}
    panel.name = ADDON_NAME
    if tabSettings.Text then
        tabSettings.Text:SetText(L.TabSettings or "Settings")
    end
    if tabOverrides.Text then
        tabOverrides.Text:SetText(L.TabOverrides or "Overrides")
    end
    selectOptionsTab(activeTab)
    -- Layout 60% / 40%: left textures, right options
    local panelW = settingsPanel:GetWidth()
    if panelW and panelW > 0 then
        group3:SetWidth(panelW * 0.6)
        group1:SetWidth(panelW * 0.4)
        group3:ClearAllPoints()
        group3:SetPoint("TOPLEFT", settingsPanel, "TOPLEFT", PAD, -8)
        group3:SetPoint("BOTTOMLEFT", settingsPanel, "BOTTOMLEFT", PAD, 24)
        group1:ClearAllPoints()
        group1:SetPoint("TOPLEFT", group3, "TOPRIGHT", GROUP_SPACING, 0)
        group1:SetPoint("TOPRIGHT", settingsPanel, "TOPRIGHT", -PAD, 0)
        group1:SetPoint("BOTTOMRIGHT", settingsPanel, "BOTTOMRIGHT", -PAD, 24)
    end
    title:SetText(ADDON_NAME)
    sectionMain:SetText(L.SectionMainAddon or "Opciones")
    checkDisplayLabel:SetText(L.Display or "Display")
    checkClassLabel:SetText(L.ClassSelection or "Class selection")
    checkSexLabel:SetText(L.SexSelection or "Sex selection")
    checkFactionLabel:SetText(L.FactionSelection or "Faction selection")
    checkHideInInstanceLabel:SetText(L.HideInInstance or "Display in instances")
    checkHideInInstance.tooltipText = L.HideInInstanceDesc or "Use custom frame in instances, raids, battlegrounds and arenas."
    outputLabel:SetText(L.OutputLevel or "Message output level")
    outputDropdown.tooltipText = L.OutputLevelDesc or "Message verbosity (0 = critical, higher = more debug)."
    btnReset:SetText(L.Reset or "Reset")
    btnReset.tooltipText = L.ResetDesc or "Reset Elite Player Frame (Enhanced) settings to defaults."
    listLabel:SetText(getSectionTexturesLabel())
    local addon = getBaseAddon()
    local modes = getFrameModes(addon)
    local settings = getBaseSettings()
    refreshMainAddonChecks()
    updateFrameModeList()
    if C_Timer and C_Timer.After then
        C_Timer.After(0, refreshMainAddonChecks)
    end
end)

local function registerOptions()
    if InterfaceOptions_AddCategory then
        InterfaceOptions_AddCategory(panel)
    end
    if Settings and Settings.RegisterCanvasLayoutCategory and Settings.RegisterAddOnCategory then
        local category = Settings.RegisterCanvasLayoutCategory(panel, ADDON_NAME)
        Settings.RegisterAddOnCategory(category)
    end
    local addon = getBaseAddon()
    if addon and type(addon.WhenInitialised) == "function" then
        addon:WhenInitialised(function(a)
            if type(a.RegisterCallback) == "function" then
                a:RegisterCallback("SETTING_CHANGED", function()
                    refreshMainAddonChecks()
                    updateFrameModeList()
                end, "EPF_CustomSkins_Options_SettingChanged")
                a:RegisterCallback("SETTINGS_RESET", function()
                    refreshMainAddonChecks()
                    updateFrameModeList()
                end, "EPF_CustomSkins_Options_SettingsReset")
            end
            refreshMainAddonChecks()
            updateFrameModeList()
        end)
    end
end

local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:SetScript("OnEvent", function(_, event, addonName)
    if event == "ADDON_LOADED" and addonName == ADDON_LOADED_NAME then
        eventFrame:UnregisterEvent("ADDON_LOADED")
        registerOptions()
    end
end)
