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

local RequireApi = INTERNAL_API.LIDPANELS_RequireApi_Impl
local RegisterTutorialTexture = INTERNAL_API.LIDPANELS_RegisterTutorialTexture_Impl
local SetDropdownSelection = INTERNAL_API.LIDPANELS_SetDropdownSelection_Impl
local GetDropdownMenuWidth = INTERNAL_API.LIDPANELS_GetDropdownMenuWidth_Impl
local BindMouseWheelScroll = INTERNAL_API.LIDPANELS_BindMouseWheelScroll_Impl
local BindScrollChildWidth = INTERNAL_API.LIDPANELS_BindScrollChildWidth_Impl
if type(RequireApi) ~= "function"
  or type(RegisterTutorialTexture) ~= "function"
  or type(SetDropdownSelection) ~= "function"
  or type(GetDropdownMenuWidth) ~= "function"
  or type(BindMouseWheelScroll) ~= "function"
  or type(BindScrollChildWidth) ~= "function" then
  error("LidPanels missing shared editor page helpers.")
end

local RootDB = RequireApi("LIDPANELS_RootDB", _G.LIDPANELS_RootDB)
local EnsureDefaults = RequireApi("LIDPANELS_EnsureDefaults", _G.LIDPANELS_EnsureDefaults)
local Print = RequireApi("LIDPANELS_Print", _G.LIDPANELS_Print)
local ExportProfile = RequireApi("LIDPANELS_ExportProfile", _G.LIDPANELS_ExportProfile)
local ImportProfile = RequireApi("LIDPANELS_ImportProfile", _G.LIDPANELS_ImportProfile)
local GetCurrentSpecID = RequireApi("LIDPANELS_GetCurrentSpecID", _G.LIDPANELS_GetCurrentSpecID)
local ApplyFrameSkin = RequireApi("LIDPANELS_ApplyFrameSkin", _G.LIDPANELS_ApplyFrameSkin)
local MakeYellowSubHeader = RequireApi("LIDPANELS_MakeYellowSubHeader", _G.LIDPANELS_MakeYellowSubHeader)
local CARD_W = RequireApi("LIDPANELS_CARD_W", _G.LIDPANELS_CARD_W)
local CARD_H = RequireApi("LIDPANELS_CARD_H", _G.LIDPANELS_CARD_H)
local RebuildAllPanels = RequireApi("LIDPANELS_RebuildAllPanels", _G.LIDPANELS_RebuildAllPanels)
local SwitchProfile = RequireApi("LIDPANELS_SwitchProfile", _G.LIDPANELS_SwitchProfile)
local ShowExportWindow = RequireApi("LIDPANELS_ShowExportWindow", _G.LIDPANELS_ShowExportWindow)
local ShowImportWindow = RequireApi("LIDPANELS_ShowImportWindow", _G.LIDPANELS_ShowImportWindow)
local CreateCustomDropdownControl = RequireApi("LIDPANELS_CreateCustomDropdownControl", _G.LIDPANELS_CreateCustomDropdownControl)

local Compat = rawget(_G, "LIDPANELS_Compat")
local LogSilent = rawget(_G, "LIDPANELS_LogSilent")

local PROFILE_DROPDOWN_PAGE_SIZE = 19
local PROFILE_DROPDOWN_WIDTH = 250

local function RefreshProfilesList(editor)
  if editor.RefreshProfilesListSection then
    editor:RefreshProfilesListSection()
  elseif editor.RefreshProfilesSection then
    editor:RefreshProfilesSection()
  elseif editor.Refresh then
    editor:Refresh()
  end
end

local function RefreshProfileDetails(editor)
  if editor.RefreshProfileDetailsSection then
    editor:RefreshProfileDetailsSection()
  elseif editor.RefreshProfilesSection then
    editor:RefreshProfilesSection()
  elseif editor.Refresh then
    editor:Refresh()
  end
end

local function RefreshCurrentProfile(editor)
  if editor.RefreshCurrentProfileSections then
    editor:RefreshCurrentProfileSections()
  elseif editor.Refresh then
    editor:Refresh()
  end
end

local function SetCheckButtonLabel(checkButton, text)
  if not checkButton or not checkButton.GetName then return nil end
  local label = _G[checkButton:GetName() .. "Text"]
  if label then
    label:SetText(text or "")
  end
  return label
end

local function EnsureProfileAutoSwitchConfig(profile)
  if not profile then return nil end
  profile.profileSpec = profile.profileSpec or {
    enabled = false,
    mode = "SPEC",
    specID = nil,
    character = nil,
  }
  if profile.profileSpec.enabled == nil then
    profile.profileSpec.enabled = false
  end
  if profile.profileSpec.mode ~= "CHARACTER" then
    profile.profileSpec.mode = "SPEC"
  end
  return profile.profileSpec
end

local function GetCurrentCharacterKeyForProfiles()
  if Compat and Compat.GetCharacterKey then
    return Compat.GetCharacterKey()
  end
  return nil
end

local specOptionsCache

local function BuildSpecOptions()
  if specOptionsCache then
    return specOptionsCache
  end

  local options = {}
  local seen = {}
  if Compat and Compat.GetNumClasses and Compat.GetNumSpecializationsForClassID
    and Compat.GetSpecializationInfoForClassID and Compat.GetClassInfo then
    local numClasses = Compat.GetNumClasses()
    for classID = 1, numClasses do
      local className = select(1, Compat.GetClassInfo(classID))
      local specCount = Compat.GetNumSpecializationsForClassID(classID)
      for index = 1, specCount do
        local id, name, _, icon, role = Compat.GetSpecializationInfoForClassID(classID, index)
        if id and name and not seen[id] then
          local text = (className and (className .. "_" .. name)) or name
          if role then
            text = text .. " (" .. role .. ")"
          end
          options[#options + 1] = {
            id = id,
            text = text,
            icon = icon,
            iconSize = 16,
            iconXOffset = -8,
          }
          seen[id] = true
        end
      end
    end
  elseif Compat and Compat.GetNumSpecializations and Compat.GetSpecializationInfo then
    local specCount = Compat.GetNumSpecializations()
    for index = 1, specCount do
      local id, name, _, icon, role, className = Compat.GetSpecializationInfo(index)
      if id and name then
        local text = name
        if className then
          text = className .. "_" .. name
        end
        if role then
          text = text .. " (" .. role .. ")"
        end
        options[#options + 1] = {
          id = id,
          text = text,
          icon = icon,
          iconSize = 16,
          iconXOffset = -8,
        }
      end
    end
  end

  table.sort(options, function(a, b)
    return a.text < b.text
  end)
  specOptionsCache = options
  return specOptionsCache
end

local characterOptionsCacheKey
local characterOptionsCache

local function BuildCharacterOptions()
  local list = {}
  if Compat and Compat.GetCharacterList then
    list = Compat.GetCharacterList()
  end
  if #list == 0 then
    local current = GetCurrentCharacterKeyForProfiles()
    if current then
      list = { current }
    end
  end

  local keyParts = {}
  for index, name in ipairs(list) do
    keyParts[index] = tostring(name or "")
  end
  local cacheKey = table.concat(keyParts, "\31")
  if characterOptionsCacheKey == cacheKey and characterOptionsCache then
    return characterOptionsCache
  end

  local cached = {}
  for index, name in ipairs(list) do
    cached[index] = name
  end
  characterOptionsCacheKey = cacheKey
  characterOptionsCache = cached
  return characterOptionsCache
end

local function ClampProfileDropdownPage(page, totalPages)
  if page < 1 then return 1 end
  if page > totalPages then return totalPages end
  return page
end

local function BuildProfilePagedEntries(editor, pageKey, options, currentValue, onSelect, opts)
  opts = opts or {}
  options = options or {}

  local total = #options
  local totalPages = math.max(1, math.ceil(total / PROFILE_DROPDOWN_PAGE_SIZE))
  local pages = editor.profileDropdownPages or {}
  local page = ClampProfileDropdownPage(pages[pageKey] or 1, totalPages)
  pages[pageKey] = page
  editor.profileDropdownPages = pages

  local first = ((page - 1) * PROFILE_DROPDOWN_PAGE_SIZE) + 1
  local last = math.min(total, first + PROFILE_DROPDOWN_PAGE_SIZE - 1)

  local extraLabels = {}
  for _, label in ipairs(opts.extraLabels or {}) do
    extraLabels[#extraLabels + 1] = label
  end
  if totalPages > 1 then
    extraLabels[#extraLabels + 1] = string.format("Page %d/%d", totalPages, totalPages)
    extraLabels[#extraLabels + 1] = "< Prev"
    extraLabels[#extraLabels + 1] = "Next >"
  end

  local listWidth = GetDropdownMenuWidth(
    editor,
    opts.measurerKey or "__lidPanelsProfileDropdownMeasurer",
    opts.minWidth or PROFILE_DROPDOWN_WIDTH,
    options,
    extraLabels,
    opts.maxWidth or 420
  )

  local entries = {}
  for index = first, last do
    local option = options[index]
    if option then
      local value = option.value or option.id
      entries[#entries + 1] = {
        text = option.text,
        value = value,
        icon = option.icon,
        iconSize = option.iconSize or (option.icon and 16 or nil),
        iconXOffset = option.iconXOffset,
        checked = (value == currentValue),
        func = function()
          if onSelect then
            onSelect(option)
          end
        end,
      }
    end
  end

  if totalPages > 1 then
    entries[#entries + 1] = {
      text = string.format("Page %d/%d", page, totalPages),
      isTitle = true,
      notCheckable = true,
    }
    entries[#entries + 1] = {
      text = "< Prev",
      notCheckable = true,
      disabled = (page <= 1),
      keepShownOnClick = true,
      func = function()
        local pagesRef = editor.profileDropdownPages or {}
        pagesRef[pageKey] = ClampProfileDropdownPage(page - 1, totalPages)
        editor.profileDropdownPages = pagesRef
      end,
    }
    entries[#entries + 1] = {
      text = "Next >",
      notCheckable = true,
      disabled = (page >= totalPages),
      keepShownOnClick = true,
      func = function()
        local pagesRef = editor.profileDropdownPages or {}
        pagesRef[pageKey] = ClampProfileDropdownPage(page + 1, totalPages)
        editor.profileDropdownPages = pagesRef
      end,
    }
  end

  local function OnMouseWheel(delta)
    if totalPages <= 1 then
      return false
    end
    local pagesRef = editor.profileDropdownPages or {}
    local currentPage = ClampProfileDropdownPage(pagesRef[pageKey] or 1, totalPages)
    local targetPage = ClampProfileDropdownPage(currentPage - delta, totalPages)
    if targetPage == currentPage then
      return false
    end
    pagesRef[pageKey] = targetPage
    editor.profileDropdownPages = pagesRef
    return true
  end

  return entries, listWidth, OnMouseWheel
end

local function BuildProfilesPage(editor, profilesPage)
  if not editor or not profilesPage then return end

  local profTitle = profilesPage:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
  profTitle:SetPoint("TOPLEFT", 0, 0)
  profTitle:SetText("Profiles")

  local currentLabel = profilesPage:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  currentLabel:SetPoint("TOPLEFT", 0, -22)
  editor.profileLabel = currentLabel

  local profListBg = CreateFrame("Frame", nil, profilesPage, "BackdropTemplate")
  profListBg:SetPoint("TOPLEFT", 0, -44)
  profListBg:SetPoint("BOTTOMLEFT", 0, 0)
  profListBg:SetWidth(240)
  ApplyFrameSkin(profListBg)
  editor.profListBg = profListBg

  local profScroll = CreateFrame("ScrollFrame", nil, profListBg, "UIPanelScrollFrameTemplate")
  profScroll:SetPoint("TOPLEFT", 6, -6)
  profScroll:SetPoint("BOTTOMRIGHT", -28, 64)
  editor.profScroll = profScroll

  local profContent = CreateFrame("Frame", nil, profScroll)
  profContent:SetSize(1, 1)
  profScroll:SetScrollChild(profContent)
  editor.profContent = profContent
  editor.profButtons = {}
  editor.selectedProfileName = nil
  editor.selectedProfileGroupName = nil

  local profPrevBtn = CreateFrame("Button", nil, profListBg, "UIPanelButtonTemplate")
  profPrevBtn:SetSize(60, 20)
  profPrevBtn:SetPoint("BOTTOMLEFT", 6, 34)
  profPrevBtn:SetText("< Prev")
  profPrevBtn:SetScript("OnClick", function()
    editor.profListPage = math.max(1, (editor.profListPage or 1) - 1)
    RefreshProfilesList(editor)
  end)
  editor.profPrevBtn = profPrevBtn

  local profNextBtn = CreateFrame("Button", nil, profListBg, "UIPanelButtonTemplate")
  profNextBtn:SetSize(60, 20)
  profNextBtn:SetPoint("BOTTOMLEFT", 138, 34)
  profNextBtn:SetText("Next >")
  profNextBtn:SetScript("OnClick", function()
    editor.profListPage = (editor.profListPage or 1) + 1
    RefreshProfilesList(editor)
  end)
  editor.profNextBtn = profNextBtn

  local profPageText = profListBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  profPageText:SetPoint("LEFT", profPrevBtn, "RIGHT", 8, 0)
  profPageText:SetWidth(64)
  profPageText:SetJustifyH("CENTER")
  editor.profPageText = profPageText

  local newProfBtn = CreateFrame("Button", nil, profListBg, "UIPanelButtonTemplate")
  newProfBtn:SetSize(96, 22)
  newProfBtn:SetPoint("BOTTOMLEFT", 6, 8)
  newProfBtn:SetText("Create Profile")
  newProfBtn:SetScript("OnClick", function()
    StaticPopup_Show("LIDPANELS_CREATE_PROFILE")
  end)
  editor.newProfBtn = newProfBtn

  local newProfGroupBtn = CreateFrame("Button", nil, profListBg, "UIPanelButtonTemplate")
  newProfGroupBtn:SetSize(96, 22)
  newProfGroupBtn:SetPoint("LEFT", newProfBtn, "RIGHT", 8, 0)
  newProfGroupBtn:SetText("Create Group")
  newProfGroupBtn:SetScript("OnClick", function()
    StaticPopup_Show("LIDPANELS_CREATE_PROFILE_GROUP")
  end)
  editor.newProfGroupBtn = newProfGroupBtn

  local profRightBg = CreateFrame("Frame", nil, profilesPage, "BackdropTemplate")
  profRightBg:SetPoint("TOPLEFT", profListBg, "TOPRIGHT", 12, 0)
  profRightBg:SetPoint("BOTTOMRIGHT", 0, 0)
  ApplyFrameSkin(profRightBg)
  editor.profRightBg = profRightBg

  local profRightScroll = CreateFrame("ScrollFrame", nil, profRightBg, "UIPanelScrollFrameTemplate")
  profRightScroll:SetPoint("TOPLEFT", 18, -12)
  profRightScroll:SetPoint("BOTTOMRIGHT", -28, 12)
  BindMouseWheelScroll(profRightScroll)

  local profRight = CreateFrame("Frame", nil, profRightScroll)
  profRight:SetSize(1, 1)
  profRightScroll:SetScrollChild(profRight)
  editor.profRightScroll = profRightScroll
  BindScrollChildWidth(profRightScroll, profRight, {
    logSilent = LogSilent,
    warningPrefix = "Profiles right scroll OnSizeChanged failed: ",
  })

  local profGroupScroll = CreateFrame("ScrollFrame", nil, profRightBg, "UIPanelScrollFrameTemplate")
  profGroupScroll:SetPoint("TOPLEFT", 18, -12)
  profGroupScroll:SetPoint("BOTTOMRIGHT", -28, 12)
  BindMouseWheelScroll(profGroupScroll)
  profGroupScroll:Hide()
  editor.profGroupScroll = profGroupScroll

  local profGroup = CreateFrame("Frame", nil, profGroupScroll)
  profGroup:SetSize(1, 1)
  profGroupScroll:SetScrollChild(profGroup)
  editor.profGroupFrame = profGroup
  BindScrollChildWidth(profGroupScroll, profGroup, {
    logSilent = LogSilent,
    warningPrefix = "Profiles group scroll OnSizeChanged failed: ",
  })

  local profWelcomeScroll = CreateFrame("ScrollFrame", nil, profRightBg, "UIPanelScrollFrameTemplate")
  profWelcomeScroll:SetPoint("TOPLEFT", 18, -12)
  profWelcomeScroll:SetPoint("BOTTOMRIGHT", -28, 12)
  BindMouseWheelScroll(profWelcomeScroll)
  profWelcomeScroll:Hide()
  editor.profWelcomeScroll = profWelcomeScroll

  local profWelcomeFrame = CreateFrame("Frame", nil, profWelcomeScroll)
  profWelcomeFrame:SetPoint("TOPLEFT", 0, 0)
  profWelcomeFrame:SetSize(1, 1)
  profWelcomeFrame:SetClipsChildren(true)
  profWelcomeScroll:SetScrollChild(profWelcomeFrame)
  editor.profWelcomeFrame = profWelcomeFrame
  BindScrollChildWidth(profWelcomeScroll, profWelcomeFrame, {
    onResize = function()
      if editor and editor.LayoutProfileWelcome then
        editor:LayoutProfileWelcome()
      end
    end,
    logSilent = LogSilent,
    warningPrefix = "Profiles welcome scroll OnSizeChanged failed: ",
  })

  local welcomeHeader = profWelcomeFrame:CreateTexture(nil, "ARTWORK")
  welcomeHeader:SetPoint("TOPLEFT", 18, -18)
  RegisterTutorialTexture(editor, welcomeHeader, "Interface\\AddOns\\LidPanels\\Media\\Lidpanels\\Tutorials\\Profiles_1_Title.tga")
  welcomeHeader:SetTexCoord(0, 1, 0, 1)
  editor.profWelcomeHeader = welcomeHeader

  local function MakeProfileCard(parent, texturePath)
    local card = CreateFrame("Frame", nil, parent)
    card:SetPoint("TOPLEFT", 0, 0)
    card:SetSize(CARD_W, CARD_H)

    local texture = card:CreateTexture(nil, "ARTWORK")
    texture:SetPoint("TOPLEFT", 0, 0)
    texture:SetPoint("BOTTOMRIGHT", 0, 0)
    RegisterTutorialTexture(editor, texture, texturePath)
    texture:SetTexCoord(0, 1, 0, 1)
    card.texObj = texture
    return card
  end

  editor.profWelcomeCards = {
    MakeProfileCard(profWelcomeFrame, "Interface\\AddOns\\LidPanels\\Media\\Lidpanels\\Tutorials\\Profile_2_Step1.tga"),
    MakeProfileCard(profWelcomeFrame, "Interface\\AddOns\\LidPanels\\Media\\Lidpanels\\Tutorials\\Profile_3_Step2.tga"),
    MakeProfileCard(profWelcomeFrame, "Interface\\AddOns\\LidPanels\\Media\\Lidpanels\\Tutorials\\Profile_4_Step3.tga"),
    MakeProfileCard(profWelcomeFrame, "Interface\\AddOns\\LidPanels\\Media\\Lidpanels\\Tutorials\\Profile_5_Step4.tga"),
  }

  function editor:LayoutProfileWelcome()
    if not self.profWelcomeFrame or not self.profWelcomeCards then return end
    local availableWidth = self.profWelcomeFrame:GetWidth()
    if not availableWidth or availableWidth < 1 then return end

    local leftPad = 18
    local cols = 2
    local gap = 20
    local rowWidth = availableWidth - leftPad
    local cardWidth = math.max(1, math.floor((rowWidth - gap) / 2))
    local cardHeight = math.floor(cardWidth * 0.75)
    local headerWidth = (cardWidth * 2) + gap
    local headerHeight = math.floor(cardHeight * 0.6)

    if self.profWelcomeHeader then
      self.profWelcomeHeader:SetSize(headerWidth, headerHeight)
      self.profWelcomeHeader:ClearAllPoints()
      self.profWelcomeHeader:SetPoint("TOPLEFT", leftPad, -18)
    end

    local y = -18 - headerHeight - 20
    local index = 1
    for row = 1, 2 do
      for col = 1, cols do
        local card = self.profWelcomeCards[index]
        if not card then break end
        local x = leftPad + ((col - 1) * (cardWidth + gap))
        card:SetSize(cardWidth, cardHeight)
        card:ClearAllPoints()
        card:SetPoint("TOPLEFT", x, y)
        index = index + 1
      end
      y = y - cardHeight - 20
    end

    local contentHeight = math.max(400, (-y) + 80)
    self.profWelcomeFrame:SetHeight(contentHeight)
    if self.profWelcomeScroll and self.profWelcomeScroll.UpdateScrollChildRect then
      self.profWelcomeScroll:UpdateScrollChildRect()
    end
  end

  local selProf = profRight:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
  selProf:SetPoint("TOPLEFT", 0, 0)
  selProf:SetText("Selected: (none)")
  editor.selProfLabel = selProf

  local selProfGroup = profGroup:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
  selProfGroup:SetPoint("TOPLEFT", 0, 0)
  selProfGroup:SetText("Selected Group: (none)")
  editor.selProfGroupLabel = selProfGroup

  MakeYellowSubHeader(profGroup, "Modify Group", 0, -26)

  local renameProfGroupBtn = CreateFrame("Button", nil, profGroup, "UIPanelButtonTemplate")
  renameProfGroupBtn:SetSize(160, 22)
  renameProfGroupBtn:SetPoint("TOPLEFT", 0, -50)
  renameProfGroupBtn:SetText("Rename Group")
  renameProfGroupBtn:SetScript("OnClick", function()
    if not editor.selectedProfileGroupName then return end
    StaticPopup_Show("LIDPANELS_RENAME_PROFILE_GROUP")
  end)
  editor.renameProfGroupBtn = renameProfGroupBtn

  local delProfGroupBtn = CreateFrame("Button", nil, profGroup, "UIPanelButtonTemplate")
  delProfGroupBtn:SetSize(160, 22)
  delProfGroupBtn:SetPoint("TOPLEFT", 0, -78)
  delProfGroupBtn:SetText("Delete Group")
  delProfGroupBtn:SetScript("OnClick", function()
    if not editor.selectedProfileGroupName then return end
    StaticPopup_Show("LIDPANELS_DELETE_PROFILE_GROUP", editor.selectedProfileGroupName)
  end)
  editor.delProfGroupBtn = delProfGroupBtn

  local profGroupInfo = profGroup:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  profGroupInfo:SetPoint("TOPLEFT", 0, -118)
  profGroupInfo:SetWidth(520)
  profGroupInfo:SetJustifyH("LEFT")
  profGroupInfo:SetText("Deleting a group will only ungroup its profiles.")
  editor.profGroupInfoLabel = profGroupInfo
  profGroup:SetHeight(220)

  MakeYellowSubHeader(profRight, "Activate Profile", 0, -26)

  local activateBtn = CreateFrame("Button", nil, profRight, "UIPanelButtonTemplate")
  activateBtn:SetSize(120, 22)
  activateBtn:SetPoint("TOPLEFT", 0, -50)
  activateBtn:SetText("Activate")
  activateBtn:SetScript("OnClick", function()
    if not editor.selectedProfileName then return end
    SwitchProfile(editor.selectedProfileName)
    EnsureDefaults()
    RebuildAllPanels()
    RefreshCurrentProfile(editor)
    Print("Loaded profile: " .. editor.selectedProfileName)
  end)
  editor.activateBtn = activateBtn

  local deactivateBtn = CreateFrame("Button", nil, profRight, "UIPanelButtonTemplate")
  deactivateBtn:SetSize(120, 22)
  deactivateBtn:SetPoint("LEFT", activateBtn, "RIGHT", 10, 0)
  deactivateBtn:SetText("Deactivate")
  deactivateBtn:SetScript("OnClick", function()
    SwitchProfile("Default")
    EnsureDefaults()
    RebuildAllPanels()
    RefreshCurrentProfile(editor)
    Print("No active profile.")
  end)
  editor.deactivateBtn = deactivateBtn

  MakeYellowSubHeader(profRight, "Automatic Profile Change", 0, -90)

  local specDesc = profRight:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  specDesc:SetPoint("TOPLEFT", 0, -114)
  specDesc:SetWidth(520)
  specDesc:SetJustifyH("LEFT")
  specDesc:SetText("If this option is activated, this profile will automatically activate when you change to the selected specialization. You can optionally limit this behavior to a specific character.")
  editor.specDesc = specDesc

  local specAutoCheck = CreateFrame("CheckButton", "LIDPANELS_SpecAutoCheck", profRight, "UICheckButtonTemplate")
  specAutoCheck:SetPoint("TOPLEFT", 0, -158)
  SetCheckButtonLabel(specAutoCheck, "Activate automatic profile change")
  editor.specAutoCheck = specAutoCheck

  local modeLabel = profRight:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  modeLabel:SetPoint("TOPLEFT", 0, -196)
  modeLabel:SetText("Change Mode")
  editor.profileModeLabel = modeLabel

  local modeDrop = CreateCustomDropdownControl(editor, profRight, {
    width = 250,
    text = "Change by Specialization",
  })
  modeDrop:SetPoint("TOPLEFT", -12, -210)
  editor.profileModeDrop = modeDrop

  local charLabel = profRight:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  charLabel:SetPoint("TOPLEFT", 0, -246)
  charLabel:SetText("Optional Character Filter")
  editor.charLabel = charLabel

  local charDrop = CreateCustomDropdownControl(editor, profRight, {
    width = 250,
    text = "Any character",
  })
  charDrop:SetPoint("TOPLEFT", -12, -260)
  editor.charDrop = charDrop

  local specLabel = profRight:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  specLabel:SetPoint("TOPLEFT", 0, -296)
  specLabel:SetText("Choose Specialization")
  editor.specLabel = specLabel

  local specDrop = CreateCustomDropdownControl(editor, profRight, {
    width = 250,
    text = "Unbound",
  })
  specDrop:SetPoint("TOPLEFT", -12, -310)
  editor.specDrop = specDrop

  modeDrop:SetMenuBuilder(function()
    local currentMode = "SPEC"
    if editor.selectedProfileName then
      local profile = RootDB().profiles[editor.selectedProfileName]
      local profileSpec = EnsureProfileAutoSwitchConfig(profile)
      currentMode = profileSpec and profileSpec.mode or "SPEC"
    end

    local function ApplyMode(mode, text)
      SetDropdownSelection(modeDrop, mode, text)
      if editor.selectedProfileName then
        local profile = RootDB().profiles[editor.selectedProfileName]
        local profileSpec = EnsureProfileAutoSwitchConfig(profile)
        profileSpec.mode = mode
        if mode == "CHARACTER" then
          if not profileSpec.character then
            profileSpec.character = GetCurrentCharacterKeyForProfiles()
          end
        elseif not profileSpec.specID then
          profileSpec.specID = GetCurrentSpecID()
        end
        RefreshProfileDetails(editor)
      end
    end

    return {
      entries = {
        {
          text = "Change by Specialization",
          value = "SPEC",
          checked = (currentMode == "SPEC"),
          func = function()
            ApplyMode("SPEC", "Change by Specialization")
          end,
        },
        {
          text = "Change by Character",
          value = "CHARACTER",
          checked = (currentMode == "CHARACTER"),
          func = function()
            ApplyMode("CHARACTER", "Change by Character")
          end,
        },
      },
      width = 250,
    }
  end)

  editor.profileDropdownPages = editor.profileDropdownPages or { spec = 1, character = 1 }

  specDrop:SetMenuBuilder(function()
    local entries = {}
    local currentSpecID = nil
    if editor.selectedProfileName then
      local profile = RootDB().profiles[editor.selectedProfileName]
      local profileSpec = EnsureProfileAutoSwitchConfig(profile)
      if profileSpec then
        currentSpecID = profileSpec.specID
      end
    end

    entries[#entries + 1] = {
      text = "Unbound",
      value = "NONE",
      checked = (currentSpecID == nil),
      func = function()
        SetDropdownSelection(specDrop, "NONE", "Unbound")
        if editor.selectedProfileName then
          local profile = RootDB().profiles[editor.selectedProfileName]
          local profileSpec = EnsureProfileAutoSwitchConfig(profile)
          profileSpec.specID = nil
          RefreshProfileDetails(editor)
        end
      end,
    }

    local pagedEntries, listWidth, onMouseWheel = BuildProfilePagedEntries(
      editor,
      "spec",
      BuildSpecOptions(),
      currentSpecID,
      function(option)
        SetDropdownSelection(specDrop, option.id, option.text)
        if editor.selectedProfileName then
          local profile = RootDB().profiles[editor.selectedProfileName]
          local profileSpec = EnsureProfileAutoSwitchConfig(profile)
          profileSpec.specID = option.id
          RefreshProfileDetails(editor)
        end
      end,
      {
        measurerKey = "__lidPanelsProfileSpecDropdownMeasurer",
        minWidth = PROFILE_DROPDOWN_WIDTH,
        extraLabels = { "Unbound" },
      }
    )

    for _, entry in ipairs(pagedEntries) do
      entries[#entries + 1] = entry
    end

    return {
      entries = entries,
      width = listWidth,
      onMouseWheel = onMouseWheel,
    }
  end)

  charDrop:SetMenuBuilder(function()
    local entries = {}
    local currentCharacter = nil
    local currentMode = "SPEC"
    if editor.selectedProfileName then
      local profile = RootDB().profiles[editor.selectedProfileName]
      local profileSpec = EnsureProfileAutoSwitchConfig(profile)
      if profileSpec then
        currentCharacter = profileSpec.character
        currentMode = profileSpec.mode or "SPEC"
      end
    end

    if currentMode == "SPEC" then
      entries[#entries + 1] = {
        text = "Any character",
        value = "ANY",
        checked = (currentCharacter == nil),
        func = function()
          SetDropdownSelection(charDrop, "ANY", "Any character")
          if editor.selectedProfileName then
            local profile = RootDB().profiles[editor.selectedProfileName]
            local profileSpec = EnsureProfileAutoSwitchConfig(profile)
            profileSpec.character = nil
            RefreshProfileDetails(editor)
          end
        end,
      }
    end

    local options = {}
    for _, name in ipairs(BuildCharacterOptions()) do
      options[#options + 1] = {
        text = name,
        value = name,
      }
    end

    local pagedEntries, listWidth, onMouseWheel = BuildProfilePagedEntries(
      editor,
      "character",
      options,
      currentCharacter,
      function(option)
        SetDropdownSelection(charDrop, option.value, option.text)
        if editor.selectedProfileName then
          local profile = RootDB().profiles[editor.selectedProfileName]
          local profileSpec = EnsureProfileAutoSwitchConfig(profile)
          profileSpec.character = option.value
          RefreshProfileDetails(editor)
        end
      end,
      {
        measurerKey = "__lidPanelsProfileCharacterDropdownMeasurer",
        minWidth = PROFILE_DROPDOWN_WIDTH,
        extraLabels = (currentMode == "SPEC") and { "Any character" } or nil,
      }
    )

    for _, entry in ipairs(pagedEntries) do
      entries[#entries + 1] = entry
    end

    return {
      entries = entries,
      width = listWidth,
      onMouseWheel = onMouseWheel,
    }
  end)

  specAutoCheck:SetScript("OnClick", function(self)
    if not editor.selectedProfileName then return end
    local profile = RootDB().profiles[editor.selectedProfileName]
    local profileSpec = EnsureProfileAutoSwitchConfig(profile)
    profileSpec.enabled = self:GetChecked() and true or false
    if profileSpec.enabled then
      if profileSpec.mode == "CHARACTER" then
        if not profileSpec.character then
          profileSpec.character = GetCurrentCharacterKeyForProfiles()
        end
      elseif not profileSpec.specID then
        profileSpec.specID = GetCurrentSpecID()
      end
    end
    RefreshProfileDetails(editor)
  end)

  MakeYellowSubHeader(profRight, "Modify Profile", 0, -370)

  local renameProfBtn = CreateFrame("Button", nil, profRight, "UIPanelButtonTemplate")
  renameProfBtn:SetSize(160, 22)
  renameProfBtn:SetPoint("TOPLEFT", 0, -394)
  renameProfBtn:SetText("Rename Profile")
  renameProfBtn:SetScript("OnClick", function()
    if not editor.selectedProfileName then return end
    StaticPopup_Show("LIDPANELS_RENAME_PROFILE")
  end)
  editor.renameProfBtn = renameProfBtn

  local copyProfBtn = CreateFrame("Button", nil, profRight, "UIPanelButtonTemplate")
  copyProfBtn:SetSize(160, 22)
  copyProfBtn:SetPoint("TOPLEFT", 0, -422)
  copyProfBtn:SetText("Copy Profile")
  copyProfBtn:SetScript("OnClick", function()
    if not editor.selectedProfileName then return end
    StaticPopup_Show("LIDPANELS_COPY_PROFILE")
  end)
  editor.copyProfBtn = copyProfBtn

  local delProfBtn = CreateFrame("Button", nil, profRight, "UIPanelButtonTemplate")
  delProfBtn:SetSize(160, 22)
  delProfBtn:SetPoint("TOPLEFT", 0, -450)
  delProfBtn:SetText("Delete Profile")
  delProfBtn:SetScript("OnClick", function()
    if not editor.selectedProfileName then return end
    StaticPopup_Show("LIDPANELS_DELETE_PROFILE", editor.selectedProfileName)
  end)
  editor.delProfBtn = delProfBtn

  MakeYellowSubHeader(profRight, "Import and Export", 0, -490)

  local exportBtn = CreateFrame("Button", nil, profRight, "UIPanelButtonTemplate")
  exportBtn:SetSize(100, 20)
  exportBtn:SetPoint("TOPLEFT", 0, -514)
  exportBtn:SetText("Export")
  exportBtn:SetScript("OnClick", function()
    local root = RootDB()
    local profileName = editor.selectedProfileName or root.currentProfile
    local exported = ExportProfile(profileName)
    if not exported then
      Print("Export failed.")
      return
    end
    ShowExportWindow(profileName, exported)
  end)
  editor.exportBtn = exportBtn

  local importBtn = CreateFrame("Button", nil, profRight, "UIPanelButtonTemplate")
  importBtn:SetSize(100, 20)
  importBtn:SetPoint("LEFT", exportBtn, "RIGHT", 8, 0)
  importBtn:SetText("Import")
  importBtn:SetScript("OnClick", function()
    ShowImportWindow(function(newName, pasted)
      local ok = ImportProfile(newName, pasted)
      if ok then
        if editor and editor.InvalidateSortedNameCaches then
          editor:InvalidateSortedNameCaches()
        end
        if editor and editor.Refresh then
          editor:Refresh()
        end
      end
    end)
  end)
  editor.importBtn = importBtn

  profRight:SetHeight(580)
end

INTERNAL_API.LIDPANELS_BuildProfilesPage_Impl = BuildProfilesPage
