-- Portal Authority — options/panel_profiles.lua
-- Profiles settings panel and profile-management dialogs.
--
-- Depends on: PortalAuthority.OptionsInternal shared helpers; PortalAuthority profile APIs
-- Exposes:    PortalAuthority.OptionsInternal.createProfilesPanel
-- DB keys:    PortalAuthorityProfilesDB via profile APIs
-- Events:     none
-- Search key: profiles

PortalAuthority = PortalAuthority or {}

if PortalAuthority.IsSettingsBaselineGateEnabled and PortalAuthority:IsSettingsBaselineGateEnabled() then
    return
end

if not Settings or not Settings.RegisterCanvasLayoutCategory then
    return
end

PortalAuthority.OptionsInternal = PortalAuthority.OptionsInternal or {}
local OptionsInternal = PortalAuthority.OptionsInternal

local settingsSearchRuntime = OptionsInternal.SearchRuntime
local trim = OptionsInternal.trim
local rgba255 = OptionsInternal.rgba255
local unpackColor = OptionsInternal.unpackColor
local applyGlobalFontToObject = OptionsInternal.applyGlobalFontToObject
local getPortalMedia = OptionsInternal.getPortalMedia
local normalizeSoundChoiceValue = OptionsInternal.normalizeSoundChoiceValue
local compareChoiceLabels = OptionsInternal.compareChoiceLabels
local normalizeChoicePathKey = OptionsInternal.normalizeChoicePathKey
local resolveFontChoicePath = OptionsInternal.resolveFontChoicePath
local getSoundChoiceValueKey = OptionsInternal.getSoundChoiceValueKey
local buildFallbackSoundChoices = OptionsInternal.buildFallbackSoundChoices
local getSummonSoundChoices = OptionsInternal.getSummonSoundChoices
local getAvailableFontChoices = OptionsInternal.getAvailableFontChoices
local buildSharedFontPickerChoices = OptionsInternal.buildSharedFontPickerChoices
local SUMMON_SOUND_CHANNEL_CHOICES = OptionsInternal.SUMMON_SOUND_CHANNEL_CHOICES
local debugSettingsLog = OptionsInternal.debugSettingsLog or function() end
local FLAT_SETTINGS_BACKDROP = OptionsInternal.FLAT_SETTINGS_BACKDROP
local SETTINGS_WINDOW_HOSTED_TOP_RHYTHM_NUDGE = OptionsInternal.SETTINGS_WINDOW_HOSTED_TOP_RHYTHM_NUDGE
local SETTINGS_WINDOW_SCROLLBAR_WIDTH = OptionsInternal.SETTINGS_WINDOW_SCROLLBAR_WIDTH
local SETTINGS_WINDOW_SCROLLBAR_GAP = OptionsInternal.SETTINGS_WINDOW_SCROLLBAR_GAP
local SETTINGS_WINDOW_SCROLLBAR_MIN_THUMB_HEIGHT = OptionsInternal.SETTINGS_WINDOW_SCROLLBAR_MIN_THUMB_HEIGHT
local SETTINGS_WINDOW_HOST_COLORS = OptionsInternal.SETTINGS_WINDOW_HOST_COLORS
local SETTINGS_WINDOW_SCROLLBAR_TRACK = OptionsInternal.SETTINGS_WINDOW_SCROLLBAR_TRACK
local SETTINGS_WINDOW_SCROLLBAR_THUMB = OptionsInternal.SETTINGS_WINDOW_SCROLLBAR_THUMB
local SETTINGS_WINDOW_SCROLLBAR_THUMB_HOVER = OptionsInternal.SETTINGS_WINDOW_SCROLLBAR_THUMB_HOVER
local frameIsAlive = OptionsInternal.frameIsAlive
local isDescendedFromFrame = OptionsInternal.isDescendedFromFrame
local markSettingsWindowVisualOptIn = OptionsInternal.markSettingsWindowVisualOptIn
local isUsingCustomSettingsWindowVisualStyle = OptionsInternal.isUsingCustomSettingsWindowVisualStyle
local registerSettingsWindowVisualRefresh = OptionsInternal.registerSettingsWindowVisualRefresh
local setTextureSolidColor = OptionsInternal.setTextureSolidColor
local hideDefaultScrollBarPart = OptionsInternal.hideDefaultScrollBarPart
local getTemplateScrollBar = OptionsInternal.getTemplateScrollBar
local hideDefaultScrollBarChrome = OptionsInternal.hideDefaultScrollBarChrome
local refreshCustomSettingsScrollBarThumb = OptionsInternal.refreshCustomSettingsScrollBarThumb
local settingsScrollRuntime = PortalAuthority._settingsScrollRuntime or OptionsInternal.settingsScrollRuntime
local createStyledFontString = OptionsInternal.createStyledFontString
local createTopRightHeader = OptionsInternal.createTopRightHeader
local PA_SafeBool = OptionsInternal.PA_SafeBool
local getClassHex = OptionsInternal.getClassHex
local createCheckbox = OptionsInternal.createCheckbox
local createActionButton = OptionsInternal.createActionButton
local styleSecondaryActionButtonShared = OptionsInternal.styleSecondaryActionButtonShared
local createNumeric = OptionsInternal.createNumeric
local createDropdown = OptionsInternal.createDropdown
local createDynamicDropdown = OptionsInternal.createDynamicDropdown
local createPremiumSegmentedChoice = OptionsInternal.createPremiumSegmentedChoice
local CreatePicker = OptionsInternal.CreatePicker
local CreateStepperControl = OptionsInternal.CreateStepperControl
local createCanonicalDockFontSizeStepperControl = OptionsInternal.CreateStepperControl or OptionsInternal.createCanonicalDockFontSizeStepperControl
local createTextPlacement = OptionsInternal.createTextPlacement
local setSettingsControlEnabled = OptionsInternal.setSettingsControlEnabled
local setSettingsTextEnabled = OptionsInternal.setSettingsTextEnabled
local createScrollableChild = OptionsInternal.createScrollableChild
local updateScrollBehavior = OptionsInternal.updateScrollBehavior
local withPanelHydration = OptionsInternal.withPanelHydration
local panelHasSizedViewport = OptionsInternal.panelHasSizedViewport
local setSettingsWindowChromeVisible = OptionsInternal.setSettingsWindowChromeVisible
local handleSettingsFirstOpenSizeReady = OptionsInternal.handleSettingsFirstOpenSizeReady
local handleSettingsFirstOpenPanelShow = OptionsInternal.handleSettingsFirstOpenPanelShow
local handleSettingsFirstOpenPanelHide = OptionsInternal.handleSettingsFirstOpenPanelHide
local shouldSuppressSettingsFirstOpenExternalRefresh = OptionsInternal.shouldSuppressSettingsFirstOpenExternalRefresh
local isPanelUsingCustomSettingsWindowHost = OptionsInternal.isPanelUsingCustomSettingsWindowHost
local refreshPanel = OptionsInternal.refreshPanel
local createScrollableTextArea = OptionsInternal.createScrollableTextArea
local createSettingsSectionDescriptor = OptionsInternal.createSettingsSectionDescriptor
local layoutSettingsSectionDescriptor = OptionsInternal.layoutSettingsSectionDescriptor
local registerRefreshCallback = OptionsInternal.registerRefreshCallback
local ensureDatabase = OptionsInternal.ensureDatabase
local IsPointerInsideActivePickerSafeZone = OptionsInternal.IsPointerInsideActivePickerSafeZone
local CloseActivePortalPicker = OptionsInternal.CloseActivePortalPicker
local settingsFirstOpenHost = OptionsInternal.settingsFirstOpenHost
local resetSettingsFirstOpenPanelState = OptionsInternal.resetSettingsFirstOpenPanelState

local function PA_PerfBegin(scopeName, explicitState)
    if PortalAuthority and PortalAuthority.PerfBegin then
        return PortalAuthority:PerfBegin(scopeName, explicitState)
    end
    return nil, nil
end

local function PA_PerfEnd(scopeName, startedAt, stateLabel)
    if startedAt ~= nil and PortalAuthority and PortalAuthority.PerfEnd then
        PortalAuthority:PerfEnd(scopeName, startedAt, stateLabel)
    end
end

local function createProfilesPanel()
    local panel = CreateFrame("Frame")
    panel.name = "Profiles"
    panel._paSearchSectionKey = "profiles"
    panel._paSearchSectionName = panel.name

    panel.EnsureBuilt = function(self)
        if self._initialized then return end
        self._initialized = true
        resetSettingsFirstOpenPanelState(self)
        ensureDatabase()
        settingsSearchRuntime.beginDescriptorCapture(self)

        local scrollFrame, scrollChild = createScrollableChild(self)
        if not scrollFrame or not scrollChild then
            settingsSearchRuntime.endDescriptorCapture(self)
            return
        end
        self._sizingFrame = scrollFrame
        self._profilesScrollFrame = scrollFrame
        self._profilesScrollChild = scrollChild

        -- Profiles-local frozen layout tokens. Preserve values exactly in this pass.
        local PROFILES_LAYOUT = {
            page = {
                min_content_width = 320,
                module_lane_min_width = 320,
                max_module_width = 720,
                top_padding = 20,
                bottom_padding = 52,
                header_left = 16,
                header_bottom_gap = 30,
                content_left = 20,
                content_right = 20,
                module_gap = 12,
                scroll_width_adjust = 6,
            },
            module = {
                accent_width = 2,
                padding_x = 18,
                padding_top = 16,
                padding_bottom = 12,
                title_content_gap = 16,
                helper_min_height = 16,
                helper_pref_width = 300,
                actions_helper_gap = 10,
            },
            controls = {
                min_width = 120,
                segment_width = 240,
                segment_control_height = 24,
                segment_min_width = 92,
                picker_width = 240,
                picker_height = 22,
                shared_picker_menu_height = 220,
                action_button_width = 240,
                danger_button_width = 240,
                button_height = 24,
                button_gap = 8,
                field_gap = 8,
            },
            meta = {
                row_height = 14,
                row_bottom_gap = 8,
                status_size = 6,
                prefix_to_indicator_gap = 8,
                indicator_to_name_gap = 8,
            },
            profile_selection = {
                shared_label_gap = 18,
            },
            actions = {
                status_gap = 10,
                status_min_height = 12,
            },
            danger = {
                title_gap = 18,
                trailing_gap = 2,
            },
            value_button = {
                min_label_width = 20,
                text_left_inset = 8,
                text_right_inset = 18,
                caret_right_inset = 7,
                label_trim_reserve = 26,
            },
            dialog = {
                backdrop_edge_size = 12,
                backdrop_inset = 3,
                width = 476,
                min_height = 196,
                choice_button_width = 260,
                choice_picker_width = 420,
                choice_picker_height = 320,
                confirm_button_width = 140,
                cancel_button_width = 120,
                edit_text_inset_x = 8,
                inner_left = 18,
                inner_right = 18,
                title_top = 14,
                message_top = 40,
                title_body_gap = 14,
                section_gap = 14,
                label_control_gap = 18,
                feedback_gap = 12,
                feedback_min_height = 12,
                edit_height = 22,
                actions_gap = 16,
                button_gap = 10,
                bottom_padding = 18,
                min_title_height = 16,
                min_message_height = 20,
            },
        }

        local widgets = {}
        self._profilesWidgets = widgets
        self._profilesStatusText = ""
        self._profilesStatusColor = { 0.72, 0.72, 0.76, 1 }
        widgets.sectionDescriptor = createSettingsSectionDescriptor(scrollChild, "Manage your saved profiles.")

        local function helperTone(fs, alpha)
            if not fs then return end
            fs:SetTextColor(0.72, 0.72, 0.76, alpha or 1)
        end

        local function setStatus(text, r, g, b, a)
            self._profilesStatusText = tostring(text or "")
            self._profilesStatusColor = {
                tonumber(r) or 0.72,
                tonumber(g) or 0.72,
                tonumber(b) or 0.76,
                tonumber(a) or 1,
            }
            if widgets.status then
                widgets.status:SetText(self._profilesStatusText)
                widgets.status:SetTextColor(unpack(self._profilesStatusColor))
                if self._profilesStatusText == "" then
                    widgets.status:Hide()
                else
                    widgets.status:Show()
                end
            end
            if self._layout then
                self._layout()
            end
        end

        local function createSubtleCard(parent)
            local card = CreateFrame("Frame", nil, parent, "BackdropTemplate")
            card:SetBackdrop({
                bgFile = "Interface\\Buttons\\WHITE8x8",
                edgeFile = "Interface\\Buttons\\WHITE8x8",
                edgeSize = 1,
                insets = { left = 0, right = 0, top = 0, bottom = 0 },
            })
            card:SetBackdropColor(0.06, 0.07, 0.09, 0.42)
            card:SetBackdropBorderColor(0.20, 0.23, 0.29, 0.50)
            return card
        end

        local function createCard(parent, titleText, helperText, accentColor, titleColor)
            local card = createSubtleCard(parent)
            settingsSearchRuntime.markTextContainer(card)
            local accent = card:CreateTexture(nil, "BORDER")
            accent:SetTexture("Interface\\Buttons\\WHITE8x8")
            accent:SetPoint("TOPLEFT", card, "TOPLEFT", 0, 0)
            accent:SetPoint("BOTTOMLEFT", card, "BOTTOMLEFT", 0, 0)
            accent:SetWidth(PROFILES_LAYOUT.module.accent_width)
            accent:SetVertexColor(unpack(accentColor or { 0.27, 0.27, 0.27, 1 }))

            local title = createStyledFontString(card, "ARTWORK", "GameFontHighlightSmall", 10)
            title:SetJustifyH("LEFT")
            title:SetTextColor(unpack(titleColor or { 0.75, 0.77, 0.80, 1 }))
            title:SetText(string.upper(tostring(titleText or "")))

            local helper = createStyledFontString(card, "ARTWORK", "GameFontHighlightSmall", 11)
            helper:SetJustifyH("LEFT")
            helper:SetJustifyV("TOP")
            helper:SetWordWrap(true)
            helper:SetText(tostring(helperText or ""))
            helperTone(helper)

            return {
                frame = card,
                accent = accent,
                title = title,
                helper = helper,
            }
        end

        local function createValueButton(parent, width)
            local button = CreateFrame("Button", nil, parent, "BackdropTemplate")
            button:SetBackdrop({
                bgFile = "Interface\\Buttons\\WHITE8x8",
                edgeFile = "Interface\\Buttons\\WHITE8x8",
                edgeSize = 1,
                insets = { left = 0, right = 0, top = 0, bottom = 0 },
            })
            button:SetBackdropColor(0.10, 0.11, 0.14, 0.95)
            button:SetBackdropBorderColor(0.24, 0.27, 0.32, 1.0)
            button:SetSize(width or PROFILES_LAYOUT.controls.picker_width, PROFILES_LAYOUT.controls.picker_height)
            button:RegisterForClicks("LeftButtonUp")

            local text = createStyledFontString(button, "ARTWORK", "GameFontHighlightSmall", 11)
            text:SetPoint("LEFT", button, "LEFT", PROFILES_LAYOUT.value_button.text_left_inset, 0)
            text:SetPoint("RIGHT", button, "RIGHT", -PROFILES_LAYOUT.value_button.text_right_inset, 0)
            text:SetJustifyH("LEFT")
            text:SetTextColor(0.92, 0.92, 0.92, 1)
            text:SetWordWrap(false)
            if text.SetMaxLines then
                text:SetMaxLines(1)
            end

            local caret = createStyledFontString(button, "ARTWORK", "GameFontHighlightSmall", 10)
            caret:SetPoint("RIGHT", button, "RIGHT", -PROFILES_LAYOUT.value_button.caret_right_inset, 0)
            caret:SetText("v")
            caret:SetTextColor(0.76, 0.76, 0.78, 1)

            local function applyVisual(hovered)
                if hovered then
                    button:SetBackdropColor(0.16, 0.17, 0.20, 0.95)
                    button:SetBackdropBorderColor(0.30, 0.33, 0.38, 1.0)
                    caret:SetTextColor(0.88, 0.88, 0.90, 1)
                else
                    button:SetBackdropColor(0.10, 0.11, 0.14, 0.95)
                    button:SetBackdropBorderColor(0.24, 0.27, 0.32, 1.0)
                    caret:SetTextColor(0.76, 0.76, 0.78, 1)
                end
                if not button:IsEnabled() then
                    button:SetBackdropColor(0.08, 0.09, 0.11, 0.85)
                    button:SetBackdropBorderColor(0.18, 0.20, 0.24, 0.90)
                    text:SetTextColor(0.55, 0.55, 0.58, 1)
                    caret:SetTextColor(0.55, 0.55, 0.58, 1)
                else
                    text:SetTextColor(0.92, 0.92, 0.92, 1)
                end
            end

            function button:SetButtonLabel(labelText)
                local raw = tostring(labelText or "")
                local maxWidth = math.max(PROFILES_LAYOUT.value_button.min_label_width, (button:GetWidth() or 0) - PROFILES_LAYOUT.value_button.label_trim_reserve)
                text:SetWidth(maxWidth)
                text:SetText(raw)
                if text:GetStringWidth() <= maxWidth then
                    return
                end
                local cut = string.len(raw)
                while cut > 0 do
                    local candidate = string.sub(raw, 1, cut) .. "..."
                    text:SetText(candidate)
                    if text:GetStringWidth() <= maxWidth then
                        return
                    end
                    cut = cut - 1
                end
                text:SetText("...")
            end

            button:SetScript("OnEnter", function() applyVisual(true) end)
            button:SetScript("OnLeave", function() applyVisual(false) end)
            button:HookScript("OnShow", function() applyVisual(false) end)
            applyVisual(false)
            return button
        end

        local function skinEditBox(edit)
            if not edit then return end
            if not edit._paPremiumBg then
                edit._paPremiumBg = edit:CreateTexture(nil, "BACKGROUND")
                edit._paPremiumBg:SetAllPoints(edit)
                edit._paPremiumBg:SetTexture("Interface\\Buttons\\WHITE8x8")
                edit._paPremiumBorder = CreateFrame("Frame", nil, edit, "BackdropTemplate")
                edit._paPremiumBorder:SetPoint("TOPLEFT", edit, "TOPLEFT", -1, 1)
                edit._paPremiumBorder:SetPoint("BOTTOMRIGHT", edit, "BOTTOMRIGHT", 1, -1)
                edit._paPremiumBorder:SetBackdrop({
                    edgeFile = "Interface\\Buttons\\WHITE8x8",
                    edgeSize = 1,
                })
                edit._paPremiumBorder:SetBackdropBorderColor(0.24, 0.27, 0.32, 1.0)
            end

            local function applyVisual()
                if edit.Left then edit.Left:SetAlpha(0) end
                if edit.Middle then edit.Middle:SetAlpha(0) end
                if edit.Right then edit.Right:SetAlpha(0) end
                if edit:HasFocus() then
                    edit._paPremiumBg:SetVertexColor(0.12, 0.13, 0.17, 0.95)
                    edit._paPremiumBorder:SetBackdropBorderColor(0.30, 0.33, 0.38, 1.0)
                else
                    edit._paPremiumBg:SetVertexColor(0.10, 0.11, 0.14, 0.95)
                    edit._paPremiumBorder:SetBackdropBorderColor(0.24, 0.27, 0.32, 1.0)
                end
            end

            edit:HookScript("OnShow", applyVisual)
            edit:HookScript("OnEditFocusGained", applyVisual)
            edit:HookScript("OnEditFocusLost", applyVisual)
            applyVisual()
        end

        local function createActionButtonStyled(parent, text, width, styleOpts)
            local btn = createActionButton(parent, text, nil, width)
            styleSecondaryActionButtonShared(btn, styleOpts)
            btn:SetHeight(PROFILES_LAYOUT.controls.button_height)
            if btn.Text then
                applyGlobalFontToObject(btn.Text, 11)
            end
            return btn
        end

        local function refreshModeControlDeferred()
            if widgets.modeControl and widgets.modeControl.Refresh and C_Timer and C_Timer.After then
                C_Timer.After(0, function()
                    if widgets.modeControl and widgets.modeControl.Refresh then
                        widgets.modeControl:Refresh()
                    end
                end)
            end
        end

        local function buildActiveMetadataRow(parent)
            widgets.activeMetaRow = CreateFrame("Frame", nil, parent)
            widgets.activeMetaRow:EnableMouse(false)
            widgets.activeMetaPrefix = createStyledFontString(widgets.activeMetaRow, "ARTWORK", "GameFontHighlightSmall", 11)
            widgets.activeMetaPrefix:SetJustifyH("LEFT")
            widgets.activeMetaPrefix:SetWordWrap(false)
            widgets.activeMetaPrefix:SetTextColor(0.72, 0.72, 0.76, 1)
            if widgets.activeMetaPrefix.SetMaxLines then
                widgets.activeMetaPrefix:SetMaxLines(1)
            end
            widgets.activeMetaIndicator = widgets.activeMetaRow:CreateTexture(nil, "ARTWORK")
            widgets.activeMetaIndicator:SetTexture("Interface\\Buttons\\WHITE8x8")
            widgets.activeMetaIndicator:SetSize(PROFILES_LAYOUT.meta.status_size, PROFILES_LAYOUT.meta.status_size)
            widgets.activeMetaIndicator:SetVertexColor(0.435, 0.682, 0.420, 1)
            widgets.activeMetaName = createStyledFontString(widgets.activeMetaRow, "ARTWORK", "GameFontHighlightSmall", 11)
            widgets.activeMetaName:SetJustifyH("LEFT")
            widgets.activeMetaName:SetWordWrap(false)
            widgets.activeMetaName:SetTextColor(0.94, 0.94, 0.96, 1)
            if widgets.activeMetaName.SetMaxLines then
                widgets.activeMetaName:SetMaxLines(1)
            end
        end

        local function updateActiveMetadataRow(activeInfo)
            local activeDisplay = tostring(activeInfo and activeInfo.displayName or "Default")
            if activeInfo and activeInfo.isShared then
                widgets.activeMetaPrefix:SetText("Using Shared")
            else
                widgets.activeMetaPrefix:SetText("Using Character")
            end
            widgets.activeMetaName:SetText(activeDisplay)
        end

        local function layoutActiveMetadataRow(cardFrame, innerLeft, innerY, rowWidth)
            local row = widgets.activeMetaRow
            local prefix = widgets.activeMetaPrefix
            local indicator = widgets.activeMetaIndicator
            local name = widgets.activeMetaName
            local rowHeight = PROFILES_LAYOUT.meta.row_height

            row:ClearAllPoints()
            row:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
            row:SetSize(rowWidth, rowHeight)

            prefix:ClearAllPoints()
            prefix:SetPoint("LEFT", row, "LEFT", 0, 0)
            local prefixWidth = math.ceil(prefix:GetStringWidth() or 0)

            indicator:ClearAllPoints()
            indicator:SetPoint("LEFT", prefix, "RIGHT", PROFILES_LAYOUT.meta.prefix_to_indicator_gap, 0)

            name:ClearAllPoints()
            name:SetPoint("LEFT", indicator, "RIGHT", PROFILES_LAYOUT.meta.indicator_to_name_gap, 0)
            local availableNameWidth = rowWidth
                - prefixWidth
                - PROFILES_LAYOUT.meta.prefix_to_indicator_gap
                - PROFILES_LAYOUT.meta.status_size
                - PROFILES_LAYOUT.meta.indicator_to_name_gap
            if availableNameWidth < 1 then
                availableNameWidth = 1
            end
            name:SetWidth(availableNameWidth)
            if type(setSingleLineEllipsis) == "function" then
                setSingleLineEllipsis(name, tostring(name:GetText() or ""), availableNameWidth)
            end

            return rowHeight
        end

        local function buildProfileSelectionModule()
            local currentCard = createCard(
                scrollChild,
                "Profile Selection",
                "",
                { 0.27, 0.27, 0.27, 1 },
                { 0.75, 0.77, 0.80, 1 }
            )
            widgets.currentCard = currentCard.frame
            widgets.currentCardTitle = currentCard.title
            widgets.currentCardHelper = currentCard.helper
            buildActiveMetadataRow(currentCard.frame)
            return currentCard
        end

        local function buildActionsModule()
            local actionsCard = createCard(
                scrollChild,
                "Actions",
                "All changes require a UI reload to take effect.",
                { 0.27, 0.27, 0.27, 1 },
                { 0.75, 0.77, 0.80, 1 }
            )
            widgets.actionsCard = actionsCard.frame
            widgets.actionsCardTitle = actionsCard.title
            widgets.actionsCardHelper = actionsCard.helper
            return actionsCard
        end

        local function buildDangerModule()
            local dangerCard = createCard(
                scrollChild,
                "Danger",
                "",
                { 0.54, 0.27, 0.27, 1 },
                { 0.78, 0.53, 0.53, 1 }
            )
            widgets.dangerCard = dangerCard.frame
            widgets.dangerCardTitle = dangerCard.title
            widgets.dangerCardHelper = dangerCard.helper
            return dangerCard
        end

        local currentCard = buildProfileSelectionModule()
        local actionsCard = buildActionsModule()
        local dangerCard = buildDangerModule()

        local function openSwitchToCharacterDialog()
            if self._profilesDialog and self._profilesDialog.Open then
                self._profilesDialog:Open({
                    title = "Switch to Character Profile",
                    message = "This character will start using its own local settings. Portal Authority will reload the UI.",
                    confirmText = "Switch & Reload",
                    onConfirm = function()
                        return PortalAuthority:Profiles_SwitchToCharacterAndReload()
                    end,
                })
            end
        end

        local function openSwitchToSharedDialog()
            if self._profilesDialog and self._profilesDialog.Open then
                local sharedChoices = PortalAuthority:Profiles_GetSharedChoices()
                local pickerOptions = {}
                local defaultValue = PortalAuthority:GetProfilesCanonicalDefaultID()
                for _, choice in ipairs(sharedChoices) do
                    pickerOptions[#pickerOptions + 1] = {
                        value = choice.id,
                        label = choice.label,
                    }
                end
                self._profilesDialog:Open({
                    title = "Switch to Shared Profile",
                    message = "Choose which shared profile this character should use. Portal Authority will reload the UI.",
                    confirmText = "Switch & Reload",
                    choiceLabel = "Shared Profile",
                    choiceOptions = pickerOptions,
                    choiceValue = defaultValue,
                    onConfirm = function(_, selectedValue)
                        return PortalAuthority:Profiles_SwitchToSharedAndReload(selectedValue)
                    end,
                })
            end
        end

        local function buildModeControl(parent)
            widgets.modeControl = createPremiumSegmentedChoice(parent, "", nil, {
                { label = "Character", value = "character" },
                { label = "Shared", value = "shared" },
            }, function(value)
                local activeInfo = PortalAuthority and PortalAuthority.Profiles_GetActiveInfo and PortalAuthority:Profiles_GetActiveInfo() or nil
                if not activeInfo or value == activeInfo.kind then
                    refreshModeControlDeferred()
                    return
                end

                if value == "character" then
                    openSwitchToCharacterDialog()
                else
                    openSwitchToSharedDialog()
                end

                refreshModeControlDeferred()
            end, {
                getValue = function()
                    local activeInfo = PortalAuthority and PortalAuthority.Profiles_GetActiveInfo and PortalAuthority:Profiles_GetActiveInfo() or nil
                    return activeInfo and activeInfo.kind or "shared"
                end,
                setValue = function() end,
                minWidth = PROFILES_LAYOUT.controls.segment_width,
                controlHeight = PROFILES_LAYOUT.controls.segment_control_height,
                segmentMinWidth = PROFILES_LAYOUT.controls.segment_min_width,
                selectionVariant = "lock_meta",
            })
            if widgets.modeControl and widgets.modeControl.label then
                widgets.modeControl.label:SetText("")
                widgets.modeControl.label:Hide()
            end
        end

        local function buildSharedPicker(parent)
            widgets.sharedPickerLabel = createStyledFontString(parent, "ARTWORK", "GameFontHighlight", 12)
            widgets.sharedPickerLabel:SetText("Shared Profile")
            widgets.sharedPickerLabel:SetTextColor(0.75, 0.77, 0.80, 1)
            widgets.sharedPicker = createValueButton(parent, PROFILES_LAYOUT.controls.picker_width)
            widgets.sharedPickerPicker = CreatePicker(UIParent, {}, function(value, option)
                local selectedValue = trim(tostring(value or ""))
                local activeInfo = PortalAuthority:Profiles_GetActiveInfo()
                if selectedValue == "" or selectedValue == tostring(activeInfo and activeInfo.sharedID or "") then
                    return
                end
                local displayName = option and option.label or PortalAuthority:Profiles_GetSharedDisplayName(selectedValue) or "Shared Profile"
                if self._profilesDialog and self._profilesDialog.Open then
                    self._profilesDialog:Open({
                        title = "Switch Shared Profile",
                        message = string.format("Switch this character to \"%s\"? Portal Authority will reload the UI.", tostring(displayName)),
                        confirmText = "Switch & Reload",
                        onConfirm = function()
                            return PortalAuthority:Profiles_SwitchToSharedAndReload(selectedValue)
                        end,
                    })
                end
            end, {
                width = PROFILES_LAYOUT.controls.picker_width,
                height = PROFILES_LAYOUT.controls.shared_picker_menu_height,
                noSearch = true,
                hideTitle = true,
                showClearButton = false,
                showCloseButton = false,
                ellipsizeRows = true,
                footerFlowWithRows = true,
                footerHint = "Only user-facing profile names are shown here.",
            })
            widgets.sharedPicker:SetScript("OnClick", function(btn)
                if ACTIVE_PORTAL_PICKER == widgets.sharedPickerPicker and widgets.sharedPickerPicker:IsShown() then
                    widgets.sharedPickerPicker:Close()
                    return
                end
                local sharedChoices = PortalAuthority:Profiles_GetSharedChoices()
                local options = {}
                for _, choice in ipairs(sharedChoices) do
                    options[#options + 1] = {
                        value = choice.id,
                        label = choice.label,
                    }
                end
                widgets.sharedPickerPicker:SetOptions(options)
                widgets.sharedPickerPicker:Open(btn)
            end)
        end

        local function buildActionsControls(parent)
            widgets.createSharedButton = createActionButtonStyled(parent, "Save as Shared Profile", PROFILES_LAYOUT.controls.action_button_width)
            widgets.copyFromButton = createActionButtonStyled(parent, "Copy from Profile", PROFILES_LAYOUT.controls.action_button_width)
            widgets.resetProfileButton = createActionButtonStyled(parent, "Reset Profile", PROFILES_LAYOUT.controls.action_button_width)

            widgets.status = createStyledFontString(parent, "ARTWORK", "GameFontHighlightSmall", 10)
            widgets.status:SetJustifyH("LEFT")
            widgets.status:SetWordWrap(true)
            helperTone(widgets.status)
            widgets.status:Hide()
        end

        local function buildDangerControls(parent)
            widgets.renameSharedButton = createActionButtonStyled(parent, "Rename Profile", PROFILES_LAYOUT.controls.danger_button_width, {
                baseBg = { 0.11, 0.08, 0.09, 0.95 },
                hoverBg = { 0.15, 0.10, 0.11, 0.95 },
                pressedBg = { 0.09, 0.06, 0.07, 0.96 },
                baseBorder = { 0.30, 0.18, 0.20, 0.90 },
                hoverBorder = { 0.38, 0.22, 0.24, 0.95 },
                pressedBorder = { 0.34, 0.20, 0.22, 0.90 },
                textColor = { 0.92, 0.82, 0.83, 1 },
            })
            widgets.deleteSharedButton = createActionButtonStyled(parent, "Delete Profile", PROFILES_LAYOUT.controls.danger_button_width, {
                baseBg = { 0.13, 0.08, 0.09, 0.95 },
                hoverBg = { 0.18, 0.10, 0.11, 0.95 },
                pressedBg = { 0.10, 0.06, 0.07, 0.96 },
                baseBorder = { 0.34, 0.18, 0.20, 0.90 },
                hoverBorder = { 0.44, 0.22, 0.24, 0.95 },
                pressedBorder = { 0.40, 0.20, 0.22, 0.90 },
                textColor = { 0.95, 0.84, 0.85, 1 },
            })
        end

        buildModeControl(currentCard.frame)
        buildSharedPicker(currentCard.frame)
        buildActionsControls(actionsCard.frame)
        buildDangerControls(dangerCard.frame)

        local refreshProfilesBindings = nil
        local layoutProfiles = nil
        local refreshAndLayoutProfiles = nil

        local dialog = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")
        dialog:SetBackdrop({
            bgFile = "Interface\\Buttons\\WHITE8x8",
            edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
            edgeSize = PROFILES_LAYOUT.dialog.backdrop_edge_size,
            insets = {
                left = PROFILES_LAYOUT.dialog.backdrop_inset,
                right = PROFILES_LAYOUT.dialog.backdrop_inset,
                top = PROFILES_LAYOUT.dialog.backdrop_inset,
                bottom = PROFILES_LAYOUT.dialog.backdrop_inset,
            },
        })
        dialog:SetBackdropColor(0.05, 0.06, 0.08, 0.985)
        dialog:SetBackdropBorderColor(0.32, 0.35, 0.40, 1)
        dialog:SetSize(PROFILES_LAYOUT.dialog.width, PROFILES_LAYOUT.dialog.min_height)
        dialog:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
        dialog:SetFrameStrata("DIALOG")
        dialog:SetToplevel(true)
        dialog:SetClampedToScreen(true)
        dialog:EnableMouse(true)
        dialog:Hide()
        self._profilesDialog = dialog

        dialog.title = createStyledFontString(dialog, "ARTWORK", "GameFontHighlight", 12)
        dialog.title:SetPoint("TOPLEFT", dialog, "TOPLEFT", PROFILES_LAYOUT.dialog.inner_left, -PROFILES_LAYOUT.dialog.title_top)
        dialog.title:SetTextColor(1, 0.82, 0, 1)
        dialog.title:SetJustifyH("LEFT")

        dialog.message = createStyledFontString(dialog, "ARTWORK", "GameFontHighlightSmall", 11)
        dialog.message:SetPoint("TOPLEFT", dialog, "TOPLEFT", PROFILES_LAYOUT.dialog.inner_left, -PROFILES_LAYOUT.dialog.message_top)
        dialog.message:SetPoint("TOPRIGHT", dialog, "TOPRIGHT", -PROFILES_LAYOUT.dialog.inner_right, -PROFILES_LAYOUT.dialog.message_top)
        dialog.message:SetJustifyH("LEFT")
        dialog.message:SetJustifyV("TOP")
        dialog.message:SetWordWrap(true)
        helperTone(dialog.message)

        dialog.choiceLabel = createStyledFontString(dialog, "ARTWORK", "GameFontHighlight", 12)
        dialog.choiceLabel:SetText("")
        dialog.choiceButton = createValueButton(dialog, PROFILES_LAYOUT.dialog.choice_button_width)

        dialog.editLabel = createStyledFontString(dialog, "ARTWORK", "GameFontHighlight", 12)
        dialog.editLabel:SetText("")
        dialog.edit = CreateFrame("EditBox", nil, dialog, "InputBoxTemplate")
        dialog.edit:SetAutoFocus(false)
        dialog.edit:SetTextInsets(PROFILES_LAYOUT.dialog.edit_text_inset_x, PROFILES_LAYOUT.dialog.edit_text_inset_x, 0, 0)
        dialog.edit:SetTextColor(1, 1, 1, 1)
        dialog.edit:SetHighlightColor(1, 1, 1, 0.25)
        dialog.edit:SetMaxLetters(80)
        applyGlobalFontToObject(dialog.edit, 11)
        skinEditBox(dialog.edit)

        dialog.feedback = createStyledFontString(dialog, "ARTWORK", "GameFontHighlightSmall", 10)
        dialog.feedback:SetJustifyH("LEFT")
        dialog.feedback:SetWordWrap(true)
        dialog.feedback:SetText("")
        dialog.feedback:Hide()

        dialog.confirm = createActionButtonStyled(dialog, "Confirm", PROFILES_LAYOUT.dialog.confirm_button_width)
        dialog.cancel = createActionButtonStyled(dialog, "Cancel", PROFILES_LAYOUT.dialog.cancel_button_width)

        dialog.choicePicker = CreatePicker(UIParent, {}, function(value, option)
            dialog._selectedChoiceValue = value
            dialog._selectedChoiceLabel = option and option.label or ""
            dialog.choiceButton:SetButtonLabel(dialog._selectedChoiceLabel ~= "" and dialog._selectedChoiceLabel or "Select profile")
            dialog.feedback:Hide()
            if dialog._layout then
                dialog._layout()
            end
        end, {
            title = "Choose Profile",
            searchHint = "Search profiles",
            width = PROFILES_LAYOUT.dialog.choice_picker_width,
            height = PROFILES_LAYOUT.dialog.choice_picker_height,
            footerHint = "Only user-facing profile names are shown here.",
        })

        function dialog:Close()
            if self.choicePicker and self.choicePicker.Close then
                self.choicePicker:Close()
            end
            self._onConfirm = nil
            self._selectedChoiceValue = nil
            self._selectedChoiceLabel = ""
            self.feedback:SetText("")
            self.feedback:Hide()
            self:Hide()
        end

        function dialog:Open(spec)
            spec = type(spec) == "table" and spec or {}
            self._onConfirm = spec.onConfirm
            self._selectedChoiceValue = spec.choiceValue
            self._selectedChoiceLabel = spec.choiceLabelText or ""
            self.title:SetText(tostring(spec.title or "Profiles"))
            self.message:SetText(tostring(spec.message or ""))
            self.confirm:SetText(tostring(spec.confirmText or "Confirm"))
            self.cancel:SetText(tostring(spec.cancelText or "Cancel"))
            if self.confirm.Text then applyGlobalFontToObject(self.confirm.Text, 11) end
            if self.cancel.Text then applyGlobalFontToObject(self.cancel.Text, 11) end

            self._hasChoice = spec.choiceOptions ~= nil
            self._hasEdit = spec.editLabel ~= nil

            if self._hasChoice then
                self.choiceLabel:SetText(tostring(spec.choiceLabel or "Profile"))
                self.choiceLabel:Show()
                self.choiceButton:Show()
                self.choicePicker:SetOptions(type(spec.choiceOptions) == "table" and spec.choiceOptions or {})
                local labelText = tostring(spec.choiceLabelText or "")
                if labelText == "" and spec.choiceValue ~= nil then
                    for _, option in ipairs(spec.choiceOptions or {}) do
                        if option.value == spec.choiceValue then
                            labelText = tostring(option.label or "")
                            break
                        end
                    end
                end
                if labelText == "" then
                    labelText = "Select profile"
                end
                self.choiceButton:SetButtonLabel(labelText)
                self.choiceButton:SetScript("OnClick", function(btn)
                    self.choicePicker:Open(btn)
                end)
            else
                self.choiceLabel:Hide()
                self.choiceButton:Hide()
            end

            if self._hasEdit then
                self.editLabel:SetText(tostring(spec.editLabel or "Name"))
                self.editLabel:Show()
                self.edit:Show()
                self.edit:SetText(tostring(spec.editValue or ""))
                self.edit:SetCursorPosition(string.len(self.edit:GetText() or ""))
                self.edit:SetMaxLetters(math.max(1, tonumber(spec.editMaxLetters) or 80))
            else
                self.editLabel:Hide()
                self.edit:Hide()
                self.edit:SetText("")
            end

            self.feedback:SetText("")
            self.feedback:Hide()
            self:Show()
            if self._hasEdit then
                self.edit:SetFocus()
                self.edit:HighlightText(0, string.len(self.edit:GetText() or ""))
            else
                self.edit:ClearFocus()
            end
            if self._layout then
                self._layout()
            end
        end

        local function layoutDialogChoiceSection(innerLeft, y)
            if not dialog._hasChoice then
                return y
            end
            y = y - PROFILES_LAYOUT.dialog.section_gap
            dialog.choiceLabel:ClearAllPoints()
            dialog.choiceLabel:SetPoint("TOPLEFT", dialog, "TOPLEFT", innerLeft, y)
            y = y - PROFILES_LAYOUT.dialog.label_control_gap
            dialog.choiceButton:ClearAllPoints()
            dialog.choiceButton:SetPoint("TOPLEFT", dialog, "TOPLEFT", innerLeft, y)
            return y - PROFILES_LAYOUT.controls.picker_height
        end

        local function layoutDialogEditSection(innerLeft, width, y)
            if not dialog._hasEdit then
                return y
            end
            y = y - PROFILES_LAYOUT.dialog.section_gap
            dialog.editLabel:ClearAllPoints()
            dialog.editLabel:SetPoint("TOPLEFT", dialog, "TOPLEFT", innerLeft, y)
            y = y - PROFILES_LAYOUT.dialog.label_control_gap
            dialog.edit:ClearAllPoints()
            dialog.edit:SetPoint("TOPLEFT", dialog, "TOPLEFT", innerLeft, y)
            dialog.edit:SetWidth(width)
            dialog.edit:SetHeight(PROFILES_LAYOUT.dialog.edit_height)
            return y - PROFILES_LAYOUT.dialog.edit_height
        end

        local function layoutDialogFeedbackSection(innerLeft, innerRight, y)
            local feedbackText = trim(dialog.feedback:GetText() or "")
            if not dialog.feedback:IsShown() or feedbackText == "" then
                return y
            end
            y = y - PROFILES_LAYOUT.dialog.feedback_gap
            dialog.feedback:ClearAllPoints()
            dialog.feedback:SetPoint("TOPLEFT", dialog, "TOPLEFT", innerLeft, y)
            dialog.feedback:SetPoint("TOPRIGHT", dialog, "TOPRIGHT", -innerRight, y)
            return y - math.max(PROFILES_LAYOUT.dialog.feedback_min_height, dialog.feedback:GetStringHeight())
        end

        dialog._layout = function()
            local innerLeft = PROFILES_LAYOUT.dialog.inner_left
            local innerRight = PROFILES_LAYOUT.dialog.inner_right
            local topPad = PROFILES_LAYOUT.dialog.title_top
            local titleGap = PROFILES_LAYOUT.dialog.title_body_gap
            local actionsGap = PROFILES_LAYOUT.dialog.actions_gap
            local bottomPad = PROFILES_LAYOUT.dialog.bottom_padding
            local minHeight = PROFILES_LAYOUT.dialog.min_height
            local width = (dialog:GetWidth() or PROFILES_LAYOUT.dialog.width) - innerLeft - innerRight
            local titleH = math.max(PROFILES_LAYOUT.dialog.min_title_height, dialog.title:GetStringHeight() or 0)
            local y = -(topPad + titleH + titleGap)

            dialog.message:ClearAllPoints()
            dialog.message:SetPoint("TOPLEFT", dialog, "TOPLEFT", innerLeft, y)
            dialog.message:SetWidth(width)
            local messageH = math.max(PROFILES_LAYOUT.dialog.min_message_height, dialog.message:GetStringHeight())
            y = y - messageH
            y = layoutDialogChoiceSection(innerLeft, y)
            y = layoutDialogEditSection(innerLeft, width, y)
            y = layoutDialogFeedbackSection(innerLeft, innerRight, y)

            local buttonRowH = math.max(
                dialog.confirm:GetHeight() or PROFILES_LAYOUT.controls.button_height,
                dialog.cancel:GetHeight() or PROFILES_LAYOUT.controls.button_height
            )
            local totalHeight = math.max(minHeight, (-y) + actionsGap + buttonRowH + bottomPad)
            dialog:SetHeight(totalHeight)

            dialog.cancel:ClearAllPoints()
            dialog.cancel:SetPoint("BOTTOMRIGHT", dialog, "BOTTOMRIGHT", -innerRight, bottomPad)
            dialog.confirm:ClearAllPoints()
            dialog.confirm:SetPoint("RIGHT", dialog.cancel, "LEFT", -PROFILES_LAYOUT.dialog.button_gap, 0)
        end

        local function wireDialogControls()
            dialog.confirm:SetScript("OnClick", function()
                local rawEditValue = dialog._hasEdit and dialog.edit:GetText() or nil
                local selectedValue = dialog._hasChoice and dialog._selectedChoiceValue or nil
                local ok, err = true, nil
                if dialog._hasChoice and (selectedValue == nil or tostring(selectedValue) == "") then
                    ok, err = false, "Select a profile first."
                elseif dialog._onConfirm then
                    ok, err = dialog._onConfirm(rawEditValue, selectedValue)
                end
                if ok == false then
                    dialog.feedback:SetText(tostring(err or "Profile operation failed."))
                    dialog.feedback:SetTextColor(1.0, 0.36, 0.36, 1)
                    dialog.feedback:Show()
                    if dialog._layout then
                        dialog._layout()
                    end
                    refreshModeControlDeferred()
                    return
                end
                dialog:Close()
                if refreshAndLayoutProfiles then
                    refreshAndLayoutProfiles()
                end
            end)
            dialog.cancel:SetScript("OnClick", function()
                dialog:Close()
                refreshModeControlDeferred()
            end)
            dialog.edit:SetScript("OnEscapePressed", function() dialog.cancel:Click() end)
            dialog.edit:SetScript("OnEnterPressed", function() dialog.confirm:Click() end)
        end

        wireDialogControls()

        local function wireActionButtons()
            widgets.createSharedButton:SetScript("OnClick", function()
                dialog:Open({
                    title = "Create Shared Profile",
                    message = "Save the current runtime settings as a new shared profile. Portal Authority will reload the UI.",
                    confirmText = "Create & Reload",
                    editLabel = "Shared Profile Name",
                    editValue = "",
                    editMaxLetters = 80,
                    onConfirm = function(rawName)
                        return PortalAuthority:Profiles_CreateSharedAndSwitch(rawName)
                    end,
                })
            end)

            widgets.copyFromButton:SetScript("OnClick", function()
                local copyChoices = PortalAuthority:Profiles_GetCopySourceChoices()
                if not copyChoices or #copyChoices == 0 then
                    setStatus("No other profile is available to copy from.", 1.0, 0.36, 0.36, 1)
                    return
                end
                local pickerOptions = {}
                local defaultValue = nil
                for index, choice in ipairs(copyChoices) do
                    local encoded = string.format("%s:%s", tostring(choice.kind or ""), tostring(choice.id or ""))
                    pickerOptions[#pickerOptions + 1] = {
                        value = encoded,
                        label = choice.label,
                    }
                    if index == 1 then
                        defaultValue = encoded
                    end
                end
                dialog:Open({
                    title = "Copy From Another Profile",
                    message = "Copy another profile into the current active profile. Portal Authority will reload the UI.",
                    confirmText = "Copy & Reload",
                    choiceLabel = "Source Profile",
                    choiceOptions = pickerOptions,
                    choiceValue = defaultValue,
                    onConfirm = function(_, encodedValue)
                        local kind, id = tostring(encodedValue or ""):match("^(.-):(.*)$")
                        if kind ~= "shared" and kind ~= "character" then
                            return false, "Source profile is unavailable."
                        end
                        if kind == "character" then
                            id = nil
                        end
                        return PortalAuthority:Profiles_CopyIntoActiveAndReload(kind, id)
                    end,
                })
            end)

            widgets.resetProfileButton:SetScript("OnClick", function()
                local activeInfo = PortalAuthority:Profiles_GetActiveInfo()
                local message = "Reset the current profile to defaults? Portal Authority will reload the UI."
                if activeInfo and activeInfo.isShared then
                    message = "Reset this shared profile to defaults? This affects every character using it, and Portal Authority will reload the UI."
                end
                dialog:Open({
                    title = "Reset Current Profile",
                    message = message,
                    confirmText = "Reset & Reload",
                    onConfirm = function()
                        return PortalAuthority:Profiles_ResetActiveAndReload()
                    end,
                })
            end)

            widgets.renameSharedButton:SetScript("OnClick", function()
                local activeInfo = PortalAuthority:Profiles_GetActiveInfo()
                if not activeInfo or not activeInfo.canRenameShared then
                    return
                end
                dialog:Open({
                    title = "Rename Shared Profile",
                    message = "Update the display name for this shared profile.",
                    confirmText = "Rename",
                    editLabel = "Shared Profile Name",
                    editValue = activeInfo.displayName or "",
                    editMaxLetters = 80,
                    onConfirm = function(rawName)
                        local ok, err = PortalAuthority:Profiles_RenameShared(activeInfo.sharedID, rawName)
                        if ok == false then
                            return false, err
                        end
                        setStatus("Shared profile renamed.", 0.66, 0.86, 0.70, 1)
                        return true
                    end,
                })
            end)

            widgets.deleteSharedButton:SetScript("OnClick", function()
                local activeInfo = PortalAuthority:Profiles_GetActiveInfo()
                if not activeInfo or not activeInfo.canDeleteShared then
                    return
                end
                dialog:Open({
                    title = "Delete Shared Profile",
                    message = string.format("Delete \"%s\"? This character will fall back to Default and Portal Authority will reload the UI.", tostring(activeInfo.displayName or "Shared Profile")),
                    confirmText = "Delete & Reload",
                    onConfirm = function()
                        return PortalAuthority:Profiles_DeleteShared(activeInfo.sharedID)
                    end,
                })
            end)
        end

        wireActionButtons()

        local function refreshSharedPicker(activeInfo)
            if activeInfo.isShared then
                widgets.sharedPickerLabel:Show()
                widgets.sharedPicker:Show()
                widgets.sharedPicker:SetButtonLabel(tostring(activeInfo.displayName or "Default"))
                if widgets.sharedPickerPicker and widgets.sharedPickerPicker.SetSelectedValue then
                    widgets.sharedPickerPicker:SetSelectedValue(activeInfo.sharedID)
                end
            else
                widgets.sharedPickerLabel:Hide()
                widgets.sharedPicker:Hide()
                if ACTIVE_PORTAL_PICKER == widgets.sharedPickerPicker and widgets.sharedPickerPicker and widgets.sharedPickerPicker.Close then
                    widgets.sharedPickerPicker:Close()
                end
            end
        end

        local function refreshProfileSelection(activeInfo)
            updateActiveMetadataRow(activeInfo)
            if activeInfo.isShared then
                widgets.currentCardHelper:SetText("Used by any character assigned to this shared profile.")
            else
                widgets.currentCardHelper:SetText("Stored only for this character.")
            end
            widgets.currentCardHelper:Show()
            refreshSharedPicker(activeInfo)
        end

        local function refreshActionsModule()
            if widgets.actionsCardHelper then
                widgets.actionsCardHelper:SetText("All changes require a UI reload to take effect.")
                widgets.actionsCardHelper:Show()
            end
            if widgets.status then
                widgets.status:SetText(self._profilesStatusText)
                widgets.status:SetTextColor(unpack(self._profilesStatusColor))
                if self._profilesStatusText == "" then
                    widgets.status:Hide()
                else
                    widgets.status:Show()
                end
            end
        end

        local function refreshDangerModule(activeInfo)
            if activeInfo.canDeleteShared then
                widgets.dangerCard:Show()
            else
                widgets.dangerCard:Hide()
            end
            if widgets.dangerCardHelper then
                widgets.dangerCardHelper:SetText("")
                widgets.dangerCardHelper:Hide()
            end
        end

        refreshProfilesBindings = function(activeInfo)
            activeInfo = activeInfo or (PortalAuthority and PortalAuthority.Profiles_GetActiveInfo and PortalAuthority:Profiles_GetActiveInfo() or nil)
            if not activeInfo then
                return nil
            end
            refreshProfileSelection(activeInfo)
            if widgets.modeControl and widgets.modeControl.Refresh then
                widgets.modeControl:Refresh()
            end
            refreshDangerModule(activeInfo)
            refreshActionsModule()
            return activeInfo
        end

        local function ensureProfilesHeader()
            local header = widgets.header
            if not header then
                header = createStyledFontString(scrollChild, "ARTWORK", "GameFontNormalLarge", 14)
                header:SetText("|cffffd100Profiles|r")
                header:SetJustifyH("LEFT")
                widgets.header = header
            end
            return header
        end

        local function computeHelperWidth(innerWidth, controlW)
            return math.max(1, math.min(innerWidth, math.max(controlW, PROFILES_LAYOUT.module.helper_pref_width)))
        end

        local function layoutSharedPickerSection(cardFrame, innerLeft, innerY, controlW, currentInfo)
            if currentInfo and currentInfo.isShared then
                widgets.sharedPickerLabel:ClearAllPoints()
                widgets.sharedPickerLabel:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
                widgets.sharedPickerLabel:SetWidth(controlW)
                innerY = innerY - PROFILES_LAYOUT.profile_selection.shared_label_gap
                widgets.sharedPicker:ClearAllPoints()
                widgets.sharedPicker:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
                widgets.sharedPicker:SetWidth(controlW)
                widgets.sharedPicker:SetButtonLabel(tostring(currentInfo.displayName or "Default"))
                innerY = innerY - PROFILES_LAYOUT.controls.picker_height - PROFILES_LAYOUT.controls.field_gap
            end
            return innerY
        end

        local function layoutProfileSelectionModule(cardX, cardY, cardW, currentInfo)
            local cardFrame = widgets.currentCard
            local title = widgets.currentCardTitle
            local helper = widgets.currentCardHelper
            local controlW = math.min(
                PROFILES_LAYOUT.controls.segment_width,
                math.max(PROFILES_LAYOUT.controls.min_width, cardW - (PROFILES_LAYOUT.module.padding_x * 2))
            )
            local innerLeft = PROFILES_LAYOUT.module.padding_x
            local innerWidth = cardW - (PROFILES_LAYOUT.module.padding_x * 2)
            local innerY = -PROFILES_LAYOUT.module.padding_top

            cardFrame:ClearAllPoints()
            cardFrame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", cardX, cardY)
            cardFrame:SetWidth(cardW)

            title:ClearAllPoints()
            title:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
            innerY = innerY - PROFILES_LAYOUT.module.title_content_gap

            local metaH = layoutActiveMetadataRow(cardFrame, innerLeft, innerY, math.min(innerWidth, controlW))
            innerY = innerY - metaH - PROFILES_LAYOUT.meta.row_bottom_gap

            widgets.modeControl.control:ClearAllPoints()
            widgets.modeControl.control:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
            widgets.modeControl:Layout(controlW)
            innerY = innerY - PROFILES_LAYOUT.controls.segment_control_height - PROFILES_LAYOUT.controls.field_gap

            innerY = layoutSharedPickerSection(cardFrame, innerLeft, innerY, controlW, currentInfo)

            local helperText = trim(helper:GetText() or "")
            if helperText ~= "" then
                local helperW = computeHelperWidth(innerWidth, controlW)
                helper:Show()
                helper:ClearAllPoints()
                helper:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
                helper:SetWidth(helperW)
                innerY = innerY - math.max(PROFILES_LAYOUT.module.helper_min_height, helper:GetStringHeight())
            else
                helper:Hide()
            end

            local cardH = (-innerY) + PROFILES_LAYOUT.module.padding_bottom
            cardFrame:SetHeight(cardH)
            return cardH
        end

        local function layoutActionsModule(cardX, cardY, cardW)
            local cardFrame = widgets.actionsCard
            local title = widgets.actionsCardTitle
            local helper = widgets.actionsCardHelper
            local controlW = math.min(
                PROFILES_LAYOUT.controls.action_button_width,
                math.max(PROFILES_LAYOUT.controls.min_width, cardW - (PROFILES_LAYOUT.module.padding_x * 2))
            )
            local innerLeft = PROFILES_LAYOUT.module.padding_x
            local innerY = -PROFILES_LAYOUT.module.padding_top

            cardFrame:ClearAllPoints()
            cardFrame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", cardX, cardY)
            cardFrame:SetWidth(cardW)

            title:ClearAllPoints()
            title:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
            innerY = innerY - PROFILES_LAYOUT.module.title_content_gap

            helper:Show()
            helper:ClearAllPoints()
            helper:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
            helper:SetWidth(computeHelperWidth(cardW - (PROFILES_LAYOUT.module.padding_x * 2), controlW))
            innerY = innerY - math.max(PROFILES_LAYOUT.module.helper_min_height, helper:GetStringHeight()) - PROFILES_LAYOUT.module.actions_helper_gap

            widgets.createSharedButton:ClearAllPoints()
            widgets.createSharedButton:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
            widgets.createSharedButton:SetWidth(controlW)
            innerY = innerY - PROFILES_LAYOUT.controls.button_height - PROFILES_LAYOUT.controls.button_gap

            widgets.copyFromButton:ClearAllPoints()
            widgets.copyFromButton:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
            widgets.copyFromButton:SetWidth(controlW)
            innerY = innerY - PROFILES_LAYOUT.controls.button_height - PROFILES_LAYOUT.controls.button_gap

            widgets.resetProfileButton:ClearAllPoints()
            widgets.resetProfileButton:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
            widgets.resetProfileButton:SetWidth(controlW)
            innerY = innerY - PROFILES_LAYOUT.controls.button_height - PROFILES_LAYOUT.actions.status_gap

            widgets.status:ClearAllPoints()
            widgets.status:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
            widgets.status:SetWidth(controlW)
            if widgets.status:IsShown() then
                innerY = innerY - math.max(PROFILES_LAYOUT.actions.status_min_height, widgets.status:GetStringHeight())
            end

            local cardH = (-innerY) + PROFILES_LAYOUT.module.padding_bottom
            cardFrame:SetHeight(cardH)
            return cardH
        end

        local function layoutDangerModule(cardX, cardY, cardW, controlX)
            local cardFrame = widgets.dangerCard
            local title = widgets.dangerCardTitle
            local controlW = PROFILES_LAYOUT.controls.danger_button_width
            local innerLeft = PROFILES_LAYOUT.module.padding_x
            local innerY = -PROFILES_LAYOUT.module.padding_top

            cardFrame:ClearAllPoints()
            cardFrame:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", cardX, cardY)
            cardFrame:SetWidth(cardW)

            title:ClearAllPoints()
            title:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", innerLeft, innerY)
            innerY = innerY - PROFILES_LAYOUT.danger.title_gap

            widgets.renameSharedButton:ClearAllPoints()
            widgets.renameSharedButton:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", controlX, innerY)
            widgets.renameSharedButton:SetWidth(controlW)
            innerY = innerY - PROFILES_LAYOUT.controls.button_height - PROFILES_LAYOUT.controls.button_gap

            widgets.deleteSharedButton:ClearAllPoints()
            widgets.deleteSharedButton:SetPoint("TOPLEFT", cardFrame, "TOPLEFT", controlX, innerY)
            widgets.deleteSharedButton:SetWidth(controlW)
            innerY = innerY - PROFILES_LAYOUT.controls.button_height - PROFILES_LAYOUT.danger.trailing_gap

            local cardH = (-innerY) + PROFILES_LAYOUT.module.padding_bottom
            cardFrame:SetHeight(cardH)
            return cardH
        end

        layoutProfiles = function(currentInfo)
            currentInfo = currentInfo or (PortalAuthority and PortalAuthority.Profiles_GetActiveInfo and PortalAuthority:Profiles_GetActiveInfo() or nil)
            local scrollW = (scrollFrame:GetWidth() or 0)
            local contentW = math.max(PROFILES_LAYOUT.page.min_content_width, scrollW - PROFILES_LAYOUT.page.scroll_width_adjust)
            local useHostedChrome = isPanelUsingCustomSettingsWindowHost(self)
            scrollChild:SetWidth(contentW)

            local headerWidth = math.max(1, contentW - PROFILES_LAYOUT.page.header_left - PROFILES_LAYOUT.page.content_right)
            local left = PROFILES_LAYOUT.page.content_left
            local right = PROFILES_LAYOUT.page.content_right
            local sectionSpan = math.max(PROFILES_LAYOUT.page.module_lane_min_width, contentW - left - right)
            local y = -PROFILES_LAYOUT.page.top_padding
            if useHostedChrome then
                y = y - SETTINGS_WINDOW_HOSTED_TOP_RHYTHM_NUDGE
            end

            local header = ensureProfilesHeader()
            if useHostedChrome then
                setSettingsWindowChromeVisible(header, false, scrollChild)
                setSettingsWindowChromeVisible(widgets.sectionDescriptor, false, scrollChild)
            else
                setSettingsWindowChromeVisible(header, true)
                setSettingsWindowChromeVisible(widgets.sectionDescriptor, true, scrollChild)
                header:ClearAllPoints()
                header:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", PROFILES_LAYOUT.page.header_left, y)
                header:SetWidth(headerWidth)
                y = y - math.min(PROFILES_LAYOUT.page.header_bottom_gap, 14)
                y = layoutSettingsSectionDescriptor(
                    widgets.sectionDescriptor,
                    scrollChild,
                    PROFILES_LAYOUT.page.header_left,
                    y,
                    headerWidth
                )
            end

            local cardW = math.min(sectionSpan, PROFILES_LAYOUT.page.max_module_width)
            local currentHeight = layoutProfileSelectionModule(left, y, cardW, currentInfo)
            y = y - currentHeight - PROFILES_LAYOUT.page.module_gap

            local actionsHeight = layoutActionsModule(left, y, cardW)
            y = y - actionsHeight - PROFILES_LAYOUT.page.module_gap

            if widgets.dangerCard:IsShown() then
                layoutDangerModule(left, y, cardW, PROFILES_LAYOUT.module.padding_x)
                y = y - widgets.dangerCard:GetHeight() - PROFILES_LAYOUT.page.module_gap
            end

            scrollChild:SetHeight(math.max(1, -y + PROFILES_LAYOUT.page.bottom_padding))
            updateScrollBehavior(scrollFrame, scrollChild)
        end

        refreshAndLayoutProfiles = function()
            local activeInfo = refreshProfilesBindings()
            if not activeInfo then
                return
            end
            layoutProfiles(activeInfo)
        end

        self._refresh = function()
            local perfStart, perfState = PA_PerfBegin("profiles_refresh")
            local activeInfo = refreshProfilesBindings()
            PA_PerfEnd("profiles_refresh", perfStart, perfState)
            return activeInfo
        end

        self._layout = function(activeInfo)
            local perfStart, perfState = PA_PerfBegin("profiles_layout")
            local result = layoutProfiles(activeInfo)
            PA_PerfEnd("profiles_layout", perfStart, perfState)
            return result
        end

        registerRefreshCallback(function()
            if shouldSuppressSettingsFirstOpenExternalRefresh(self) then
                return
            end
            if not self then
                return
            end
            if self.IsShown and self:IsShown() then
                if refreshAndLayoutProfiles then
                    refreshAndLayoutProfiles()
                end
            elseif self._refresh then
                self._refresh()
            end
        end, self)
        scrollFrame:SetScript("OnSizeChanged", function()
            if handleSettingsFirstOpenSizeReady(self, "size_changed") then
                return
            end
            if shouldSuppressSettingsFirstOpenExternalRefresh(self) then
                return
            end
            if self._layout then self._layout() end
        end)
        self._settingsFirstOpenKey = "profiles"
        self._settingsFirstOpenSizeTarget = scrollFrame
        self._settingsFirstOpenRender = function(panel)
            if panel._refresh and panel._layout then
                local activeInfo = panel._refresh()
                panel._layout(activeInfo)
            elseif panel._layout then
                panel._layout()
            elseif panel._refresh then
                panel._refresh()
            end
        end
        self._settingsFirstOpenIsReady = function(panel)
            return panelHasSizedViewport(scrollFrame)
                and widgets.currentCard ~= nil and widgets.currentCard:IsShown()
                and widgets.actionsCard ~= nil and widgets.actionsCard:IsShown()
                and widgets.modeControl ~= nil and widgets.modeControl.control ~= nil and widgets.modeControl.control:IsShown()
                and (tonumber(scrollChild:GetHeight()) or 0) >= 1
        end
        settingsSearchRuntime.endDescriptorCapture(self)
    end

    panel:SetScript("OnShow", function(self)
        if not self._paAnchored then
            local p = self:GetParent()
            if p then
                self:ClearAllPoints()
                self:SetAllPoints(p)
                self._paAnchored = true
            end
        end

        self:EnsureBuilt()
        if not handleSettingsFirstOpenPanelShow(self) then
            withPanelHydration(self, function()
                if self._refresh and self._layout then
                    local activeInfo = self._refresh()
                    self._layout(activeInfo)
                elseif self._layout then
                    self._layout()
                elseif self._refresh then
                    self._refresh()
                end
            end)
        end
    end)

    panel:HookScript("OnHide", function(self)
        handleSettingsFirstOpenPanelHide(self)
        if self and self._profilesWidgets and self._profilesWidgets.sharedPickerPicker and self._profilesWidgets.sharedPickerPicker.Close then
            self._profilesWidgets.sharedPickerPicker:Close()
        end
        if self and self._profilesDialog and self._profilesDialog.Close then
            self._profilesDialog:Close()
        end
    end)

    return panel
end
OptionsInternal.createProfilesPanel = createProfilesPanel
