local API = rawget(_G, "LIDCOUNCIL_API")
local INTERNAL_API = type(API) == "table" and type(API.__internal) == "table" and API.__internal or nil
if type(INTERNAL_API) ~= "table" then
  error("LidCouncil missing internal API registry.")
end

local shared = INTERNAL_API.LIDCOUNCIL_LootEditorShared_Impl
if type(shared) ~= "table" then
  error("LidCouncil missing loot editor shared helpers.")
end

local RequireApi = shared.RequireApi
local BindMouseWheelScroll = shared.BindMouseWheelScroll
local RootDB = shared.RootDB
local ApplyFrameSkin = shared.ApplyFrameSkin
local MakeYellowSubHeader = shared.MakeYellowSubHeader
local GetCharacterKey = shared.GetCharacterKey
local GetLootProfile = shared.GetLootProfile
local GetEnabledLootProfileName = shared.GetEnabledLootProfileName or RequireApi("LIDCOUNCIL_GetEnabledLootProfileName", _G.LIDCOUNCIL_GetEnabledLootProfileName)
local GetPrimaryLootProfileName = shared.GetPrimaryLootProfileName
local GetLootProfileNames = shared.GetLootProfileNames
local GetVisibleLootProfileNames = shared.GetVisibleLootProfileNames or shared.GetLootProfileNames
local GetLootProfileRoleEntries = shared.GetLootProfileRoleEntries
local GetLootProfileAccessInfo = shared.GetLootProfileAccessInfo
local GetLootProfileAccessInfoForRole = shared.GetLootProfileAccessInfoForRole
local GetLootProfilePermissionPolicyRoleState = shared.GetLootProfilePermissionPolicyRoleState
local SetCurrentLootProfile = shared.SetCurrentLootProfile
local CreateLootProfile = shared.CreateLootProfile
local DeleteLootProfile = shared.DeleteLootProfile
local CopyLootProfile = shared.CopyLootProfile
local SetLootProfileMemberRole = shared.SetLootProfileMemberRole
local SetLootProfilePermissionPolicyValue = shared.SetLootProfilePermissionPolicyValue
local ResetLootProfilePermissionPolicy = shared.ResetLootProfilePermissionPolicy
local TransferLootProfileMaster = shared.TransferLootProfileMaster
local SetLootProfileEnabled = shared.SetLootProfileEnabled
local SetLootProfileRaid = shared.SetLootProfileRaid
local ApplyLootRollTemplate = shared.ApplyLootRollTemplate
local AddLootRollOption = shared.AddLootRollOption
local UpdateLootRollOption = shared.UpdateLootRollOption
local MoveLootRollOption = shared.MoveLootRollOption
local RemoveLootRollOption = shared.RemoveLootRollOption
local UpdateLootPointMode = shared.UpdateLootPointMode
local UpdateLootLidTableRow = shared.UpdateLootLidTableRow
local AddLootPointRule = shared.AddLootPointRule
local RemoveLootPointRule = shared.RemoveLootPointRule
local StartLootSession = shared.StartLootSession
local StopLootSession = shared.StopLootSession
local GetActiveLootSession = shared.GetActiveLootSession
local AddLootLedgerEntry = shared.AddLootLedgerEntry
local GetLootLedgerCharacters = shared.GetLootLedgerCharacters
local ResolveOptionalApiFunction = shared.ResolveOptionalApiFunction
local CreateCustomDropdownControl = shared.CreateCustomDropdownControl
local TrimText = shared.TrimText
local FormatDateTime = shared.FormatDateTime
local FormatDuration = shared.FormatDuration
local CreateSimpleEditBox = shared.CreateSimpleEditBox
local SetListButtonSelected = shared.SetListButtonSelected
local SetTextListButtonTextColor = shared.SetTextListButtonTextColor
local EnsureTextListButtons = shared.EnsureTextListButtons
local CreateSectionShell = shared.CreateSectionShell
local ClampLayoutValue = shared.ClampLayoutValue
local GetResponsiveSectionLayout = shared.GetResponsiveSectionLayout
local SetControlWidth = shared.SetControlWidth
local GetFontStringWidth = shared.GetFontStringWidth
local CreateSectionDivider = shared.CreateSectionDivider
local FlowLayoutControls = shared.FlowLayoutControls
local LayoutRollOptionRow = shared.LayoutRollOptionRow
local LayoutPointRuleRow = shared.LayoutPointRuleRow
local LayoutLidTableEditorRow = shared.LayoutLidTableEditorRow
local BuildRollOptionsText = shared.BuildRollOptionsText
local ROLL_TEMPLATE_CHOICES = shared.ROLL_TEMPLATE_CHOICES
local DEFAULT_ROLL_OPTION_ICON_CHOICES = shared.DEFAULT_ROLL_OPTION_ICON_CHOICES
local ResolveTextureAsset = shared.ResolveTextureAsset
local ResolveDefaultRollOptionIcon = shared.ResolveDefaultRollOptionIcon
local ResolveRollOptionIcon = shared.ResolveRollOptionIcon
local GetRollOptionIconLabel = shared.GetRollOptionIconLabel
local ResolveRollTemplate = shared.ResolveRollTemplate
local GetRollTemplateText = shared.GetRollTemplateText
local EnsureRollOptionRows = shared.EnsureRollOptionRows
local EnsurePointRuleRows = shared.EnsurePointRuleRows
local EnsureLidTableEditorRows = shared.EnsureLidTableEditorRows
local ExtractItemID = shared.ExtractItemID
local ExtractItemLinkName = shared.ExtractItemLinkName
local FormatPointRuleItemLabel = shared.FormatPointRuleItemLabel
local FormatRaidLootItemLabel = shared.FormatRaidLootItemLabel
local LOOT_ITEM_MENU_PAGE_SIZE = shared.LOOT_ITEM_MENU_PAGE_SIZE
local NormalizeInstanceTuple = shared.NormalizeInstanceTuple
local NormalizeEncounterTuple = shared.NormalizeEncounterTuple
local NormalizeLootInfo = shared.NormalizeLootInfo
local EnsureEncounterJournalLoaded = shared.EnsureEncounterJournalLoaded
local CollectRaidEntries = shared.CollectRaidEntries
local CollectRaidLootEntries = shared.CollectRaidLootEntries
local FindRaidEntryByProfile = shared.FindRaidEntryByProfile
local FindRaidLootEntry = shared.FindRaidLootEntry
local EnsureLootLiveBoardMode = shared.EnsureLootLiveBoardMode
local ClampMenuPage = shared.ClampMenuPage
local GetSelectedValuePage = shared.GetSelectedValuePage
local EnsureLootProfileGroups = shared.EnsureLootProfileGroups
local FindLootProfileGroupIndex = shared.FindLootProfileGroupIndex
local RemoveLootProfileFromGroups = shared.RemoveLootProfileFromGroups
local ToggleLootProfileGroupCollapsed = shared.ToggleLootProfileGroupCollapsed
local GetLootProfileGroupName = shared.GetLootProfileGroupName
local BuildLootProfileNavRows = shared.BuildLootProfileNavRows
local BuildPointRulesText = shared.BuildPointRulesText
local ResolvePointMode = shared.ResolvePointMode
local GetLidTableRows = shared.GetLidTableRows
local BuildLidTableSummaryText = shared.BuildLidTableSummaryText
local POINT_MODE_CHOICES = shared.POINT_MODE_CHOICES
local GetSelectedProfileName = shared.GetSelectedProfileName
local RequestEditorPageRefresh = shared.RequestEditorPageRefresh

local function CreateRollColumnHeader(parent, text)
  local header = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  header:SetJustifyH("LEFT")
  header:SetText(tostring(text or ""))
  return header
end

local LOOT_PROFILE_PERMISSION_POLICY_ROWS = {
  { section = "Profile" },
  { key = "canManageRoles", label = "Manage Member Roles" },
  { key = "canManageRights", label = "Manage Rights" },
  { key = "canEditRaidSettings", label = "Edit Raid Settings" },
  { key = "canEditRollSettings", label = "Edit Roll Settings" },
  { key = "canEditPointSettings", label = "Edit Point Settings" },
  { key = "canDeleteProfile", label = "Delete Local Profile Copy" },
  { section = "Session" },
  { key = "canStartSession", label = "Start Session" },
  { key = "canManageSession", label = "Manage / Stop Session" },
  { key = "canOpenLiveBoard", label = "Open Live Board" },
  { key = "canVote", label = "Use Voting" },
  { key = "canAssignLoot", label = "Assign Loot" },
  { section = "Loot List" },
  { key = "canEditLootList", label = "Edit Loot List" },
  { key = "canEditManualPoints", label = "Edit Manual Points" },
  { key = "canDeleteLootListCharacter", label = "Delete Loot List Character" },
  { key = "canEditMainAlt", label = "Edit Main / Alt" },
  { key = "canEditNotes", label = "Edit Notes" },
}

local function CreatePermissionPolicyCell(parent, interactive)
  local cell = CreateFrame("Button", nil, parent, "BackdropTemplate")
  ApplyFrameSkin(cell)
  cell:SetSize(68, 20)
  cell.label = cell:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  cell.label:SetPoint("CENTER", 0, 0)
  cell.__interactive = interactive and true or false
  if not cell.__interactive then
    cell:EnableMouse(false)
  end
  cell:SetScript("OnEnter", function(self)
    if self.__interactive and self.SetBackdropColor and self.__hoverBackdrop then
      self:SetBackdropColor(self.__hoverBackdrop[1], self.__hoverBackdrop[2], self.__hoverBackdrop[3], self.__hoverBackdrop[4])
    end
    if self.__tooltipText and GameTooltip and GameTooltip.SetOwner then
      GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
      GameTooltip:SetText(self.__tooltipText)
      GameTooltip:Show()
    end
  end)
  cell:SetScript("OnLeave", function(self)
    if self.SetBackdropColor and self.__normalBackdrop then
      self:SetBackdropColor(self.__normalBackdrop[1], self.__normalBackdrop[2], self.__normalBackdrop[3], self.__normalBackdrop[4])
    end
    if GameTooltip and GameTooltip:GetOwner() == self then
      GameTooltip:Hide()
    end
  end)
  return cell
end

local function SetPermissionPolicyCellState(cell, allowed, interactive, mirrored)
  if not cell or not cell.label then
    return
  end

  cell.__interactive = interactive and true or false
  local isAllowed = allowed and true or false
  local isFixed = mirrored and not interactive
  local text = isFixed and (isAllowed and "Locked On" or "Locked Off") or (isAllowed and "Allowed" or "Denied")
  cell.label:SetText(text)
  if isFixed then
    cell.__tooltipText = isAllowed
      and "Locked and allowed by LidCouncil role safeguards. This right cannot be changed."
      or "Locked and denied by LidCouncil role safeguards. This right cannot be changed."
  elseif interactive then
    cell.__tooltipText = isAllowed
      and "Allowed. Click to deny this right for the role. Changes save immediately."
      or "Denied. Click to allow this right for the role. Changes save immediately."
  else
    cell.__tooltipText = isAllowed
      and "Allowed. You do not have permission to change this right."
      or "Denied. You do not have permission to change this right."
  end

  local normalBackdrop
  local textColor
  local borderColor
  if isFixed then
    normalBackdrop = { 0.10, 0.11, 0.13, 0.96 }
    textColor = { 0.76, 0.78, 0.82, 1.00 }
    borderColor = { 0.38, 0.42, 0.48, 0.84 }
  elseif isAllowed then
    normalBackdrop = { 0.08, 0.18, 0.12, 0.98 }
    textColor = { 0.58, 0.96, 0.70, 1.00 }
    borderColor = { 0.24, 0.70, 0.38, 0.90 }
  else
    normalBackdrop = { 0.19, 0.09, 0.10, 0.98 }
    textColor = { 1.00, 0.62, 0.62, 1.00 }
    borderColor = { 0.72, 0.28, 0.30, 0.90 }
  end

  cell.__normalBackdrop = normalBackdrop
  cell.__hoverBackdrop = interactive and {
    math.min(1, normalBackdrop[1] + 0.04),
    math.min(1, normalBackdrop[2] + 0.04),
    math.min(1, normalBackdrop[3] + 0.04),
    normalBackdrop[4],
  } or normalBackdrop

  if cell.SetBackdropColor then
    cell:SetBackdropColor(normalBackdrop[1], normalBackdrop[2], normalBackdrop[3], normalBackdrop[4])
  end
  if cell.SetBackdropBorderColor and borderColor then
    cell:SetBackdropBorderColor(borderColor[1], borderColor[2], borderColor[3], borderColor[4])
  end
  cell.label:SetTextColor(textColor[1], textColor[2], textColor[3], textColor[4])

  if interactive then
    cell:EnableMouse(true)
    if cell.Enable then
      cell:Enable()
    end
  else
    cell:EnableMouse(false)
    if cell.Disable then
      cell:Disable()
    end
  end
end

local function EnsurePermissionPolicyRows(editor, parent)
  editor.lootProfilePermissionPolicyRows = editor.lootProfilePermissionPolicyRows or {}
  while #editor.lootProfilePermissionPolicyRows < #LOOT_PROFILE_PERMISSION_POLICY_ROWS do
    local row = CreateFrame("Button", nil, parent, "BackdropTemplate")
    ApplyFrameSkin(row)
    if row.SetBackdropColor then
      row:SetBackdropColor(0.05, 0.05, 0.07, 0.98)
    end
    row:SetHeight(24)
    row.labelText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    row.labelText:SetJustifyH("LEFT")
    row.masterCell = CreatePermissionPolicyCell(row, false)
    row.sessionHostCell = CreatePermissionPolicyCell(row, false)
    row.councilCell = CreatePermissionPolicyCell(row, true)
    row.raiderCell = CreatePermissionPolicyCell(row, true)
    editor.lootProfilePermissionPolicyRows[#editor.lootProfilePermissionPolicyRows + 1] = row
  end
  return editor.lootProfilePermissionPolicyRows
end

local FormatLootProfileRoleLabel
local BuildLootProfileRoleBuckets
local GetProfileClassColor
local ResolveProfileMemberDisplay
local ResolveProfileIconData
local ApplyProfileIcon
local BuildProfileClassSummary
local ResolveRaidPreviewTexture

local CreateLootProfileDisplayHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootProfileDisplayHelpers_Impl
if type(CreateLootProfileDisplayHelpers) ~= "function" then
  error("LidCouncil missing loot profiles display helpers.")
end

local lootProfileDisplayHelpers = CreateLootProfileDisplayHelpers({
  TrimText = TrimText,
})

FormatLootProfileRoleLabel = lootProfileDisplayHelpers.FormatLootProfileRoleLabel
BuildLootProfileRoleBuckets = lootProfileDisplayHelpers.BuildLootProfileRoleBuckets
GetProfileClassColor = lootProfileDisplayHelpers.GetProfileClassColor
ResolveProfileMemberDisplay = lootProfileDisplayHelpers.ResolveProfileMemberDisplay
ResolveProfileIconData = lootProfileDisplayHelpers.ResolveProfileIconData
ApplyProfileIcon = lootProfileDisplayHelpers.ApplyProfileIcon
BuildProfileClassSummary = lootProfileDisplayHelpers.BuildProfileClassSummary
ResolveRaidPreviewTexture = lootProfileDisplayHelpers.ResolveRaidPreviewTexture

local CreateLootProfileLayoutHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootProfileLayoutHelpers_Impl
if type(CreateLootProfileLayoutHelpers) ~= "function" then
  error("LidCouncil missing loot profiles layout helpers.")
end

local CreateLootProfileRefreshHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootProfileRefreshHelpers_Impl
if type(CreateLootProfileRefreshHelpers) ~= "function" then
  error("LidCouncil missing loot profiles refresh helpers.")
end

local BuildLootProfilesPageScaffold = INTERNAL_API.LIDCOUNCIL_BuildLootProfilesPageScaffold_Impl
if type(BuildLootProfilesPageScaffold) ~= "function" then
  error("LidCouncil missing loot profiles page scaffold builder.")
end

local CreateLootProfileMemberHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootProfileMemberHelpers_Impl
if type(CreateLootProfileMemberHelpers) ~= "function" then
  error("LidCouncil missing loot profiles member helpers.")
end

local CreateLootProfileSettingsHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootProfileSettingsHelpers_Impl
if type(CreateLootProfileSettingsHelpers) ~= "function" then
  error("LidCouncil missing loot profiles settings helpers.")
end

local editorUiHelpers = INTERNAL_API.LIDCOUNCIL_EditorUiHelpers_Impl
local CreatePurpleOutline = type(editorUiHelpers) == "table" and editorUiHelpers.CreatePurpleOutline or nil
local ClampListPage = type(editorUiHelpers) == "table" and editorUiHelpers.ClampListPage or nil
local GetListPageForValue = type(editorUiHelpers) == "table" and editorUiHelpers.GetListPageForValue or nil
local UpdatePagerControls = type(editorUiHelpers) == "table" and editorUiHelpers.UpdatePagerControls or nil
local profileManagement = INTERNAL_API.LIDCOUNCIL_EditorProfileManagement_Impl
local AssignProfileToGroup = type(profileManagement) == "table" and profileManagement.AssignProfileToGroup or nil

local PROFILE_PAGE_DEPS = {
  INTERNAL_API = INTERNAL_API,
  BindMouseWheelScroll = BindMouseWheelScroll,
  RootDB = RootDB,
  ApplyFrameSkin = ApplyFrameSkin,
  MakeYellowSubHeader = MakeYellowSubHeader,
  GetCharacterKey = GetCharacterKey,
  GetLootProfile = GetLootProfile,
  GetLootProfileNames = GetLootProfileNames,
  GetLootProfileRoleEntries = GetLootProfileRoleEntries,
  GetLootProfileAccessInfo = GetLootProfileAccessInfo,
  GetLootProfileAccessInfoForRole = GetLootProfileAccessInfoForRole,
  SetCurrentLootProfile = SetCurrentLootProfile,
  CreateLootProfile = CreateLootProfile,
  DeleteLootProfile = DeleteLootProfile,
  CopyLootProfile = CopyLootProfile,
  SetLootProfileMemberRole = SetLootProfileMemberRole,
  SetLootProfilePermissionPolicyValue = SetLootProfilePermissionPolicyValue,
  ResetLootProfilePermissionPolicy = ResetLootProfilePermissionPolicy,
  TransferLootProfileMaster = TransferLootProfileMaster,
  SetLootProfileEnabled = SetLootProfileEnabled,
  SetLootProfileRaid = SetLootProfileRaid,
  ApplyLootRollTemplate = ApplyLootRollTemplate,
  AddLootRollOption = AddLootRollOption,
  UpdateLootRollOption = UpdateLootRollOption,
  MoveLootRollOption = MoveLootRollOption,
  RemoveLootRollOption = RemoveLootRollOption,
  UpdateLootPointMode = UpdateLootPointMode,
  UpdateLootLidTableRow = UpdateLootLidTableRow,
  AddLootPointRule = AddLootPointRule,
  RemoveLootPointRule = RemoveLootPointRule,
  StartLootSession = StartLootSession,
  StopLootSession = StopLootSession,
  GetActiveLootSession = GetActiveLootSession,
  AddLootLedgerEntry = AddLootLedgerEntry,
  GetLootLedgerCharacters = GetLootLedgerCharacters,
  ResolveOptionalApiFunction = ResolveOptionalApiFunction,
  CreateCustomDropdownControl = CreateCustomDropdownControl,
  TrimText = TrimText,
  FormatDateTime = FormatDateTime,
  FormatDuration = FormatDuration,
  CreateSimpleEditBox = CreateSimpleEditBox,
  SetListButtonSelected = SetListButtonSelected,
  SetTextListButtonTextColor = SetTextListButtonTextColor,
  EnsureTextListButtons = EnsureTextListButtons,
  CreateSectionShell = CreateSectionShell,
  ClampLayoutValue = ClampLayoutValue,
  GetResponsiveSectionLayout = GetResponsiveSectionLayout,
  SetControlWidth = SetControlWidth,
  GetFontStringWidth = GetFontStringWidth,
  CreateSectionDivider = CreateSectionDivider,
  FlowLayoutControls = FlowLayoutControls,
  LayoutRollOptionRow = LayoutRollOptionRow,
  LayoutLidTableEditorRow = LayoutLidTableEditorRow,
  BuildRollOptionsText = BuildRollOptionsText,
  ROLL_TEMPLATE_CHOICES = ROLL_TEMPLATE_CHOICES,
  DEFAULT_ROLL_OPTION_ICON_CHOICES = DEFAULT_ROLL_OPTION_ICON_CHOICES,
  ResolveTextureAsset = ResolveTextureAsset,
  ResolveDefaultRollOptionIcon = ResolveDefaultRollOptionIcon,
  ResolveRollOptionIcon = ResolveRollOptionIcon,
  GetRollOptionIconLabel = GetRollOptionIconLabel,
  ResolveRollTemplate = ResolveRollTemplate,
  GetRollTemplateText = GetRollTemplateText,
  EnsureRollOptionRows = EnsureRollOptionRows,
  EnsureLidTableEditorRows = EnsureLidTableEditorRows,
  ExtractItemID = ExtractItemID,
  ExtractItemLinkName = ExtractItemLinkName,
  FormatPointRuleItemLabel = FormatPointRuleItemLabel,
  FormatRaidLootItemLabel = FormatRaidLootItemLabel,
  LOOT_ITEM_MENU_PAGE_SIZE = LOOT_ITEM_MENU_PAGE_SIZE,
  NormalizeInstanceTuple = NormalizeInstanceTuple,
  NormalizeEncounterTuple = NormalizeEncounterTuple,
  NormalizeLootInfo = NormalizeLootInfo,
  EnsureEncounterJournalLoaded = EnsureEncounterJournalLoaded,
  CollectRaidEntries = CollectRaidEntries,
  CollectRaidLootEntries = CollectRaidLootEntries,
  FindRaidEntryByProfile = FindRaidEntryByProfile,
  FindRaidLootEntry = FindRaidLootEntry,
  EnsureLootLiveBoardMode = EnsureLootLiveBoardMode,
  ClampMenuPage = ClampMenuPage,
  GetSelectedValuePage = GetSelectedValuePage,
  EnsureLootProfileGroups = EnsureLootProfileGroups,
  FindLootProfileGroupIndex = FindLootProfileGroupIndex,
  RemoveLootProfileFromGroups = RemoveLootProfileFromGroups,
  ToggleLootProfileGroupCollapsed = ToggleLootProfileGroupCollapsed,
  GetLootProfileGroupName = GetLootProfileGroupName,
  BuildLootProfileNavRows = BuildLootProfileNavRows,
  BuildPointRulesText = BuildPointRulesText,
  ResolvePointMode = ResolvePointMode,
  GetLidTableRows = GetLidTableRows,
  BuildLidTableSummaryText = BuildLidTableSummaryText,
  POINT_MODE_CHOICES = POINT_MODE_CHOICES,
  GetSelectedProfileName = GetSelectedProfileName,
  FormatLootProfileRoleLabel = FormatLootProfileRoleLabel,
  BuildLootProfileRoleBuckets = BuildLootProfileRoleBuckets,
  PermissionPolicyRowDefs = LOOT_PROFILE_PERMISSION_POLICY_ROWS,
  SetPermissionPolicyCellState = SetPermissionPolicyCellState,
  GetProfileClassColor = GetProfileClassColor,
  ResolveProfileMemberDisplay = ResolveProfileMemberDisplay,
  ResolveProfileIconData = ResolveProfileIconData,
  ApplyProfileIcon = ApplyProfileIcon,
  BuildProfileClassSummary = BuildProfileClassSummary,
  CreatePurpleOutline = CreatePurpleOutline,
  ClampListPage = ClampListPage,
  GetListPageForValue = GetListPageForValue,
  UpdatePagerControls = UpdatePagerControls,
  AssignProfileToGroup = AssignProfileToGroup,
}

local function BuildLootProfilesPage(editor, page)
  if not editor or not page then return end

  local function RequestLootProfilePageRefresh(owner)
    if type(owner) ~= "table" then
      return false
    end
    if type(RequestEditorPageRefresh) == "function" then
      local handled = RequestEditorPageRefresh(owner, "Profiles", "RefreshLootProfilePage")
      if handled then
        return true
      end
    end
    if owner.RefreshLootProfilePage then
      owner:RefreshLootProfilePage()
      return true
    end
    if owner.Refresh then
      owner:Refresh()
      return true
    end
    return false
  end

  editor.RequestLootProfilePageRefresh = function(self)
    return RequestLootProfilePageRefresh(type(self) == "table" and self or editor)
  end

  local function RefreshProfilesPage()
    return RequestLootProfilePageRefresh(editor)
  end

  local deps = PROFILE_PAGE_DEPS
  local INTERNAL_API = deps.INTERNAL_API
  local ApplyFrameSkin = deps.ApplyFrameSkin
  local GetLootProfile = deps.GetLootProfile
  local GetLootProfileRoleEntries = deps.GetLootProfileRoleEntries
  local GetLootProfileAccessInfo = deps.GetLootProfileAccessInfo
  local GetLootProfileAccessInfoForRole = deps.GetLootProfileAccessInfoForRole
  local SetLootProfileMemberRole = deps.SetLootProfileMemberRole
  local SetLootProfilePermissionPolicyValue = deps.SetLootProfilePermissionPolicyValue
  local ResetLootProfilePermissionPolicy = deps.ResetLootProfilePermissionPolicy
  local SetLootProfileEnabled = deps.SetLootProfileEnabled
  local SetLootProfileRaid = deps.SetLootProfileRaid
  local UpdateLootRollOption = deps.UpdateLootRollOption
  local AddLootPointRule = deps.AddLootPointRule
  local GetActiveLootSession = deps.GetActiveLootSession
  local ResolveOptionalApiFunction = deps.ResolveOptionalApiFunction
  local TrimText = deps.TrimText
  local SetListButtonSelected = deps.SetListButtonSelected
  local SetTextListButtonTextColor = deps.SetTextListButtonTextColor
  local ClampLayoutValue = deps.ClampLayoutValue
  local SetControlWidth = deps.SetControlWidth
  local GetFontStringWidth = deps.GetFontStringWidth
  local FlowLayoutControls = deps.FlowLayoutControls
  local ResolveTextureAsset = deps.ResolveTextureAsset
  local ResolveRollOptionIcon = deps.ResolveRollOptionIcon
  local EnsureLidTableEditorRows = deps.EnsureLidTableEditorRows
  local FormatRaidLootItemLabel = deps.FormatRaidLootItemLabel
  local LOOT_ITEM_MENU_PAGE_SIZE = deps.LOOT_ITEM_MENU_PAGE_SIZE
  local CollectRaidEntries = deps.CollectRaidEntries
  local ClampMenuPage = deps.ClampMenuPage
  local GetSelectedValuePage = deps.GetSelectedValuePage
  local ResolvePointMode = deps.ResolvePointMode
  local GetLidTableRows = deps.GetLidTableRows
  local GetSelectedProfileName = deps.GetSelectedProfileName
  local FormatLootProfileRoleLabel = deps.FormatLootProfileRoleLabel
  local GetProfileClassColor = deps.GetProfileClassColor
  local ResolveProfileMemberDisplay = deps.ResolveProfileMemberDisplay
  local ResolveProfileIconData = deps.ResolveProfileIconData
  local ApplyProfileIcon = deps.ApplyProfileIcon
  local BuildProfileClassSummary = deps.BuildProfileClassSummary
  local PermissionPolicyRowDefs = deps.PermissionPolicyRowDefs
  local SetPermissionPolicyCellState = deps.SetPermissionPolicyCellState

  if type(editor.ShowIconPicker) ~= "function" then
    local createPanelAssetPickers = INTERNAL_API.LIDCOUNCIL_CreatePanelAssetPickers_Impl
    if type(createPanelAssetPickers) == "function" then
      createPanelAssetPickers(editor, {})
    end
  end
  BuildLootProfilesPageScaffold(editor, page)
  EnsurePermissionPolicyRows(editor, editor.lootProfileAccessFrame)

  local rightBg = editor.lootProfilesRightBg
  local rightContent = editor.lootProfilesRightContent
  local addGroupBtn = editor.lootAddGroupBtn
  local addProfileBtn = editor.lootAddProfileBtn
  local prevPageBtn = editor.lootProfilesPrevBtn
  local nextPageBtn = editor.lootProfilesNextBtn
  local deleteGroupBtn = editor.lootDeleteGroupBtn
  local deleteBtn = editor.lootDeleteProfileBtn
  local feedback = editor.lootProfilesFeedback
  local activateBtn = editor.lootActivateProfileBtn
  local deactivateBtn = editor.lootDeactivateProfileBtn
  local copyBtn = editor.lootCopyProfileBtn
  local clearSimulationBtn = editor.lootClearSimulationContentBtn
  local pointModeDropdown = editor.lootPointModeDropdown
  local raidSeasonDropdown = editor.lootRaidSeasonDropdown
  local raidDropdown = editor.lootRaidDropdown
  local saveRaidBtn = editor.lootSaveRaidBtn
  local rollTemplateDropdown = editor.lootRollTemplateDropdown
  local rollEdit = editor.lootRollOptionEdit
  local addRollBtn = editor.lootAddRollOptionBtn
  local removeRollBtn = editor.lootRemoveRollOptionBtn
  local testRollBtn = editor.lootTestRollPopupBtn
  local previewHostBoardBtn = editor.lootPreviewHostBoardBtn
  local rollSettingsToolsDropdown = editor.lootRollSettingsToolsDropdown
  local rollExportBtn = editor.lootRollExportBtn
  local rollImportStringBtn = editor.lootRollImportStringBtn
  local rollImportProfileDropdown = editor.lootRollImportProfileDropdown
  local levelEdit = editor.lootPointItemLevelEdit
  local itemDropdown = editor.lootPointItemDropdown
  local levelPointsEdit = editor.lootPointLevelValueEdit or editor.lootPointValueEdit
  local itemPointsEdit = editor.lootPointItemValueEdit
  local addLevelRuleBtn = editor.lootAddPointRuleBtn
  local addItemRuleBtn = editor.lootAddItemPointRuleBtn
  local removeRuleBtn = editor.lootRemovePointRuleBtn
  local pointExportBtn = editor.lootPointExportBtn
  local pointImportStringBtn = editor.lootPointImportStringBtn
  local pointImportProfileDropdown = editor.lootPointImportProfileDropdown
  local raiderFrame = editor.lootProfileRaiderFrame
  local raiderToggleBtn = editor.lootProfileRaiderToggleBtn
  local overviewToggleBtn = editor.lootProfileOverviewToggleBtn
  local accessToggleBtn = editor.lootProfileAccessToggleBtn
  local raidToggleBtn = editor.lootProfileRaidToggleBtn
  local rollToggleBtn = editor.lootProfileRollToggleBtn
  local pointsToggleBtn = editor.lootProfilePointsToggleBtn
  local backupToggleBtn = editor.lootProfileBackupToggleBtn
  local saveBackupBtn = editor.lootProfileSaveBackupBtn
  local backupDropdown = editor.lootProfileBackupDropdown
  local loadBackupBtn = editor.lootProfileLoadBackupBtn
  local deleteBackupBtn = editor.lootProfileDeleteBackupBtn
  local transferMasterBtn = editor.lootProfileTransferMasterBtn

  local function RejectCombatLockedProfileAction(actionLabel)
    if type(InCombatLockdown) ~= "function" or not InCombatLockdown() then
      return false
    end
    if feedback and feedback.SetText then
      feedback:SetText(tostring(actionLabel or "This profile action") .. " is unavailable during combat.")
    end
    return true
  end

  local function RejectActiveSessionBackupAction()
    if not GetActiveLootSession() then
      return false
    end
    if feedback and feedback.SetText then
      feedback:SetText("Backups are locked while a loot session is active. Stop the session first.")
    end
    return true
  end

  local memberHelpersContext = {
    editor = editor,
    rightContent = rightContent,
    feedback = feedback,
    RequestProfilesPageRefresh = RefreshProfilesPage,
    GetLootProfileAccessInfo = GetLootProfileAccessInfo,
    GetSelectedProfileName = GetSelectedProfileName,
    ResolveProfileMemberDisplay = ResolveProfileMemberDisplay,
    ResolveProfileIconData = ResolveProfileIconData,
    GetProfileClassColor = GetProfileClassColor,
    ApplyProfileIcon = ApplyProfileIcon,
    SetListButtonSelected = SetListButtonSelected,
    TrimText = TrimText,
    FormatLootProfileRoleLabel = FormatLootProfileRoleLabel,
    SetLootProfileMemberRole = SetLootProfileMemberRole,
    GetLootProfileRoleEntries = GetLootProfileRoleEntries,
    ResolveOptionalApiFunction = ResolveOptionalApiFunction,
  }
  local memberHelpers = CreateLootProfileMemberHelpers(memberHelpersContext)
  local ApplyProfileActionButtonStyle = memberHelpers.ApplyProfileActionButtonStyle
  local RefreshProfileMemberRows = memberHelpers.RefreshProfileMemberRows

  local settingsHelpersContext = {
    editor = editor,
    rightContent = rightContent,
    feedback = feedback,
    RequestProfilesPageRefresh = RefreshProfilesPage,
    GetSelectedProfileName = GetSelectedProfileName,
    GetLootProfile = GetLootProfile,
    SetLootProfileRaid = SetLootProfileRaid,
    ApplyLootRollTemplate = ApplyLootRollTemplate,
    UpdateLootRollOption = UpdateLootRollOption,
    UpdateLootPointMode = UpdateLootPointMode,
    UpdateLootLidTableRow = UpdateLootLidTableRow,
    EnsureLidTableEditorRows = EnsureLidTableEditorRows,
    EnsureRollOptionRows = EnsureRollOptionRows,
    EnsurePointRuleRows = EnsurePointRuleRows,
    GetLidTableRows = GetLidTableRows,
    TrimText = TrimText,
    FormatPointRuleItemLabel = FormatPointRuleItemLabel,
    ResolveOptionalApiFunction = ResolveOptionalApiFunction,
    ResolveTextureAsset = ResolveTextureAsset,
    ResolveDefaultRollOptionIcon = ResolveDefaultRollOptionIcon,
    ResolveRollOptionIcon = ResolveRollOptionIcon,
    GetRollOptionIconLabel = GetRollOptionIconLabel,
    ResolveRollTemplate = ResolveRollTemplate,
    GetRollTemplateText = GetRollTemplateText,
    ROLL_TEMPLATE_CHOICES = ROLL_TEMPLATE_CHOICES,
    DEFAULT_ROLL_OPTION_ICON_CHOICES = DEFAULT_ROLL_OPTION_ICON_CHOICES,
    LOOT_ITEM_MENU_PAGE_SIZE = LOOT_ITEM_MENU_PAGE_SIZE,
    ClampMenuPage = ClampMenuPage,
    GetSelectedValuePage = GetSelectedValuePage,
    CollectRaidEntries = CollectRaidEntries,
    CollectRaidLootEntries = CollectRaidLootEntries,
    FindRaidEntryByProfile = FindRaidEntryByProfile,
    ResolvePointMode = ResolvePointMode,
    POINT_MODE_CHOICES = POINT_MODE_CHOICES,
    FormatRaidLootItemLabel = FormatRaidLootItemLabel,
    MoveLootRollOption = deps.MoveLootRollOption,
  }
  local settingsHelpers = CreateLootProfileSettingsHelpers(settingsHelpersContext)
  local SetDropdownValue = settingsHelpers.SetDropdownValue
  local ClearItemRuleSelection = settingsHelpers.ClearItemRuleSelection
  local RefreshLidTableRows = settingsHelpers.RefreshLidTableRows
  local BindAllLidTableRows = settingsHelpers.BindAllLidTableRows
  local RefreshRollOptionRows = settingsHelpers.RefreshRollOptionRows
  local RefreshPointRuleRows = settingsHelpers.RefreshPointRuleRows
  local GetResolvedRaidEntry = settingsHelpers.GetResolvedRaidEntry
  local GetCurrentLootSeasonContext = settingsHelpers.GetCurrentLootSeasonContext
  local BuildSeasonRaidNamesText = settingsHelpers.BuildSeasonRaidNamesText
  local CollectSeasonLootEntries = settingsHelpers.CollectSeasonLootEntries
  local FindSeasonLootEntry = settingsHelpers.FindSeasonLootEntry
  local BuildRaidSeasonDropdownMenu = settingsHelpers.BuildRaidSeasonDropdownMenu
  local BuildRaidDropdownMenu = settingsHelpers.BuildRaidDropdownMenu
  local BuildLootItemDropdownMenu = settingsHelpers.BuildLootItemDropdownMenu
  local BuildRollTemplateDropdownMenu = settingsHelpers.BuildRollTemplateDropdownMenu
  local BuildPointModeDropdownMenu = settingsHelpers.BuildPointModeDropdownMenu
  local BroadcastActiveRoleUpdate = settingsHelpers.BroadcastActiveRoleUpdate

  editor.SelectLootProfileImage = function(_, raidEntry)
    local profileName = GetSelectedProfileName(editor)
    if not GetLootProfileAccessInfo(profileName).canEditRaidSettings then
      feedback:SetText("Your current role cannot edit profile artwork.")
      return
    end

    local raidName = type(raidEntry) == "table" and raidEntry.name or nil
    local instanceID = type(raidEntry) == "table" and tonumber(raidEntry.instanceID) or nil
    local ok, result = SetLootProfileRaid(profileName, raidName, instanceID)
    if ok == false then
      feedback:SetText(tostring(result or "Could not update the profile artwork."))
      return
    end

    if type(raidEntry) == "table" then
      editor.__lootRaidSelectedTier = tonumber(raidEntry.tier) or editor.__lootRaidSelectedTier
      feedback:SetText("Selected profile artwork: " .. tostring(raidName or "?"))
    else
      feedback:SetText("Cleared profile artwork.")
    end
    ClearItemRuleSelection()
    RefreshProfilesPage()
  end

  local SelectProfileRoleTarget
  local ForceLocalRoleState

  SelectProfileRoleTarget = function(characterKey, roleValue)
    local resolvedCharacter = TrimText(characterKey)
    local resolvedRole = string.upper(TrimText(roleValue or "RAIDER"))
    if resolvedRole ~= "COUNCIL" then
      resolvedRole = "RAIDER"
    end
    editor.__lootProfileRoleTarget = resolvedCharacter ~= "" and resolvedCharacter or nil
    editor.__lootProfileRoleValue = resolvedRole
  end
  memberHelpersContext.SelectProfileRoleTarget = SelectProfileRoleTarget

  ForceLocalRoleState = function(profileName, characterKey, roleValue)
    local resolvedProfileName = TrimText(profileName)
    local resolvedCharacter = TrimText(characterKey)
    local resolvedRole = string.upper(TrimText(roleValue))
    if resolvedProfileName == "" or resolvedCharacter == "" then
      return
    end
    if resolvedRole ~= "COUNCIL" then
      resolvedRole = "RAIDER"
    end

    local profile = GetLootProfile(resolvedProfileName)
    if type(profile) ~= "table" then
      return
    end

    profile.meta = profile.meta or {}
    local permissions = type(profile.meta.permissions) == "table" and profile.meta.permissions or { master = "", members = {} }
    permissions.master = TrimText(permissions.master)
    permissions.members = type(permissions.members) == "table" and permissions.members or {}
    profile.meta.permissions = permissions

    local masterLower = string.lower(permissions.master or "")
    if masterLower ~= "" and masterLower == string.lower(resolvedCharacter) then
      return
    end

    for storedKey in pairs(permissions.members) do
      if string.lower(TrimText(storedKey)) == string.lower(resolvedCharacter) then
        permissions.members[storedKey] = nil
      end
    end
    permissions.members[resolvedCharacter] = resolvedRole
    local touchLootProfileDomain = ResolveOptionalApiFunction("LIDCOUNCIL_TouchLootProfileDomain")
    if type(touchLootProfileDomain) == "function" then
      touchLootProfileDomain(profile, "permissions")
    else
      profile.meta.revision = math.max(0, tonumber(profile.meta.revision) or 0) + 1
      profile.meta.updatedAt = time and time() or 0
    end
  end
  memberHelpersContext.ForceLocalRoleState = ForceLocalRoleState

  BindAllLidTableRows()

  if pointModeDropdown and pointModeDropdown.__lidcouncilCustomDropdown then
    pointModeDropdown:SetMenuBuilder(function(dropdownControl)
      return BuildPointModeDropdownMenu(dropdownControl)
    end)
  end
  if raidDropdown and raidDropdown.__lidcouncilCustomDropdown then
    raidDropdown:SetMenuBuilder(function(dropdownControl)
      return BuildRaidDropdownMenu(dropdownControl)
    end)
  end
  if raidSeasonDropdown and raidSeasonDropdown.__lidcouncilCustomDropdown then
    raidSeasonDropdown:SetMenuBuilder(function(dropdownControl)
      return BuildRaidSeasonDropdownMenu(dropdownControl)
    end)
  end
  if itemDropdown and itemDropdown.__lidcouncilCustomDropdown then
    itemDropdown:SetMenuBuilder(function(dropdownControl)
      return BuildLootItemDropdownMenu(dropdownControl)
    end)
  end
  if rollTemplateDropdown and rollTemplateDropdown.__lidcouncilCustomDropdown then
    rollTemplateDropdown:SetMenuBuilder(function(dropdownControl)
      return BuildRollTemplateDropdownMenu(dropdownControl)
    end)
  end

  local function ConfirmProfileSettingsImport(settingsLabel, targetProfileName, sourceDescription, replacementDescription, execute)
    if type(StaticPopupDialogs) ~= "table" or type(StaticPopup_Show) ~= "function" then
      feedback:SetText("Settings import confirmation is unavailable. Reload the UI and try again.")
      return false
    end
    if not StaticPopupDialogs.LIDCOUNCIL_IMPORT_PROFILE_SETTINGS_CONFIRM then
      StaticPopupDialogs.LIDCOUNCIL_IMPORT_PROFILE_SETTINGS_CONFIRM = {
        text = "%s",
        button1 = "Replace Settings",
        button2 = CANCEL,
        timeout = 0,
        whileDead = 1,
        hideOnEscape = 1,
        OnAccept = function(dialog)
          local action = dialog and dialog.data
          if type(action) == "table" and type(action.execute) == "function" then
            action.execute()
          end
        end,
      }
    end
    StaticPopup_Show(
      "LIDCOUNCIL_IMPORT_PROFILE_SETTINGS_CONFIRM",
      string.format(
        "Replace the %s in %s?\n\nImport source: %s\n\nThis replaces %s.",
        tostring(settingsLabel),
        tostring(targetProfileName),
        tostring(sourceDescription),
        tostring(replacementDescription)
      ),
      nil,
      { execute = execute }
    )
    return true
  end

  local function BuildRollSettingsProfileImportEntries(sourceControl)
    local targetProfileName = GetSelectedProfileName(editor)
    local entries = {}
    for _, profileName in ipairs(GetVisibleLootProfileNames() or {}) do
      if tostring(profileName) ~= tostring(targetProfileName) then
        entries[#entries + 1] = {
          text = tostring(profileName),
          value = tostring(profileName),
          func = function()
            if RejectCombatLockedProfileAction("Import Roll Settings") then
              return
            end
            ConfirmProfileSettingsImport(
              "roll settings",
              targetProfileName,
              "Profile: " .. tostring(profileName),
              "the current option order, icons, colors, point rules, and popup sections",
              function()
                if RejectCombatLockedProfileAction("Import Roll Settings") then
                  return
                end
                local copyRollSettings = ResolveOptionalApiFunction("LIDCOUNCIL_CopyLootRollSettings")
                if type(copyRollSettings) ~= "function" then
                  feedback:SetText("Roll settings import API unavailable.")
                  return
                end
                local ok, result = copyRollSettings(profileName, targetProfileName)
                if not ok then
                  feedback:SetText(tostring(result or "Could not import roll settings from profile."))
                  return
                end
                if sourceControl then
                  sourceControl:SetSelectedValue(nil)
                  sourceControl:SetText("Import Profile")
                end
                feedback:SetText(string.format("Imported roll settings from %s into %s.", tostring(profileName), tostring(targetProfileName)))
                RefreshProfilesPage()
              end
            )
          end,
        }
      end
    end
    if #entries == 0 then
      entries[1] = { text = "No other profiles", disabled = true, notCheckable = true }
    end
    return entries
  end

  if rollImportProfileDropdown and rollImportProfileDropdown.__lidcouncilCustomDropdown then
    rollImportProfileDropdown:SetMenuBuilder(function(control)
      return {
        width = 180,
        entries = BuildRollSettingsProfileImportEntries(control),
      }
    end)
  end
  if pointImportProfileDropdown and pointImportProfileDropdown.__lidcouncilCustomDropdown then
    pointImportProfileDropdown:SetMenuBuilder(function(control)
      local targetProfileName = GetSelectedProfileName(editor)
      local entries = {}
      for _, profileName in ipairs(GetVisibleLootProfileNames() or {}) do
        if tostring(profileName) ~= tostring(targetProfileName) then
          entries[#entries + 1] = {
            text = tostring(profileName),
            value = tostring(profileName),
            func = function()
              if RejectCombatLockedProfileAction("Import Point Settings") then
                return
              end
              ConfirmProfileSettingsImport(
                "point settings",
                targetProfileName,
                "Profile: " .. tostring(profileName),
                "the current point mode, item rules, level rules, and point values",
                function()
                  if RejectCombatLockedProfileAction("Import Point Settings") then
                    return
                  end
                  local copyPointSettings = ResolveOptionalApiFunction("LIDCOUNCIL_CopyLootPointSettings")
                  if type(copyPointSettings) ~= "function" then
                    feedback:SetText("Point settings import API unavailable.")
                    return
                  end
                  local ok, result = copyPointSettings(profileName, targetProfileName)
                  if not ok then
                    feedback:SetText(tostring(result or "Could not import point settings from profile."))
                    return
                  end
                  control:SetSelectedValue(nil)
                  control:SetText("Import From Profile")
                  feedback:SetText(string.format("Imported point settings from %s.", tostring(profileName)))
                  RefreshProfilesPage()
                end
              )
            end,
          }
        end
      end
      if #entries == 0 then
        entries[1] = { text = "No other profiles", disabled = true, notCheckable = true }
      end
      return {
        width = 180,
        entries = entries,
      }
    end)
  end

  local lootProfileLayoutHelpers = CreateLootProfileLayoutHelpers({
    RootDB = RootDB,
    GetResponsiveSectionLayout = GetResponsiveSectionLayout,
    ClampLayoutValue = ClampLayoutValue,
    SetControlWidth = SetControlWidth,
    GetFontStringWidth = GetFontStringWidth,
    FlowLayoutControls = FlowLayoutControls,
    LayoutRollOptionRow = LayoutRollOptionRow,
    LayoutPointRuleRow = LayoutPointRuleRow,
    LayoutLidTableEditorRow = LayoutLidTableEditorRow,
    TrimText = TrimText,
  })

  local function LayoutProfileContent(self)
    lootProfileLayoutHelpers.LayoutProfileContent(self, page)
  end
  if rightBg and rightBg.HookScript then
    rightBg:HookScript("OnSizeChanged", function()
      LayoutProfileContent(editor)
    end)
  end

  local lootProfileRefreshHelpers = CreateLootProfileRefreshHelpers({
    editor = editor,
    RequestProfilesPageRefresh = RefreshProfilesPage,
    RootDB = RootDB,
    GetSelectedProfileName = GetSelectedProfileName,
    GetLootProfile = GetLootProfile,
    GetLootProfileAccessInfo = GetLootProfileAccessInfo,
    GetLootProfileAccessInfoForRole = GetLootProfileAccessInfoForRole,
    GetLootProfilePermissionPolicyRoleState = GetLootProfilePermissionPolicyRoleState,
    GetLootProfileRoleEntries = GetLootProfileRoleEntries,
    SetLootProfilePermissionPolicyValue = SetLootProfilePermissionPolicyValue,
    ResetLootProfilePermissionPolicy = ResetLootProfilePermissionPolicy,
    PermissionPolicyRowDefs = PermissionPolicyRowDefs,
    SetPermissionPolicyCellState = SetPermissionPolicyCellState,
    BuildLootProfileNavRows = BuildLootProfileNavRows,
    EnsureTextListButtons = EnsureTextListButtons,
    ToggleLootProfileGroupCollapsed = ToggleLootProfileGroupCollapsed,
    SetListButtonSelected = SetListButtonSelected,
    SetTextListButtonTextColor = SetTextListButtonTextColor,
    TrimText = TrimText,
    GetActiveLootSession = GetActiveLootSession,
    GetEnabledLootProfileName = GetEnabledLootProfileName,
    GetPrimaryLootProfileName = GetPrimaryLootProfileName,
    FormatLootProfileRoleLabel = FormatLootProfileRoleLabel,
    BuildLootProfileRoleBuckets = BuildLootProfileRoleBuckets,
    ResolveProfileMemberDisplay = ResolveProfileMemberDisplay,
    ResolveProfileIconData = ResolveProfileIconData,
    GetProfileClassColor = GetProfileClassColor,
    ApplyProfileIcon = ApplyProfileIcon,
    BuildProfileClassSummary = BuildProfileClassSummary,
    RefreshProfileMemberRows = RefreshProfileMemberRows,
    ApplyProfileActionButtonStyle = ApplyProfileActionButtonStyle,
    CollectSeasonLootEntries = CollectSeasonLootEntries,
    FindRaidEntryByProfile = FindRaidEntryByProfile,
    BuildSeasonRaidNamesText = BuildSeasonRaidNamesText,
    ResolvePointMode = ResolvePointMode,
    ResolveRollTemplate = ResolveRollTemplate,
    GetRollTemplateText = GetRollTemplateText,
    ResolveRollOptionIcon = ResolveRollOptionIcon,
    ResolveRaidPreviewTexture = ResolveRaidPreviewTexture,
    ClearItemRuleSelection = ClearItemRuleSelection,
    SetDropdownValue = SetDropdownValue,
    FindSeasonLootEntry = FindSeasonLootEntry,
    FormatRaidLootItemLabel = FormatRaidLootItemLabel,
    RefreshRollOptionRows = RefreshRollOptionRows,
    RefreshPointRuleRows = RefreshPointRuleRows,
    RefreshLidTableRows = RefreshLidTableRows,
    BuildRollOptionsText = BuildRollOptionsText,
    BuildPointRulesText = BuildPointRulesText,
    BuildLidTableSummaryText = BuildLidTableSummaryText,
    LayoutProfileContent = LayoutProfileContent,
    CreatePurpleOutline = CreatePurpleOutline,
    AssignProfileToGroup = AssignProfileToGroup,
  })

  local function ConfirmProfileBackupAction(actionKind, profileName, execute)
    if type(StaticPopupDialogs) ~= "table" or type(StaticPopup_Show) ~= "function" then
      feedback:SetText("Backup confirmation is unavailable. Reload the UI and try again.")
      return false
    end

    local isRestore = actionKind == "restore"
    local dialogKey = isRestore
      and "LIDCOUNCIL_RESTORE_PROFILE_BACKUP_CONFIRM"
      or "LIDCOUNCIL_DELETE_PROFILE_BACKUP_CONFIRM"
    if not StaticPopupDialogs[dialogKey] then
      StaticPopupDialogs[dialogKey] = {
        text = isRestore
          and "Restore the selected backup for %s?\n\nThis replaces the current Loot List, session history, Live Board history, and roll statistics with the saved local snapshot. This cannot be undone."
          or "Delete the selected backup for %s?\n\nThis removes only the saved local backup. The current profile will not change.",
        button1 = isRestore and "Restore Backup" or "Delete Backup",
        button2 = CANCEL,
        timeout = 0,
        whileDead = 1,
        hideOnEscape = 1,
        preferredIndex = 3,
        OnAccept = function(dialog)
          local action = dialog and dialog.data
          if type(action) == "table" and type(action.execute) == "function" then
            action.execute()
          end
        end,
      }
    end

    StaticPopup_Show(dialogKey, tostring(profileName), nil, { execute = execute })
    return true
  end

  local function RefreshProfileBackupControls(self)
    local profileName = GetSelectedProfileName(self)
    local getBackups = type(ResolveOptionalApiFunction) == "function"
      and ResolveOptionalApiFunction("LIDCOUNCIL_GetLootProfileBackups")
      or nil
    local backups = type(getBackups) == "function" and getBackups(profileName) or {}
    backups = type(backups) == "table" and backups or {}
    self.__lootProfileBackups = backups

    local selectedId = TrimText(self.selectedLootProfileBackupId)
    local selectedLabel = ""
    for _, backup in ipairs(backups) do
      if TrimText(backup.id) == selectedId then
        selectedLabel = TrimText(backup.label)
        break
      end
    end
    if selectedLabel == "" then
      selectedId = ""
      self.selectedLootProfileBackupId = nil
    end

    if backupDropdown and backupDropdown.SetMenuBuilder then
      backupDropdown:SetMenuBuilder(function()
        local entries = {}
        for _, backup in ipairs(backups) do
          local backupId = TrimText(backup.id)
          local label = TrimText(backup.label)
          entries[#entries + 1] = {
            text = label ~= "" and label or backupId,
            checked = backupId ~= "" and backupId == TrimText(self.selectedLootProfileBackupId),
            func = function()
              self.selectedLootProfileBackupId = backupId
              if backupDropdown.SetSelectedValue then
                backupDropdown:SetSelectedValue(backupId)
              end
              if backupDropdown.SetText then
                backupDropdown:SetText(label ~= "" and label or backupId)
              end
              RefreshProfileBackupControls(self)
            end,
          }
        end
        if #entries == 0 then
          entries[1] = {
            text = "No local backups saved yet.",
            disabled = true,
            notCheckable = true,
          }
        end
        return { width = 300, entries = entries }
      end)
      if selectedId ~= "" then
        if backupDropdown.SetSelectedValue then backupDropdown:SetSelectedValue(selectedId) end
        if backupDropdown.SetText then backupDropdown:SetText(selectedLabel) end
      else
        if backupDropdown.SetSelectedValue then backupDropdown:SetSelectedValue(nil) end
        if backupDropdown.SetText then backupDropdown:SetText(#backups > 0 and "Select Saved Backup" or "No Saved Backups") end
      end
    end

    local hasProfile = TrimText(profileName) ~= ""
    local hasSelected = TrimText(self.selectedLootProfileBackupId) ~= ""
    local sessionActive = GetActiveLootSession() and true or false
    if self.lootProfileBackupText then
      self.lootProfileBackupText:SetText(sessionActive
        and "Backups are locked while a loot session is active. Stop the session before saving, restoring, or deleting local backups."
        or "Backups are saved only on this client and include the Loot List, session history, Live Board history, and roll statistics.")
    end
    if saveBackupBtn and saveBackupBtn.Enable then
      if hasProfile and not sessionActive then saveBackupBtn:Enable() else saveBackupBtn:Disable() end
    end
    if loadBackupBtn and loadBackupBtn.Enable then
      if hasSelected and not sessionActive then loadBackupBtn:Enable() else loadBackupBtn:Disable() end
    end
    if deleteBackupBtn and deleteBackupBtn.Enable then
      if hasSelected and not sessionActive then deleteBackupBtn:Enable() else deleteBackupBtn:Disable() end
    end
    if backupDropdown and backupDropdown.Enable then
      if sessionActive then backupDropdown:Disable() else backupDropdown:Enable() end
    end
  end

  local function RefreshProfilePage(self)
    lootProfileRefreshHelpers.RefreshProfilePage(self)
    if string.lower(TrimText(self.__lootProfileOpenSection)) == "backups" then
      RefreshProfileBackupControls(self)
    end
  end

  addGroupBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Create Profile Groups") then
      return
    end
    StaticPopup_Show("LIDCOUNCIL_CREATE_PROFILE_GROUP")
  end)

  prevPageBtn:SetScript("OnClick", function()
    editor.lootProfileListPage = math.max(1, tonumber(editor.lootProfileListPage or 1) - 1)
    RefreshProfilesPage()
  end)

  nextPageBtn:SetScript("OnClick", function()
    editor.lootProfileListPage = math.max(1, tonumber(editor.lootProfileListPage or 1) + 1)
    RefreshProfilesPage()
  end)

  addProfileBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Create Profiles") then
      return
    end
    StaticPopup_Show("LIDCOUNCIL_CREATE_PROFILE")
  end)

  deleteGroupBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Delete Profile Groups") then
      return
    end
    local groupName = TrimText(editor.selectedLootProfileGroupName)
    if groupName == "" then
      feedback:SetText("Select a profile group first.")
      return
    end
    editor.selectedProfileGroupName = groupName
    editor.selectedLootProfileGroupName = groupName
    StaticPopup_Show("LIDCOUNCIL_DELETE_PROFILE_GROUP", groupName)
  end)

  deleteBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Delete Profiles") then
      return
    end
    local currentName = GetSelectedProfileName(editor)
    if TrimText(currentName) == "Simulation" then
      feedback:SetText("Delete the Simulation profile from About > Developer Mode.")
      if feedback.SetTextColor then
        feedback:SetTextColor(1.00, 0.82, 0.24, 1.00)
      end
      return
    end
    local activeSession = GetActiveLootSession()
    if activeSession then
      feedback:SetText("Stop the active loot session before deleting local profile copies.")
      if feedback.SetTextColor then
        feedback:SetTextColor(1.00, 0.32, 0.32, 1.00)
      end
      return
    end
    editor.selectedProfileName = currentName
    StaticPopup_Show("LIDCOUNCIL_DELETE_PROFILE", currentName)
  end)

  activateBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Activate Profiles") then
      return
    end
    local ok, message = SetLootProfileEnabled(GetSelectedProfileName(editor), true)
    if ok == false and TrimText(message) ~= "" then
      StaticPopup_Show("LIDCOUNCIL_ACTIVE_SESSION_PROFILE_LOCK")
    end
    RefreshProfilesPage()
  end)

  deactivateBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Deactivate Profiles") then
      return
    end
    local ok, message = SetLootProfileEnabled(GetSelectedProfileName(editor), false)
    if ok == false and TrimText(message) ~= "" then
      StaticPopup_Show("LIDCOUNCIL_ACTIVE_SESSION_PROFILE_LOCK")
    end
    RefreshProfilesPage()
  end)

  copyBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Copy Profiles") then
      return
    end
    editor.selectedProfileName = GetSelectedProfileName(editor)
    StaticPopup_Show("LIDCOUNCIL_COPY_PROFILE")
  end)

  if clearSimulationBtn then
    clearSimulationBtn:SetScript("OnClick", function()
      if RejectCombatLockedProfileAction("Clear Simulation Content") then
        return
      end
      local currentName = GetSelectedProfileName(editor)
      if TrimText(currentName) ~= "Simulation" then
        feedback:SetText("Clear Content is only available for the Simulation profile.")
        if feedback.SetTextColor then
          feedback:SetTextColor(1.00, 0.32, 0.32, 1.00)
        end
        return
      end
      StaticPopup_Show("LIDCOUNCIL_CLEAR_SIMULATION_PROFILE_CONTENT", currentName)
    end)
  end

  transferMasterBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Transfer Profile Master") then
      return
    end
    local profileName = GetSelectedProfileName(editor)
    local targetKey = TrimText(editor.__lootProfileRoleTarget)
    if profileName == "" or targetKey == "" then
      feedback:SetText("Select a Council Member or Raider before transferring Profile Master.")
      return
    end

    local function ExecuteMasterTransfer()
      if RejectCombatLockedProfileAction("Transfer Profile Master") then
        return
      end
      local ok, newMaster, previousMaster = TransferLootProfileMaster(profileName, targetKey)
      if ok then
        editor.__lootProfileRoleTarget = previousMaster
        editor.__lootProfileRoleValue = "COUNCIL"
        feedback:SetText(string.format("Transferred Profile Master to %s.", tostring(newMaster or targetKey)))
        BroadcastActiveRoleUpdate(profileName, newMaster)
        BroadcastActiveRoleUpdate(profileName, previousMaster)
        RefreshProfilesPage()
      else
        feedback:SetText(tostring(newMaster or "Could not transfer the Profile Master role."))
      end
    end

    if type(StaticPopupDialogs) ~= "table" or type(StaticPopup_Show) ~= "function" then
      feedback:SetText("Transfer confirmation is unavailable. Reload the UI and try again.")
      return
    end
    if not StaticPopupDialogs.LIDCOUNCIL_TRANSFER_PROFILE_MASTER_CONFIRM then
      StaticPopupDialogs.LIDCOUNCIL_TRANSFER_PROFILE_MASTER_CONFIRM = {
        text = "Transfer Profile Master to %s?\n\n%s will gain full profile control. The current master becomes a Council Member. You can transfer master again later from Overview.",
        button1 = "Transfer Master",
        button2 = CANCEL,
        timeout = 0,
        whileDead = 1,
        hideOnEscape = 1,
        OnAccept = function(dialog)
          local action = dialog and dialog.data
          if type(action) == "table" and type(action.execute) == "function" then
            action.execute()
          end
        end,
      }
    end
    StaticPopup_Show("LIDCOUNCIL_TRANSFER_PROFILE_MASTER_CONFIRM", tostring(targetKey), tostring(targetKey), { execute = ExecuteMasterTransfer })
  end)

  if editor.lootProfilePermissionPolicyResetBtn then
    editor.lootProfilePermissionPolicyResetBtn:SetScript("OnClick", function()
      local profileName = GetSelectedProfileName(editor)
      local function ExecutePermissionPolicyReset()
        local ok, result = ResetLootProfilePermissionPolicy(profileName)
        if ok then
          feedback:SetText("Restored the default LidCouncil permission policy.")
          RefreshProfilesPage()
        else
          feedback:SetText(tostring(result or "Could not reset the permission policy."))
        end
      end

      if type(StaticPopupDialogs) ~= "table" or type(StaticPopup_Show) ~= "function" then
        feedback:SetText("Permission reset confirmation is unavailable. Reload the UI and try again.")
        return
      end
      if not StaticPopupDialogs.LIDCOUNCIL_RESET_PROFILE_PERMISSIONS_CONFIRM then
        StaticPopupDialogs.LIDCOUNCIL_RESET_PROFILE_PERMISSIONS_CONFIRM = {
          text = "Restore default permissions for %s?\n\nAll custom Host, Council, and Raider permissions will be replaced with the default policy. Locked permissions are unaffected.",
          button1 = "Restore Defaults",
          button2 = CANCEL,
          timeout = 0,
          whileDead = 1,
          hideOnEscape = 1,
          OnAccept = function(dialog)
            local action = dialog and dialog.data
            if type(action) == "table" and type(action.execute) == "function" then
              action.execute()
            end
          end,
        }
      end
      StaticPopup_Show("LIDCOUNCIL_RESET_PROFILE_PERMISSIONS_CONFIRM", tostring(profileName), nil, { execute = ExecutePermissionPolicyReset })
    end)
  end

  if raiderToggleBtn and raiderToggleBtn.SetScript then
    raiderToggleBtn:SetScript("OnClick", function()
      if not editor.__lootProfileRaidersCanCollapse then
        return
      end
      editor.__lootProfileRaidersCollapsed = not (editor.__lootProfileRaidersCollapsed and true or false)
      if not RefreshProfilesPage() then
        LayoutProfileContent(editor)
      end
    end)
    raiderToggleBtn:SetScript("OnEnter", function(self)
      if self.SetBackdropColor then
        self:SetBackdropColor(0.10, 0.10, 0.12, 0.30)
      end
    end)
    raiderToggleBtn:SetScript("OnLeave", function(self)
      if self.SetBackdropColor then
        self:SetBackdropColor(0, 0, 0, 0)
      end
    end)
  end
  if raiderFrame and raiderFrame.SetScript then
    raiderFrame:EnableMouse(false)
    raiderFrame:SetScript("OnMouseUp", nil)
  end

  local function SelectProfileTab(sectionKey)
    local resolvedKey = string.lower(TrimText(sectionKey))
    if resolvedKey == "" then
      return
    end
    editor.__lootProfileOpenSection = resolvedKey
    local refreshed = RefreshProfilesPage()
    if not refreshed then
      LayoutProfileContent(editor)
    end
    if editor.lootProfilesRightScroll and editor.lootProfilesRightScroll.SetVerticalScroll then
      editor.lootProfilesRightScroll:SetVerticalScroll(0)
    end
  end

  if overviewToggleBtn and overviewToggleBtn.SetScript then
    overviewToggleBtn:SetScript("OnClick", function()
      SelectProfileTab("overview")
    end)
  end
  if accessToggleBtn and accessToggleBtn.SetScript then
    accessToggleBtn:SetScript("OnClick", function()
      SelectProfileTab("access")
    end)
  end
  if raidToggleBtn and raidToggleBtn.SetScript then
    raidToggleBtn:SetScript("OnClick", function()
      SelectProfileTab("raid")
    end)
  end
  if rollToggleBtn and rollToggleBtn.SetScript then
    rollToggleBtn:SetScript("OnClick", function()
      SelectProfileTab("roll")
    end)
  end
  if pointsToggleBtn and pointsToggleBtn.SetScript then
    pointsToggleBtn:SetScript("OnClick", function()
      SelectProfileTab("points")
    end)
  end
  if backupToggleBtn and backupToggleBtn.SetScript then
    backupToggleBtn:SetScript("OnClick", function()
      SelectProfileTab("backups")
    end)
  end

  if saveBackupBtn and saveBackupBtn.SetScript then
    saveBackupBtn:SetScript("OnClick", function()
      if RejectCombatLockedProfileAction("Save Profile Backups") then
        return
      end
      if RejectActiveSessionBackupAction() then
        return
      end
      local saveBackup = type(ResolveOptionalApiFunction) == "function"
        and ResolveOptionalApiFunction("LIDCOUNCIL_SaveLootProfileBackup")
        or nil
      if type(saveBackup) ~= "function" then
        feedback:SetText("Backup API unavailable.")
        return
      end
      local ok, backupOrError = saveBackup(GetSelectedProfileName(editor))
      if ok then
        editor.selectedLootProfileBackupId = type(backupOrError) == "table" and TrimText(backupOrError.id) or nil
        feedback:SetText("Saved local profile backup.")
        RefreshProfileBackupControls(editor)
      else
        feedback:SetText(tostring(backupOrError or "Could not save the backup."))
      end
    end)
  end

  if loadBackupBtn and loadBackupBtn.SetScript then
    loadBackupBtn:SetScript("OnClick", function()
      if RejectCombatLockedProfileAction("Restore Profile Backup") then
        return
      end
      if RejectActiveSessionBackupAction() then
        return
      end
      local loadBackup = type(ResolveOptionalApiFunction) == "function"
        and ResolveOptionalApiFunction("LIDCOUNCIL_LoadLootProfileBackup")
        or nil
      if type(loadBackup) ~= "function" then
        feedback:SetText("Backup API unavailable.")
        return
      end
      local backupId = TrimText(editor.selectedLootProfileBackupId)
      if backupId == "" then
        feedback:SetText("Select a backup first.")
        return
      end
      local profileName = GetSelectedProfileName(editor)
      local function ExecuteBackupRestore()
        if RejectCombatLockedProfileAction("Restore Profile Backup") or RejectActiveSessionBackupAction() then
          return
        end
        local ok, result = loadBackup(profileName, backupId)
        if ok then
          feedback:SetText("Restored local profile backup.")
          RefreshProfilesPage()
        else
          feedback:SetText(tostring(result or "Could not restore the backup."))
        end
      end
      ConfirmProfileBackupAction("restore", profileName, ExecuteBackupRestore)
    end)
  end

  if deleteBackupBtn and deleteBackupBtn.SetScript then
    deleteBackupBtn:SetScript("OnClick", function()
      if RejectCombatLockedProfileAction("Delete Profile Backups") then
        return
      end
      if RejectActiveSessionBackupAction() then
        return
      end
      local deleteBackup = type(ResolveOptionalApiFunction) == "function"
        and ResolveOptionalApiFunction("LIDCOUNCIL_DeleteLootProfileBackup")
        or nil
      if type(deleteBackup) ~= "function" then
        feedback:SetText("Backup API unavailable.")
        return
      end
      local backupId = TrimText(editor.selectedLootProfileBackupId)
      if backupId == "" then
        feedback:SetText("Select a backup first.")
        return
      end
      local profileName = GetSelectedProfileName(editor)
      local function ExecuteBackupDeletion()
        if RejectCombatLockedProfileAction("Delete Profile Backup") or RejectActiveSessionBackupAction() then
          return
        end
        local ok, result = deleteBackup(profileName, backupId)
        if ok then
          editor.selectedLootProfileBackupId = nil
          feedback:SetText("Deleted selected local profile backup.")
          RefreshProfileBackupControls(editor)
        else
          feedback:SetText(tostring(result or "Could not delete the backup."))
        end
      end
      ConfirmProfileBackupAction("delete", profileName, ExecuteBackupDeletion)
    end)
  end

  saveRaidBtn:SetScript("OnClick", function()
    local profileName = GetSelectedProfileName(editor)
    if not GetLootProfileAccessInfo(profileName).canEditRaidSettings then
      feedback:SetText("Your current role cannot edit raid settings for this profile.")
      return
    end
    local ok, result = SetLootProfileRaid(profileName, nil, nil)
    if ok == false then
      feedback:SetText(tostring(result or "Could not update the raid selection."))
      return
    end
    feedback:SetText("Cleared raid selection.")
    ClearItemRuleSelection()
    RefreshProfilesPage()
  end)

  addRollBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Edit Roll Settings") then
      return
    end
    local profileName = GetSelectedProfileName(editor)
    if not GetLootProfileAccessInfo(profileName).canEditRollSettings then
      feedback:SetText("Your current role cannot edit roll settings for this profile.")
      return
    end
    local ok, result = AddLootRollOption(profileName, rollEdit:GetText())
    if ok then
      rollEdit:SetText("")
      RefreshProfilesPage()
    else
      feedback:SetText(tostring(result or "Could not add roll option."))
    end
  end)

  removeRollBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Edit Roll Settings") then
      return
    end
    local profileName = GetSelectedProfileName(editor)
    if not GetLootProfileAccessInfo(profileName).canEditRollSettings then
      feedback:SetText("Your current role cannot edit roll settings for this profile.")
      return
    end
    local profile = GetLootProfile(profileName)
    local options = profile.settings and profile.settings.rollOptions or {}
    local selectedOptionIndex = tonumber(editor.__lootSelectedRollOptionIndex)
    if not selectedOptionIndex or selectedOptionIndex < 1 or selectedOptionIndex > #options then
      feedback:SetText("Select a roll option by clicking its Select control or an empty area of the row first.")
      return
    end
    local ok, result = RemoveLootRollOption(profileName, selectedOptionIndex)
    if not ok then
      feedback:SetText(tostring(result or "Could not remove the roll option."))
      return
    end
    editor.__lootSelectedRollOptionIndex = nil
    editor.__lootSelectedRollOptionProfileName = nil
    RefreshProfilesPage()
  end)

  testRollBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Preview Roll Settings") then
      return
    end
    local profileName = GetSelectedProfileName(editor)
    if not GetLootProfileAccessInfo(profileName).canEditRollSettings then
      feedback:SetText("Your current role cannot edit roll settings for this profile.")
      return
    end
    local previewPopup = ResolveOptionalApiFunction("LIDCOUNCIL_PreviewRollChoicePopup")
    if previewPopup then
      previewPopup(profileName)
    end
  end)

  previewHostBoardBtn:SetScript("OnClick", function()
    if RejectCombatLockedProfileAction("Preview Roll Settings") then
      return
    end
    local profileName = GetSelectedProfileName(editor)
    if not GetLootProfileAccessInfo(profileName).canEditRollSettings then
      feedback:SetText("Your current role cannot edit roll settings for this profile.")
      return
    end
    local previewBoard = ResolveOptionalApiFunction("LIDCOUNCIL_PreviewLiveLootBoard")
    if previewBoard then
      previewBoard(profileName)
    end
  end)

  local function RunRollSettingsExport()
      if RejectCombatLockedProfileAction("Export Roll Settings") then
        return
      end
      local exportRollSettings = ResolveOptionalApiFunction("LIDCOUNCIL_ExportLootRollSettings")
      local showExportWindow = ResolveOptionalApiFunction("LIDCOUNCIL_ShowExportWindow")
      if type(exportRollSettings) ~= "function" or type(showExportWindow) ~= "function" then
        feedback:SetText("Roll settings export window unavailable.")
        return
      end
      local profileName = GetSelectedProfileName(editor)
      if not GetLootProfileAccessInfo(profileName).canEditRollSettings then
        feedback:SetText("Your current role cannot edit roll settings for this profile.")
        return
      end
      local exported = exportRollSettings(profileName)
      if not exported then
        feedback:SetText("Could not create a roll settings export.")
        return
      end
      showExportWindow(profileName .. " Roll Settings", exported)
      feedback:SetText("Roll settings export ready. Copy the text from the export window.")
  end

  if rollExportBtn then
    rollExportBtn:SetScript("OnClick", RunRollSettingsExport)
  end

  local function RunRollSettingsTextImport()
      if RejectCombatLockedProfileAction("Import Roll Settings") then
        return
      end
      local importRollSettings = ResolveOptionalApiFunction("LIDCOUNCIL_ImportLootRollSettings")
      local showImportWindow = ResolveOptionalApiFunction("LIDCOUNCIL_ShowSettingsImportWindow")
      if type(importRollSettings) ~= "function" or type(showImportWindow) ~= "function" then
        feedback:SetText("Roll settings import window unavailable.")
        return
      end
      local profileName = GetSelectedProfileName(editor)
      if not GetLootProfileAccessInfo(profileName).canEditRollSettings then
        feedback:SetText("Your current role cannot edit roll settings for this profile.")
        return
      end
      showImportWindow(function(_, pasted)
        if RejectCombatLockedProfileAction("Import Roll Settings") then
          return
        end
        ConfirmRollSettingsImport(profileName, "Pasted roll settings", function()
          if RejectCombatLockedProfileAction("Import Roll Settings") then
            return
          end
          local ok, result = importRollSettings(profileName, pasted)
          if not ok then
            feedback:SetText(tostring(result or "Could not import roll settings."))
            return
          end
          feedback:SetText("Imported roll settings into " .. tostring(profileName) .. ".")
          RefreshProfilesPage()
        end)
      end, {
        title = "Import Roll Settings Text",
        requireName = false,
        buttonText = "Import Settings",
        placeholder = "Paste a LidCouncil roll settings export here",
      })
  end

  if rollImportStringBtn then
    rollImportStringBtn:SetScript("OnClick", RunRollSettingsTextImport)
  end

  if rollSettingsToolsDropdown and rollSettingsToolsDropdown.__lidcouncilCustomDropdown then
    rollSettingsToolsDropdown:SetMenuBuilder(function()
      local entries = {
        {
          text = "Export Roll Settings",
          notCheckable = true,
          func = RunRollSettingsExport,
        },
        {
          text = "Import From Text",
          notCheckable = true,
          func = RunRollSettingsTextImport,
        },
        {
          text = "Import From Profile",
          isTitle = true,
          notCheckable = true,
        },
      }
      for _, entry in ipairs(BuildRollSettingsProfileImportEntries()) do
        entries[#entries + 1] = entry
      end
      return {
        width = 250,
        maxVisibleEntries = 12,
        entries = entries,
      }
    end)
  end

  local function SetPointRuleFeedback(message)
    local resolvedMessage = TrimText(message or "")
    if editor.lootPointRuleFeedback then
      editor.lootPointRuleFeedback:SetText(resolvedMessage)
      editor.lootPointRuleFeedback:SetShown(resolvedMessage ~= "")
    end
    if feedback then
      feedback:SetText(resolvedMessage)
    end
  end

  local function ValidatePointRulePoints(pointsField)
    local pointsText = TrimText(pointsField and pointsField:GetText() or "")
    if pointsText == "" then
      SetPointRuleFeedback("Enter points before adding this rule. Use 0 explicitly when no points should be awarded.")
      if pointsField and pointsField.SetFocus then
        pointsField:SetFocus()
      end
      return nil
    end
    if not tonumber(pointsText) then
      SetPointRuleFeedback("Points must be numeric.")
      if pointsField and pointsField.SetFocus then
        pointsField:SetFocus()
      end
      return nil
    end
    return pointsText
  end

  addLevelRuleBtn:SetScript("OnClick", function()
    local profileName = GetSelectedProfileName(editor)
    if not GetLootProfileAccessInfo(profileName).canEditPointSettings then
      feedback:SetText("Your current role cannot edit point settings for this profile.")
      return
    end
    local itemLevelText = TrimText(levelEdit and levelEdit:GetText() or "")
    local itemLevel = tonumber(itemLevelText)
    if itemLevelText == "" then
      SetPointRuleFeedback("Enter an item level before adding a level rule.")
      if levelEdit and levelEdit.SetFocus then
        levelEdit:SetFocus()
      end
      return
    end
    if not itemLevel or itemLevel <= 0 or itemLevel ~= math.floor(itemLevel) then
      SetPointRuleFeedback("Item level must be a positive whole number.")
      if levelEdit and levelEdit.SetFocus then
        levelEdit:SetFocus()
      end
      return
    end
    local pointsText = ValidatePointRulePoints(levelPointsEdit)
    if not pointsText then
      return
    end
    SetPointRuleFeedback(nil)
    local ok, result = AddLootPointRule(profileName, {
      mode = "itemLevel",
      itemLevel = itemLevelText,
      points = pointsText,
    })
    if ok then
      levelEdit:SetText("")
      levelPointsEdit:SetText("")
      RefreshProfilesPage()
    else
      SetPointRuleFeedback(tostring(result or "Could not add item-level rule."))
    end
  end)

  addItemRuleBtn:SetScript("OnClick", function()
    local profileName = GetSelectedProfileName(editor)
    if not GetLootProfileAccessInfo(profileName).canEditPointSettings then
      feedback:SetText("Your current role cannot edit point settings for this profile.")
      return
    end
    local selectedItemID = ExtractItemID(editor.__lootSelectedRuleItemID)
    local selectedItem = FindSeasonLootEntry(selectedItemID)
    if not selectedItemID then
      SetPointRuleFeedback("Select a profile-season loot item before adding an item rule.")
      return
    end
    local pointsText = ValidatePointRulePoints(itemPointsEdit)
    if not pointsText then
      return
    end
    SetPointRuleFeedback(nil)
    local ok, result = AddLootPointRule(profileName, {
      mode = "item",
      itemID = selectedItem and selectedItem.itemID or selectedItemID,
      itemName = selectedItem and selectedItem.name or editor.__lootSelectedRuleItemName,
      itemLink = selectedItem and selectedItem.link or editor.__lootSelectedRuleItemLink,
      itemLevel = selectedItem and selectedItem.itemLevel or editor.__lootSelectedRuleItemLevel,
      points = pointsText,
    })
    if ok then
      itemPointsEdit:SetText("")
      RefreshProfilesPage()
    else
      SetPointRuleFeedback(tostring(result or "Could not add item rule."))
    end
  end)

  removeRuleBtn:SetScript("OnClick", function()
    local profileName = GetSelectedProfileName(editor)
    if not GetLootProfileAccessInfo(profileName).canEditPointSettings then
      feedback:SetText("Your current role cannot edit point settings for this profile.")
      return
    end
    local profile = GetLootProfile(profileName)
    local rules = profile.settings and profile.settings.pointRules or {}
    local selectedRuleIndex = tonumber(editor.__lootSelectedPointRuleIndex)
    if editor.__lootSelectedPointRuleProfileName ~= profileName
      or not selectedRuleIndex
      or selectedRuleIndex < 1
      or selectedRuleIndex > #rules then
      feedback:SetText("Select a point rule by clicking its Select control or an empty area of the row first.")
      return
    end
    local ok, result = RemoveLootPointRule(profileName, selectedRuleIndex)
    if not ok then
      feedback:SetText(tostring(result or "Could not remove the point rule."))
      return
    end
    editor.__lootSelectedPointRuleIndex = nil
    editor.__lootSelectedPointRuleProfileName = nil
    RefreshProfilesPage()
  end)

  if pointExportBtn then
    pointExportBtn:SetScript("OnClick", function()
      local exportPointSettings = ResolveOptionalApiFunction("LIDCOUNCIL_ExportLootPointSettings")
      local showExportWindow = ResolveOptionalApiFunction("LIDCOUNCIL_ShowExportWindow")
      if type(exportPointSettings) ~= "function" or type(showExportWindow) ~= "function" then
        feedback:SetText("Point settings export window unavailable.")
        return
      end
      local profileName = GetSelectedProfileName(editor)
      if not GetLootProfileAccessInfo(profileName).canEditPointSettings then
        feedback:SetText("Your current role cannot edit point settings for this profile.")
        return
      end
      local exported = exportPointSettings(profileName)
      if not exported then
        feedback:SetText("Point settings export failed.")
        return
      end
      showExportWindow(profileName .. " Point Settings", exported)
    end)
  end

  if pointImportStringBtn then
    pointImportStringBtn:SetScript("OnClick", function()
      if RejectCombatLockedProfileAction("Import Point Settings") then
        return
      end
      local importPointSettings = ResolveOptionalApiFunction("LIDCOUNCIL_ImportLootPointSettings")
      local showImportWindow = ResolveOptionalApiFunction("LIDCOUNCIL_ShowSettingsImportWindow")
      if type(importPointSettings) ~= "function" or type(showImportWindow) ~= "function" then
        feedback:SetText("Point settings import window unavailable.")
        return
      end
      local profileName = GetSelectedProfileName(editor)
      if not GetLootProfileAccessInfo(profileName).canEditPointSettings then
        feedback:SetText("Your current role cannot edit point settings for this profile.")
        return
      end
      showImportWindow(function(_, pasted)
        if RejectCombatLockedProfileAction("Import Point Settings") then
          return
        end
        ConfirmProfileSettingsImport(
          "point settings",
          profileName,
          "Pasted point settings",
          "the current point mode, item rules, level rules, and point values",
          function()
            if RejectCombatLockedProfileAction("Import Point Settings") then
              return
            end
            local ok, result = importPointSettings(profileName, pasted)
            if not ok then
              feedback:SetText(tostring(result or "Could not import point settings."))
              return
            end
            feedback:SetText("Imported point settings.")
            RefreshProfilesPage()
          end
        )
      end, {
        title = "Import Point Settings",
        requireName = false,
        buttonText = "Import",
        placeholder = "Click here and insert your point settings string",
      })
    end)
  end

  editor.RefreshLootProfilePage = function(self)
    local pageStartedAt = INTERNAL_API.LIDCOUNCIL_BeginSyncPerformanceSample_Impl("editor_page_profiles", 1)
    local profileSection = string.lower(TrimText(self and self.__lootProfileOpenSection or "overview"))
    local root = RootDB()
    local importExportFeatureEnabled = type(root.ui) == "table"
      and root.ui.developerMode == true
      and root.ui.importExportFeature == true
    if profileSection == "transfer" and not importExportFeatureEnabled then
      profileSection = "overview"
      if self then
        self.__lootProfileOpenSection = profileSection
      end
    end
    if profileSection ~= "overview" and profileSection ~= "access" and profileSection ~= "raid"
      and profileSection ~= "roll" and profileSection ~= "points" and profileSection ~= "backups"
      and profileSection ~= "transfer" then
      profileSection = "overview"
    end
    local sectionMetric = "editor_profile_" .. profileSection
    local sectionStartedAt = INTERNAL_API.LIDCOUNCIL_BeginSyncPerformanceSample_Impl(sectionMetric, 1)
    RefreshProfilePage(self)
    INTERNAL_API.LIDCOUNCIL_RecordSyncPerformance_Impl(sectionMetric, sectionStartedAt, {
      context = profileSection,
    })
    INTERNAL_API.LIDCOUNCIL_RecordSyncPerformance_Impl("editor_page_profiles", pageStartedAt, {
      context = profileSection,
    })
    if self and (not self.__refreshing) and self.ApplyTheme then
      self:ApplyTheme()
    end
  end
  editor.LayoutLootProfilePage = LayoutProfileContent
end

INTERNAL_API.LIDCOUNCIL_BuildLootProfilesPage_Impl = BuildLootProfilesPage

