local PT = AhUI
local UI = {}
local L = PT.L
PT.Settings = UI

StaticPopupDialogs["AHUI_COPY_LINK"] = {
    text = "Copy link:",
    button1 = OKAY,
    hasEditBox = true,
    editBoxWidth = 350,
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
    OnShow = function(self)
        self.EditBox:SetText("https://t.me/ahui_feedback_bot")
        self.EditBox:SetFocus()
        self.EditBox:HighlightText()
    end,
}

local function CopyFeedbackLink()
    StaticPopup_Show("AHUI_COPY_LINK")
end

function UI:Create()
    if self.panel then
        return self.panel
    end
    self.checkboxes = {}

    local function RefreshWelcome()
        if PT.WelcomeUI and PT.WelcomeUI.Refresh then
            PT.WelcomeUI:Refresh()
        end
    end

    local f = CreateFrame("Frame", "AhUISettingsMain", UIParent)
    f:SetSize(500, 440)

    local title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
    title:SetPoint("TOPLEFT", 16, -16)
    title:SetText(L["Settings_Title"])

    local saveLabel = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    saveLabel:SetPoint("TOPLEFT", title, "TOPLEFT", 465, 0)
    saveLabel:SetText(L["Settings_SaveMode"] or "Save settings")

    local cbChar = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbChar:SetPoint("TOPLEFT", saveLabel, "BOTTOMLEFT", 6, -14)
    cbChar.text:SetText(L["Settings_SaveCharacter"] or "Save per character")

    local cbAcc = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbAcc:SetPoint("TOPLEFT", cbChar, "BOTTOMLEFT", 0, -10)
    cbAcc.text:SetText(L["Settings_SaveAccount"] or "Save for account")

    local function UpdateSaveModeUI()
        cbChar:SetChecked(AhUI_DB.saveMode == "character")
        cbAcc:SetChecked(AhUI_DB.saveMode == "account")
    end

    local function SetSaveMode(mode)
        if AhUI_DB.saveMode == mode then return end

        AhUI_DB.saveMode = mode
        PT.config = PT:GetConfigDB()

        UpdateSaveModeUI()

        if PT.RefreshData then
            PT:RefreshData()
        end

        if PT.ConcentrationUI and PT.ConcentrationUI.ApplyCustomization then
            PT.ConcentrationUI:ApplyCustomization()
        end

        if PT.UI and PT.UI.ApplyCustomization then
            PT.UI:ApplyCustomization()
        end

        if PT.ConfirmButtons then
            if PT.config.confirmOK then
                PT.ConfirmButtons:EnableOK()
            else
                PT.ConfirmButtons:DisableOK()
            end

            if PT.config.confirmReload then
                PT.ConfirmButtons:ShowReload()
            else
                PT.ConfirmButtons:HideReload()
            end

            if PT.ConfirmButtons.ApplyStyle then
                PT.ConfirmButtons:ApplyStyle()
            end

            if PT.ConfirmButtons.SetAuctionatorEnabled then
                PT.ConfirmButtons:SetAuctionatorEnabled(PT.config.confirmAuctionator == true)
            end
        end

        if PT.RefreshUI then
            PT:RefreshUI()
        end

        RefreshWelcome()
    end

    cbChar:SetScript("OnClick", function(self)
        if AhUI_DB.saveMode ~= "character" then
            SetSaveMode("character")
        else
            UpdateSaveModeUI()
        end
    end)

    cbAcc:SetScript("OnClick", function(self)
        if AhUI_DB.saveMode ~= "account" then
            SetSaveMode("account")
        else
            UpdateSaveModeUI()
        end
    end)

    UpdateSaveModeUI()

    local feedbackBtn = CreateFrame("Button", nil, f)
    feedbackBtn:SetSize(160, 22)
    feedbackBtn:SetPoint("TOPLEFT", cbAcc, "BOTTOMLEFT", 2, -15)

    local icon = feedbackBtn:CreateTexture(nil, "ARTWORK")
    icon:SetSize(18, 18)
    icon:SetPoint("LEFT", 0, 0)
    icon:SetAtlas("newplayerchat-chaticon-newcomer")

    local text = feedbackBtn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    text:SetPoint("LEFT", icon, "RIGHT", 4, 0)
    text:SetText("|cff00ccffSend Feedback / Report Bug|r")

    local hover = feedbackBtn:CreateTexture(nil, "BACKGROUND")
    hover:SetAllPoints()
    hover:SetTexture("Interface\\Buttons\\WHITE8x8")
    hover:SetColorTexture(1, 1, 1, 0)

    feedbackBtn:SetScript("OnEnter", function()
        hover:SetColorTexture(1, 1, 1, 0.08)
        text:SetText("|cff66ddffSend Feedback / Report Bug|r")

        GameTooltip:SetOwner(feedbackBtn, "ANCHOR_RIGHT")
        GameTooltip:SetText("Send feedback or suggestions", 1, 1, 1)
        GameTooltip:AddLine("@ahui_feedback_bot", 0, 0.8, 1)
        GameTooltip:Show()
    end)

    feedbackBtn:SetScript("OnLeave", function()
        hover:SetColorTexture(1, 1, 1, 0)
        text:SetText("|cff00ccffSend Feedback / Report Bug|r")
        GameTooltip:Hide()
    end)

    feedbackBtn:SetScript("OnMouseUp", function()
        CopyFeedbackLink()
    end)

    local mapPinsLabel = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    mapPinsLabel:SetPoint("TOPLEFT", feedbackBtn, "BOTTOMLEFT", -6, -24)
    mapPinsLabel:SetText(L["Settings_MapPins"] or "Map pins")

    local cbMapPins = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbMapPins:SetPoint("TOPLEFT", mapPinsLabel, "BOTTOMLEFT", 10, -6)
    cbMapPins.text:SetText(L["Settings_Enable"] or "Enable")

    cbMapPins.GetValue = function()
        return PT.config.enableMapPins ~= false
    end
    cbMapPins:SetChecked(cbMapPins.GetValue())
    self.checkboxes.enableMapPins = cbMapPins

    cbMapPins:SetScript("OnClick", function(self)
        PT.config.enableMapPins = self:GetChecked()

        if PT.SkinningWorldMapDataProvider then
            if PT.config.enableMapPins then
                if WorldMapFrame and WorldMapFrame.dataProviders
                    and not WorldMapFrame.dataProviders[PT.SkinningWorldMapDataProvider]
                then
                    WorldMapFrame:AddDataProvider(PT.SkinningWorldMapDataProvider)
                end

                if PT.MapPinsButton then
                    PT.MapPinsButton:Show()
                end

                if PT.SkinningWorldMapDataProvider.RefreshAllData then
                    PT.SkinningWorldMapDataProvider:RefreshAllData()
                end
            else
                if PT.SkinningWorldMapDataProvider.RemoveAllData then
                    PT.SkinningWorldMapDataProvider:RemoveAllData()
                end

                if PT.MapPinsButton then
                    PT.MapPinsButton:Hide()
                end

                if PT.HideMapPinsMenu then
                    PT.HideMapPinsMenu()
                end
            end
        end
    end)

    local cbStackAssist = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbStackAssist:SetPoint("TOPLEFT", cbMapPins, "BOTTOMLEFT", 0, -10)
    cbStackAssist.text:SetText(L["Settings_StackAssist"] or "Stack Assist")

    cbStackAssist.GetValue = function()
        return PT.config.stackAssistEnabled == true
    end
    cbStackAssist:SetChecked(cbStackAssist.GetValue())
    self.checkboxes.stackAssistEnabled = cbStackAssist

    cbStackAssist:SetScript("OnClick", function(self)
        PT.config.stackAssistEnabled = self:GetChecked() == true

        if PT.StackAssist and PT.StackAssist.ApplyEnabledState then
            PT.StackAssist:ApplyEnabledState()
        end

        RefreshWelcome()
    end)

    local cbGoldDepositor = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbGoldDepositor:SetPoint("TOPLEFT", cbStackAssist, "BOTTOMLEFT", 0, -10)
    cbGoldDepositor.text:SetText(L["Settings_GoldDepositor"] or "Gold Depositor")

    cbGoldDepositor.GetValue = function()
        return PT.config.goldDepositorEnabled ~= false
    end
    cbGoldDepositor:SetChecked(cbGoldDepositor.GetValue())
    self.checkboxes.goldDepositorEnabled = cbGoldDepositor

    cbGoldDepositor:SetScript("OnClick", function(self)
        PT.config.goldDepositorEnabled = self:GetChecked() == true

        if PT.GoldDepositor and PT.GoldDepositor.ApplyEnabledState then
            PT.GoldDepositor:ApplyEnabledState()
        end

        RefreshWelcome()
    end) 

    local cbShoppingListAlways = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbShoppingListAlways:SetPoint("TOPLEFT", cbGoldDepositor, "BOTTOMLEFT", 0, -10)
    cbShoppingListAlways.text:SetText(L["Settings_ShoppingListAlwaysShowTab"] or "Закупки AhUIshop")

    cbShoppingListAlways.GetValue = function()
        return PT.config.shoppingListAlwaysShowTab == true
    end

    cbShoppingListAlways:SetChecked(cbShoppingListAlways.GetValue())
    self.checkboxes.shoppingListAlwaysShowTab = cbShoppingListAlways

    cbShoppingListAlways:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:SetText(L["Settings_ShoppingListAlwaysShowTab"] or "AhUIshop purchases", 1, 1, 1)
        GameTooltip:AddLine(L["Settings_ShoppingListAlwaysShowTab_Tooltip"] or "Always show the AhUIshop shopping tab", 0.8, 0.8, 0.8, true)
        GameTooltip:Show()
    end)

    cbShoppingListAlways:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)

    cbShoppingListAlways:SetScript("OnClick", function(self)
        PT.config.shoppingListAlwaysShowTab = self:GetChecked() == true

        if PT.ShoppingList and PT.ShoppingList.ApplyAlwaysShowTabSetting then
            PT.ShoppingList:ApplyAlwaysShowTabSetting()
        end

        RefreshWelcome()
    end)

    local cb = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cb:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -12)
    cb.text:SetText(L["Settings_Concentration"])
    cb.GetValue = function()
        return PT.config.showConcentration ~= false
    end
    cb:SetChecked(cb.GetValue())
    self.checkboxes.showConcentration = cb

    cb:SetScript("OnClick", function(self)
        PT.config.showConcentration = self:GetChecked()

        if PT.UpdateVisibility then
            PT:UpdateVisibility()
        end

        RefreshWelcome()
    end)

    local cbConcHide = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbConcHide:SetPoint("LEFT", cb.text, "RIGHT", 12, 0)
    cbConcHide.text:SetText(L["Settings_HideInCombat"] or "Hide in combat")

    cbConcHide.GetValue = function()
        return PT.config.hideConcentrationInCombat ~= false
    end
    cbConcHide:SetChecked(cbConcHide.GetValue())
    self.checkboxes.hideConcentrationInCombat = cbConcHide

    cbConcHide:SetScript("OnClick", function(self)
        PT.config.hideConcentrationInCombat = self:GetChecked()
    end)

    local cbConcInstance = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbConcInstance:SetPoint("LEFT", cbConcHide.text, "RIGHT", 12, 0)
    cbConcInstance.text:SetText(L["Settings_HideInInstance"] or "Hide in instances")

    cbConcInstance.GetValue = function()
        return PT.config.hideConcentrationInInstance == true
    end
    cbConcInstance:SetChecked(cbConcInstance.GetValue())
    self.checkboxes.hideConcentrationInInstance = cbConcInstance

    cbConcInstance:SetScript("OnClick", function(self)
        PT.config.hideConcentrationInInstance = self:GetChecked()
    end)

    local cb2 = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cb2:SetPoint("TOPLEFT", cb, "BOTTOMLEFT", 0, -10)
    cb2.text:SetText(L["Settings_ProfWindow"])
    cb2.GetValue = function()
        return PT.config.showProfessionsWindow ~= false
    end
    cb2:SetChecked(cb2.GetValue())
    self.checkboxes.showProfessionsWindow = cb2

    cb2:SetScript("OnClick", function(self)
        local enabled = self:GetChecked()
        PT.config.showProfessionsWindow = enabled

        if PT.UpdateVisibility then
            PT:UpdateVisibility()
        end

        RefreshWelcome()
    end)

    local cbProfHide = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbProfHide:SetPoint("TOPLEFT", cbConcHide, "BOTTOMLEFT", 0, -10)
    cbProfHide.text:SetText(L["Settings_HideInCombat"] or "Hide in combat")

    cbProfHide.GetValue = function()
        return PT.config.hideProfessionsInCombat ~= false
    end
    cbProfHide:SetChecked(cbProfHide.GetValue())
    self.checkboxes.hideProfessionsInCombat = cbProfHide

    cbProfHide:SetScript("OnClick", function(self)
        PT.config.hideProfessionsInCombat = self:GetChecked()
    end)

    local cbProfInstance = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbProfInstance:SetPoint("LEFT", cbProfHide.text, "RIGHT", 12, 0)
    cbProfInstance.text:SetText(L["Settings_HideInInstance"] or "Hide in instances")

    cbProfInstance.GetValue = function()
        return PT.config.hideProfessionsInInstance == true
    end
    cbProfInstance:SetChecked(cbProfInstance.GetValue())
    self.checkboxes.hideProfessionsInInstance = cbProfInstance

    cbProfInstance:SetScript("OnClick", function(self)
        PT.config.hideProfessionsInInstance = self:GetChecked()
    end)

    local cb3 = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cb3:SetPoint("TOPLEFT", cb2, "BOTTOMLEFT", 0, -10)
    cb3.text:SetText(L["Settings_LockWindows"])
    cb3:SetChecked(PT.config.lockWindows)

    cb3:SetScript("OnClick", function(self)
        PT.config.lockWindows = self:GetChecked()
        local windows = {
            PT.UI and PT.UI.frame,
            PT.ConcentrationUI and PT.ConcentrationUI.frame,
        }
        for _, w in ipairs(windows) do
            if w then
                w:SetMovable(not PT.config.lockWindows)
                w:EnableMouse(not PT.config.lockWindows)
            end
        end
    end)

    PT.config.confirmOK = PT.config.confirmOK ~= false
    PT.config.confirmReload = PT.config.confirmReload ~= false
    PT.config.confirmButtonStyle = PT.config.confirmButtonStyle or "default"
    PT.config.confirmAuctionator = PT.config.confirmAuctionator == true

    local cbOK = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbOK:SetPoint("TOPLEFT", cb3, "BOTTOMLEFT", 0, -10)
    cbOK.text:SetText(L["Settings_ConfirmOK"])
    cbOK.GetValue = function()
        return PT.config.confirmOK ~= false
    end
    cbOK:SetChecked(cbOK.GetValue())
    self.checkboxes.confirmOK = cbOK

    cbOK:SetScript("OnClick", function(self)
        PT.config.confirmOK = self:GetChecked()
        if PT.ConfirmButtons then
            PT.ConfirmButtons:SetOKEnabled(PT.config.confirmOK)
        end

        RefreshWelcome()
    end)

    local cbR = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbR:SetPoint("TOPLEFT", cbOK, "BOTTOMLEFT", 0, -10)
    cbR.text:SetText(L["Settings_ConfirmReload"])
    cbR.GetValue = function()
        return PT.config.confirmReload ~= false
    end
    cbR:SetChecked(cbR.GetValue())
    self.checkboxes.confirmReload = cbR

    cbR:SetScript("OnClick", function(self)
        PT.config.confirmReload = self:GetChecked()
        if PT.ConfirmButtons then
            PT.ConfirmButtons:SetReloadEnabled(PT.config.confirmReload)
        end

        RefreshWelcome()
    end)

    if PT.ConfirmButtons then
        PT.ConfirmButtons:SetOKEnabled(PT.config.confirmOK)
        PT.ConfirmButtons:SetReloadEnabled(PT.config.confirmReload)

        if PT.ConfirmButtons.SetAuctionatorEnabled then
            PT.ConfirmButtons:SetAuctionatorEnabled(PT.config.confirmAuctionator == true)
        end
    end

    local styleLabel = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    styleLabel:SetPoint("TOPLEFT", cbR, "TOPRIGHT", 140, 10)
    styleLabel:SetText(L["Settings_ConfirmStyle"])

    local styles = {}
    if PT.ConfirmButtons and PT.ConfirmButtons.STYLES then
        for key, info in pairs(PT.ConfirmButtons.STYLES) do
            table.insert(styles, { key = key, name = info.name or key })
        end
    end
    table.sort(styles, function(a, b) return a.name < b.name end)

    local dd = CreateFrame("Frame", "AhUIConfirmStyleDropdown", f, "UIDropDownMenuTemplate")
    dd:SetPoint("TOPLEFT", styleLabel, "BOTTOMLEFT", -16, -4)
    UIDropDownMenu_SetWidth(dd, 200)

    UIDropDownMenu_Initialize(dd, function(_, level)
        for _, s in ipairs(styles) do
            local info = UIDropDownMenu_CreateInfo()
            info.text = s.name
            info.checked = (PT.config.confirmButtonStyle == s.key)
            info.func = function()
                PT.config.confirmButtonStyle = s.key
                UIDropDownMenu_SetText(dd, s.name)
                if PT.ConfirmButtons and PT.ConfirmButtons.ApplyStyle then
                    PT.ConfirmButtons:ApplyStyle()
                end
            end
            UIDropDownMenu_AddButton(info, level)
        end
    end)

    do
        local cur = PT.config.confirmButtonStyle
        local style = PT.ConfirmButtons and PT.ConfirmButtons.STYLES and PT.ConfirmButtons.STYLES[cur]
        UIDropDownMenu_SetText(dd, style and style.name or L["Default"])
    end

    local addPopupLabel = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    addPopupLabel:SetPoint("TOPLEFT", cbR, "BOTTOMLEFT", 10, -14)
    addPopupLabel:SetText(L["Settings_AddPopupExclude"] or "Add popup exclusion")

    local addPopupInput = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
    addPopupInput:SetSize(180, 22)
    addPopupInput:SetPoint("TOPLEFT", addPopupLabel, "BOTTOMLEFT", 0, -6)
    addPopupInput:SetAutoFocus(false)
    addPopupInput:SetMaxLetters(80)

    local addPopupBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    addPopupBtn:SetSize(80, 22)
    addPopupBtn:SetPoint("LEFT", addPopupInput, "RIGHT", 8, 0)
    addPopupBtn:SetText(ADD or "Add")

    local debugPopupBtn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    debugPopupBtn:SetSize(80, 22)
    debugPopupBtn:SetPoint("LEFT", addPopupBtn, "RIGHT", 8, 0)

    local function RefreshDebugButtonText()
        local enabled = PT.ConfirmButtons and PT.ConfirmButtons.IsDebugEnabled and PT.ConfirmButtons:IsDebugEnabled()

        if enabled then
            debugPopupBtn:SetText(L["Settings_ConfirmDebug_On"] or "Debug: ON")
        else
            debugPopupBtn:SetText(L["Settings_ConfirmDebug_Off"] or "Debug: OFF")
        end
    end

    self.debugPopupBtn = debugPopupBtn
    self.RefreshDebugButtonText = RefreshDebugButtonText

    debugPopupBtn:SetScript("OnClick", function()
        if PT.ConfirmButtons and PT.ConfirmButtons.SetDebugEnabled and PT.ConfirmButtons.IsDebugEnabled then
            PT.ConfirmButtons:SetDebugEnabled(not PT.ConfirmButtons:IsDebugEnabled())
            RefreshDebugButtonText()
        end
    end)

    debugPopupBtn:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:SetText(L["Settings_ConfirmDebug_Tooltip_Title"] or "Popup debug mode", 1, 1, 1)
        GameTooltip:AddLine(L["Settings_ConfirmDebug_Tooltip_1"] or "Enables popup ID output in chat.", nil, nil, nil, true)
        GameTooltip:AddLine(L["Settings_ConfirmDebug_Tooltip_2"] or "When a popup appears, the addon prints its exact name to chat.", nil, nil, nil, true)
        GameTooltip:AddLine(L["Settings_ConfirmDebug_Tooltip_3"] or "Paste that name into the exclusion field exactly as it appears.", nil, nil, nil, true)
        GameTooltip:AddLine(" ", 1, 1, 1)
        GameTooltip:AddLine(L["Settings_ConfirmDebug_Tooltip_4"] or "Example: GUILD_INVITE", 1, 0.82, 0, true)
        GameTooltip:AddLine(L["Settings_ConfirmDebug_Tooltip_5"] or "After /reload, debug mode turns off automatically.", 0.7, 0.7, 0.7, true)
        GameTooltip:Show()
    end)

    debugPopupBtn:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)

    RefreshDebugButtonText()

    local popupListLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    popupListLabel:SetPoint("TOPLEFT", addPopupInput, "BOTTOMLEFT", 0, -12)
    popupListLabel:SetText(L["Settings_PopupList"] or "User popup exclusions")

    local cbAuctionator = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbAuctionator:SetPoint("TOPLEFT", cbOK, "TOPRIGHT", 135, 0)
    cbAuctionator.text:SetText(L["Settings_ConfirmAuctionator"] or "Confirm Auctionator purchases")

    cbAuctionator.GetValue = function()
        return PT.config.confirmAuctionator == true
    end
    cbAuctionator:SetChecked(cbAuctionator.GetValue())
    self.checkboxes.confirmAuctionator = cbAuctionator

    cbAuctionator:SetScript("OnClick", function(self)
        PT.config.confirmAuctionator = self:GetChecked() == true

        if PT.ConfirmButtons and PT.ConfirmButtons.SetAuctionatorEnabled then
            PT.ConfirmButtons:SetAuctionatorEnabled(PT.config.confirmAuctionator)
        end
    end)

    local popupListFrame = CreateFrame("Frame", nil, f, "BackdropTemplate")
    popupListFrame:SetPoint("TOPLEFT", popupListLabel, "BOTTOMLEFT", 0, -4)
    popupListFrame:SetSize(280, 150)
    popupListFrame:SetBackdrop({
        bgFile   = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 2,
    })
    popupListFrame:SetBackdropColor(0, 0, 0, 0.6)
    popupListFrame:SetBackdropBorderColor(1, 1, 1, 1)

    local popupScroll = CreateFrame("ScrollFrame", nil, popupListFrame)
    popupScroll:SetPoint("TOPLEFT", 4, -4)
    popupScroll:SetPoint("BOTTOMRIGHT", -4, 4)
    popupScroll:EnableMouseWheel(true)

    local popupContent = CreateFrame("Frame", nil, popupScroll)
    popupContent:SetSize(1, 1)
    popupScroll:SetScrollChild(popupContent)

    local popupRowH = 22
    popupScroll:SetScript("OnMouseWheel", function(self, delta)
        self:SetVerticalScroll(math.max(0, self:GetVerticalScroll() - delta * popupRowH))
    end)

    local function RebuildPopupList()
        local children = { popupContent:GetChildren() }
        for _, ch in ipairs(children) do
            ch:Hide()
            ch:SetParent(nil)
        end

        local M = PT.ConfirmButtons
        if not M then return end

        local list = M:GetUserExcludedPopupList()
        local y = -2

        for _, which in ipairs(list) do
            local row = CreateFrame("Frame", nil, popupContent)
            row:SetSize(272, popupRowH)
            row:SetPoint("TOPLEFT", 0, y)

            local hover = row:CreateTexture(nil, "BACKGROUND")
            hover:SetAllPoints()
            hover:SetTexture("Interface\\Buttons\\WHITE8x8")
            hover:SetColorTexture(1, 1, 1, 0)

            row:EnableMouse(true)
            row:SetScript("OnEnter", function()
                hover:SetColorTexture(1, 1, 1, 0.10)

                GameTooltip:SetOwner(row, "ANCHOR_RIGHT")
                GameTooltip:SetText(which, 1, 1, 1)

                local full = M:GetPopupFullText(which)
                if full and full ~= which then
                    GameTooltip:AddLine(full, nil, nil, nil, true)
                end

                GameTooltip:Show()
            end)

            row:SetScript("OnLeave", function()
                hover:SetColorTexture(1, 1, 1, 0)
                GameTooltip:Hide()
            end)

            local lbl = row:CreateFontString(nil, "OVERLAY", "GameFontNormal")
            lbl:SetPoint("LEFT", 6, 0)
            lbl:SetPoint("RIGHT", row, "RIGHT", -60, 0)
            lbl:SetJustifyH("LEFT")
            lbl:SetText(which)

            local removeBtn = CreateFrame("Button", nil, row, "UIPanelButtonTemplate")
            removeBtn:SetSize(70, 20)
            removeBtn:SetPoint("RIGHT", -4, 0)
            removeBtn:SetText(REMOVE or "Remove")
            removeBtn:SetScript("OnClick", function()
                M:RemoveUserExcludedPopup(which)
                RebuildPopupList()
            end)

            y = y - popupRowH
        end

        popupContent:SetHeight(math.max(1, -y + 4))
    end

    local function AddPopupFromInput()
        local text = addPopupInput:GetText()
        if not text or text == "" then return end

        text = strtrim(text)
        if text == "" then return end

        if PT.ConfirmButtons and PT.ConfirmButtons.AddUserExcludedPopup then
            PT.ConfirmButtons:AddUserExcludedPopup(text)
        end

        addPopupInput:SetText("")
        addPopupInput:ClearFocus()
        RebuildPopupList()
    end

    addPopupBtn:SetScript("OnClick", AddPopupFromInput)

    addPopupInput:SetScript("OnEnterPressed", function(self)
        AddPopupFromInput()
    end)

    RebuildPopupList()

    local reset = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    reset:SetSize(280, 22)
    reset:SetPoint("TOPLEFT", popupListFrame, "BOTTOMLEFT", 0, -6)
    reset:SetText(L["Settings_ResetOK"])
    reset:SetScript("OnClick", function()
        if PT.ConfirmButtons and PT.ConfirmButtons.ResetUserExcludedPopups then
            PT.ConfirmButtons:ResetUserExcludedPopups()
        elseif PT.ConfirmButtons and PT.ConfirmButtons.ResetOKExclusions then
            PT.ConfirmButtons:ResetOKExclusions()
        end

        RebuildPopupList()
    end)

    PT.config.skinningCheckEnabled = PT.config.skinningCheckEnabled ~= false
    PT.config.skinningIconSize = PT.config.skinningIconSize or 50

    local scb = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    scb:SetPoint("TOPLEFT", cbR, "BOTTOMLEFT", 0, -280)
    scb.GetValue = function()
        return PT.config.skinningCheckEnabled ~= false
    end
    scb:SetChecked(scb.GetValue())
    self.checkboxes.skinningCheckEnabled = scb

    scb.text = scb:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    scb.text:SetPoint("LEFT", scb, "RIGHT", 0, 0)
    scb.text:SetText(L["Settings_SkinningCheck"])

    scb:SetScript("OnClick", function(self)
        PT.config.skinningCheckEnabled = self:GetChecked()

        if PT.UpdateVisibility then
            PT:UpdateVisibility()
        end

        RefreshWelcome()
    end)

    local btn = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    btn:SetSize(140, 22)
    btn:SetPoint("LEFT", scb, "RIGHT", 120, 0)
    btn:SetText(L["Settings_SkinningTargets"])
    btn:SetScript("OnClick", function()
        if PT.UI_SkinningTargets and PT.UI_SkinningTargets.Toggle then
            PT.UI_SkinningTargets:Toggle()
        end
    end)

    local cbSkinHide = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbSkinHide:SetPoint("LEFT", btn, "RIGHT", 12, 0)
    cbSkinHide.text:SetText(L["Settings_HideInCombat"] or "Hide in combat")

    cbSkinHide.GetValue = function()
        return PT.config.hideSkinningInCombat ~= false
    end
    cbSkinHide:SetChecked(cbSkinHide.GetValue())
    self.checkboxes.hideSkinningInCombat = cbSkinHide

    cbSkinHide:SetScript("OnClick", function(self)
        PT.config.hideSkinningInCombat = self:GetChecked()
    end)

    local cbSkinInstance = CreateFrame("CheckButton", nil, f, "UICheckButtonTemplate")
    cbSkinInstance:SetPoint("LEFT", cbSkinHide.text, "RIGHT", 12, 0)
    cbSkinInstance.text:SetText(L["Settings_HideInInstance"] or "Hide in instances")

    cbSkinInstance.GetValue = function()
        return PT.config.hideSkinningInInstance == true
    end
    cbSkinInstance:SetChecked(cbSkinInstance.GetValue())
    self.checkboxes.hideSkinningInInstance = cbSkinInstance

    cbSkinInstance:SetScript("OnClick", function(self)
        PT.config.hideSkinningInInstance = self:GetChecked()
    end)

    local sizeLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    sizeLabel:SetPoint("TOPLEFT", scb, "BOTTOMLEFT", 4, -18)
    sizeLabel:SetText(L["Settings_SkinningIconSize"])

    local sizeInput = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
    sizeInput:SetSize(30, 20)
    sizeInput:SetPoint("LEFT", sizeLabel, "RIGHT", 8, 0)
    sizeInput:SetAutoFocus(false)
    sizeInput:SetNumeric(true)
    sizeInput:SetMaxLetters(3)
    sizeInput:SetText(PT.config.skinningIconSize)
    sizeInput:SetCursorPosition(0)

    sizeInput:SetScript("OnEnterPressed", function(self)
        local v = tonumber(self:GetText())
        if not v then
            self:SetText(PT.config.skinningIconSize)
            self:ClearFocus()
            return
        end
        v = math.max(20, math.min(300, math.floor(v)))
        PT.config.skinningIconSize = v
        self:SetText(v)
        self:SetCursorPosition(0)
        if PT.UI_SkinningCheck then
            PT.UI_SkinningCheck:Update()
        end
        self:ClearFocus()
    end)

    self.panel = f
    return f
end

function UI:Refresh()
    if not self.checkboxes then return end

    for _, cb in pairs(self.checkboxes) do
        if cb.GetValue then
            cb:SetChecked(cb.GetValue())
        end
    end

    if self.RefreshDebugButtonText then
        self:RefreshDebugButtonText()
    end

    if PT.WelcomeUI and PT.WelcomeUI.Refresh then
        PT.WelcomeUI:Refresh()
    end
end

function UI:Register()
    if self.category then return end

    local ev = CreateFrame("Frame")
    ev:RegisterEvent("PLAYER_LOGIN")
    ev:SetScript("OnEvent", function()
        if self.category then return end

        local panel = UI:Create()
        local category = Settings.RegisterCanvasLayoutCategory(panel, "AhUI")
        Settings.RegisterAddOnCategory(category)

        UI.category = category
        if UI.RegisterInfoPanelSubcategory then
            UI:RegisterInfoPanelSubcategory()
        end
        if UI.RegisterFarmTrackerSubcategory then
            UI:RegisterFarmTrackerSubcategory()
        end
    end)
end

SLASH_AHUI1 = "/ahui"
SlashCmdList["AHUI"] = function()
    if PT.Settings and PT.Settings.category then
        Settings.OpenToCategory(PT.Settings.category:GetID())
    end
end