-- LidCouncil_Editor_PopupDialogs.lua
-- Split from Editor.lua to isolate popup helpers and dialog registration.

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 function ResolveOptionalApiFunction(name)
  local api = rawget(_G, "LIDCOUNCIL_API")
  if type(api) == "table" and type(api[name]) == "function" then
    return api[name]
  end
  local fallback = rawget(_G, name)
  if type(fallback) == "function" then
    return fallback
  end
  return nil
end

local getDeps = INTERNAL_API.LIDCOUNCIL_GetEditorPopupDialogDeps_Impl
if type(getDeps) ~= "function" then
  error("LidCouncil missing editor popup dialog dependencies.")
end

local deps = getDeps()
local RootDB = deps.RootDB
local Print = deps.Print
local EnsureDefaults = deps.EnsureDefaults
local RebuildAllPanels = deps.RebuildAllPanels
local GetEditorProfileHelpers = deps.GetEditorProfileHelpers
local TrimName = deps.TrimName

local MAX_PANEL_NAME = deps.MAX_PANEL_NAME
local MAX_PROFILE_NAME = deps.MAX_PROFILE_NAME
local MAX_PROFILE_GROUP_NAME = deps.MAX_PROFILE_GROUP_NAME
local MAX_BACKGROUND_NAME = deps.MAX_BACKGROUND_NAME
local MAX_BG_CATEGORY_NAME = deps.MAX_BG_CATEGORY_NAME
local MAX_BG_CATEGORY_GROUP_NAME = deps.MAX_BG_CATEGORY_GROUP_NAME

local function GetEditor()
  return deps.GetEditor()
end

local function GetSelectedPanelName()
  return deps.GetSelectedPanelName()
end

local function GetSelectedBackgroundName()
  return deps.GetSelectedBackgroundName()
end

local function GetSelectedBackgroundCategory()
  return deps.GetSelectedBackgroundCategory()
end

local function GetSelectedBackgroundCategoryGroup()
  return deps.GetSelectedBackgroundCategoryGroup()
end

local function RenameSelectedPanel(...)
  return deps.RenameSelectedPanel(...)
end

local function CopySelectedPanelToProfile(...)
  return deps.CopySelectedPanelToProfile(...)
end

local function DeleteSelectedPanel(...)
  return deps.DeleteSelectedPanel(...)
end

local function CreateNewPanelNamed(...)
  return deps.CreateNewPanelNamed(...)
end

local function CreateBackgroundNamed(...)
  return deps.CreateBackgroundNamed(...)
end

local function RenameBackground(...)
  return deps.RenameBackground(...)
end

local function DeleteBackground(...)
  return deps.DeleteBackground(...)
end

local function ResolveNonSimulationFallbackProfile(root)
  root = type(root) == "table" and root or RootDB()
  root.ui = type(root.ui) == "table" and root.ui or {}

  local preferredName = tostring(root.ui.lastNonSimulationProfile or "")
  if preferredName ~= "" and preferredName ~= "Simulation" and type(root.profiles) == "table" and type(root.profiles[preferredName]) == "table" then
    return preferredName
  end
  if type(root.profiles) == "table" and type(root.profiles.Default) == "table" then
    return "Default"
  end

  local candidates = {}
  for profileName in pairs(root.profiles or {}) do
    local resolvedName = tostring(profileName or "")
    if resolvedName ~= "" and resolvedName ~= "Simulation" then
      candidates[#candidates + 1] = resolvedName
    end
  end
  table.sort(candidates, function(a, b)
    return string.lower(tostring(a or "")) < string.lower(tostring(b or ""))
  end)
  return candidates[1]
end

local function ClearSimulationDeveloperState(root)
  root = type(root) == "table" and root or RootDB()
  root.ui = type(root.ui) == "table" and root.ui or {}
  root.ui.showSimulationProfile = false
  root.ui.simulationRoleOverride = nil
  root.ui.simulationSessionHostOverride = nil
  root.ui.lastSimulationBoardHistoryProfile = nil
  root.ui.lastSimulationBoardId = nil
  root.ui.lastSimulationUpdatedAt = nil
end

local function MoveAwayFromSimulationProfile(root, currentEditor)
  root = type(root) == "table" and root or RootDB()
  local fallbackProfile = ResolveNonSimulationFallbackProfile(root) or "Default"
  if tostring(root.currentProfile or "") == "Simulation" and type(root.profiles) == "table" and type(root.profiles[fallbackProfile]) == "table" then
    root.currentProfile = fallbackProfile
  end
  local fallbackSelection = fallbackProfile ~= "Simulation" and fallbackProfile or nil
  if currentEditor then
    if currentEditor.selectedProfileName == "Simulation" then
      currentEditor.selectedProfileName = fallbackSelection
    end
    if currentEditor.selectedLootProfileName == "Simulation" then
      currentEditor.selectedLootProfileName = fallbackSelection
    end
  end
end

local function CreateBackgroundCategoryNamed(...)
  return deps.CreateBackgroundCategoryNamed(...)
end

local function DeleteBackgroundCategory(...)
  return deps.DeleteBackgroundCategory(...)
end

local function RenameBackgroundCategory(...)
  return deps.RenameBackgroundCategory(...)
end

local function CreateBackgroundCategoryGroupNamed(...)
  return deps.CreateBackgroundCategoryGroupNamed(...)
end

local function RenameBackgroundCategoryGroup(...)
  return deps.RenameBackgroundCategoryGroup(...)
end

local function DeleteBackgroundCategoryGroup(...)
  return deps.DeleteBackgroundCategoryGroup(...)
end

local function GetPopupEditBox(popup)
  if not popup then
    return nil
  end
  if popup.editBox and popup.editBox.GetText then
    return popup.editBox
  end
  if popup.EditBox and popup.EditBox.GetText then
    return popup.EditBox
  end
  if popup.GetName then
    local editBox = _G[popup:GetName() .. "EditBox"]
    if editBox and editBox.GetText then
      return editBox
    end
  end
  return nil
end

local function GetPopupText(popup)
  local editBox = GetPopupEditBox(popup)
  if editBox and editBox.GetText then
    return editBox:GetText() or ""
  end
  return ""
end

local function ConfirmPopupPrimary(popup)
  if not popup then
    return
  end
  if StaticPopup_OnClick then
    StaticPopup_OnClick(popup, 1)
    return
  end
  local button = popup.button1 or popup.Button1 or (popup.Buttons and popup.Buttons[1])
  if button and button.Click then
    button:Click()
    return
  end
  local info = popup.which and StaticPopupDialogs and StaticPopupDialogs[popup.which]
  if info and info.OnAccept then
    info.OnAccept(popup, popup.data, popup.data2)
  end
end

local function PopupEditBoxConfirm(editBox)
  local popup = editBox and editBox.GetParent and editBox:GetParent()
  if popup then
    ConfirmPopupPrimary(popup)
  end
end

local function HookPopupEnterAccept(popup)
  if not popup then
    return
  end
  local editBox = GetPopupEditBox(popup)
  if editBox and editBox.SetScript then
    editBox:SetScript("OnEnterPressed", function()
      PopupEditBoxConfirm(editBox)
    end)
  end
  if not popup.__lidEnterHooked then
    popup.__lidEnterHooked = true
    popup:EnableKeyboard(true)
    popup:HookScript("OnKeyDown", function(frame, key)
      if key == "ENTER" or key == "NUMPADENTER" then
        ConfirmPopupPrimary(frame)
      end
    end)
  end
end

local function HookPopupMaxLetters(popup, maxChars)
  local editBox = GetPopupEditBox(popup)
  if not editBox or not maxChars then
    return
  end
  editBox:SetMaxLetters(maxChars)
  editBox:SetScript("OnTextChanged", function(self)
    local text = self:GetText() or ""
    if #text > maxChars then
      self:SetText(text:sub(1, maxChars))
      self:SetCursorPosition(maxChars)
    end
  end)
end

local copyPanelTargetProfilesRoot
local copyPanelTargetProfilesCurrent
local copyPanelTargetProfilesBaseNames
local copyPanelTargetProfilesCache

local function GetCopyPanelTargetProfiles()
  local root = RootDB()
  local currentProfile = tostring(root.currentProfile or "")
  local baseNames = GetEditorProfileHelpers().ListProfiles()
  if copyPanelTargetProfilesRoot == root
    and copyPanelTargetProfilesCurrent == currentProfile
    and copyPanelTargetProfilesBaseNames == baseNames
    and copyPanelTargetProfilesCache
  then
    return copyPanelTargetProfilesCache
  end

  local names = {}
  if currentProfile ~= "" and currentProfile ~= "Default" then
    for _, name in ipairs(baseNames) do
      if name == currentProfile then
        names[#names + 1] = name
        break
      end
    end
  end

  for _, name in ipairs(baseNames) do
    if name ~= currentProfile then
      names[#names + 1] = name
    end
  end

  if #names == 0 and currentProfile ~= "" then
    names[1] = currentProfile
  end

  copyPanelTargetProfilesRoot = root
  copyPanelTargetProfilesCurrent = currentProfile
  copyPanelTargetProfilesBaseNames = baseNames
  copyPanelTargetProfilesCache = names
  return names
end

local COPY_PANEL_PROFILE_PAGE_SIZE = 12

local function ClampCopyPanelProfilePage(page, totalPages)
  totalPages = math.max(1, tonumber(totalPages) or 1)
  page = tonumber(page) or 1
  if page < 1 then
    page = 1
  end
  if page > totalPages then
    page = totalPages
  end
  return page
end

local function GetCopyPanelProfileSelectedPage(profiles, selectedProfile)
  for index, profileName in ipairs(profiles or {}) do
    if profileName == selectedProfile then
      return math.floor((index - 1) / COPY_PANEL_PROFILE_PAGE_SIZE) + 1
    end
  end
  return 1
end

local function BuildCopyPanelProfilePagedMenu(popup, dropdown)
  local profiles = popup and popup.__lidCopyPanelProfiles or {}
  local selectedProfile = popup and popup.__lidCopyProfileSelected or nil
  local totalPages = math.max(1, math.ceil(#profiles / COPY_PANEL_PROFILE_PAGE_SIZE))
  local page = ClampCopyPanelProfilePage(popup and popup.__lidCopyProfilePage or 1, totalPages)
  local firstIndex = ((page - 1) * COPY_PANEL_PROFILE_PAGE_SIZE) + 1
  local lastIndex = math.min(#profiles, firstIndex + COPY_PANEL_PROFILE_PAGE_SIZE - 1)
  local entries = {}

  for index = firstIndex, lastIndex do
    local profileName = profiles[index]
    if profileName then
      entries[#entries + 1] = {
        text = profileName,
        value = profileName,
        checked = (profileName == selectedProfile),
        func = function()
          popup.__lidCopyProfileSelected = profileName
          popup.__lidCopyProfilePage = GetCopyPanelProfileSelectedPage(profiles, profileName)
          if dropdown.__lidcouncilCustomDropdown then
            dropdown:SetSelectedValue(profileName)
            dropdown:SetText(profileName)
          else
            UIDropDownMenu_SetSelectedValue(dropdown, profileName)
            UIDropDownMenu_SetText(dropdown, profileName)
          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()
        popup.__lidCopyProfilePage = ClampCopyPanelProfilePage(page - 1, totalPages)
      end,
    }
    entries[#entries + 1] = {
      text = "Next >",
      notCheckable = true,
      disabled = (page >= totalPages),
      keepShownOnClick = true,
      func = function()
        popup.__lidCopyProfilePage = ClampCopyPanelProfilePage(page + 1, totalPages)
      end,
    }
  end

  local function OnMouseWheel(delta)
    if totalPages <= 1 then
      return false
    end
    local targetPage = ClampCopyPanelProfilePage(page - delta, totalPages)
    if targetPage == page then
      return false
    end
    popup.__lidCopyProfilePage = targetPage
    return true
  end

  return {
    entries = entries,
    width = 180,
    onMouseWheel = OnMouseWheel,
  }
end

local function EnsureCopyPanelProfileControls(popup)
  if not popup then
    return nil, nil
  end

  if not popup.__lidCopyProfileLabel then
    local label = popup:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    label:SetText("Target Profile:")
    popup.__lidCopyProfileLabel = label
  end

  if not popup.__lidCopyProfileDrop then
    local createCustomDropdown = rawget(_G, "LIDCOUNCIL_CreateCustomDropdownControl")
    local dropdown
    if type(createCustomDropdown) == "function" then
      dropdown = createCustomDropdown(GetEditor(), popup, {
        width = 180,
        buttonHeight = 24,
        text = "(select profile)",
      })
    else
      dropdown = CreateFrame("Frame", nil, popup, "UIDropDownMenuTemplate")
      UIDropDownMenu_SetWidth(dropdown, 180)
    end
    popup.__lidCopyProfileDrop = dropdown
  end

  return popup.__lidCopyProfileLabel, popup.__lidCopyProfileDrop
end

local function HideCopyPanelProfileControls(popup)
  if not popup then
    return
  end
  popup.__lidCopyPanelLayoutUntil = nil
  if popup.__lidCopyProfileLabel then
    popup.__lidCopyProfileLabel:Hide()
  end
  if popup.__lidCopyProfileDrop then
    if popup.__lidCopyProfileDrop.__lidcouncilCustomDropdown and popup.__lidCopyProfileDrop.CloseMenu then
      popup.__lidCopyProfileDrop:CloseMenu()
    end
    popup.__lidCopyProfileDrop:Hide()
  end
end

local function LayoutCopyPanelPopup(popup)
  if not popup or not popup:IsShown() then
    return
  end

  local editBox = GetPopupEditBox(popup)
  local label = popup.__lidCopyProfileLabel
  local dropdown = popup.__lidCopyProfileDrop
  local popupName = popup.GetName and popup:GetName() or nil
  local button1 = popup.button1 or (popupName and _G[popupName .. "Button1"]) or nil
  local button2 = popup.button2 or (popupName and _G[popupName .. "Button2"]) or nil
  if not label or not dropdown then
    return
  end

  label:ClearAllPoints()
  if editBox then
    label:SetPoint("TOP", editBox, "BOTTOM", 0, -12)
  else
    label:SetPoint("TOP", popup.text, "BOTTOM", 0, -44)
  end
  label:Show()

  dropdown:ClearAllPoints()
  if dropdown.__lidcouncilCustomDropdown then
    dropdown:SetPoint("TOP", label, "BOTTOM", 0, -6)
  else
    dropdown:SetPoint("TOP", label, "BOTTOM", 0, -2)
  end
  dropdown:Show()

  local buttonHeight = math.max(
    (button1 and button1.GetHeight and button1:GetHeight()) or 22,
    (button2 and button2.GetHeight and button2:GetHeight()) or 22
  )
  local buttonGapY = 32
  local bottomPadding = 14
  local extraPadding = 4
  local desiredHeight = 188
  local popupTop = popup.GetTop and popup:GetTop() or nil
  local dropdownBottom = dropdown.GetBottom and dropdown:GetBottom() or nil
  if popupTop and dropdownBottom then
    desiredHeight = math.ceil((popupTop - dropdownBottom) + buttonGapY + buttonHeight + bottomPadding + extraPadding)
    if desiredHeight < 188 then
      desiredHeight = 188
    end
  end

  if button1 and button2 then
    button1:ClearAllPoints()
    button1:SetPoint("TOPRIGHT", dropdown, "BOTTOM", -8, -buttonGapY)
    button2:ClearAllPoints()
    button2:SetPoint("TOPLEFT", dropdown, "BOTTOM", 8, -buttonGapY)
  end
  popup:SetHeight(desiredHeight)
end

local function EnsureCopyPanelPopupLayoutHook(popup)
  if not popup or popup.__lidCopyPanelLayoutHooked or type(popup.HookScript) ~= "function" then
    return
  end
  popup.__lidCopyPanelLayoutHooked = true
  popup:HookScript("OnUpdate", function(self)
    local untilTime = self.__lidCopyPanelLayoutUntil
    if not untilTime then
      return
    end
    local now = (GetTime and GetTime()) or 0
    if now > untilTime then
      self.__lidCopyPanelLayoutUntil = nil
      return
    end
    LayoutCopyPanelPopup(self)
  end)
end

local function RequestCopyPanelPopupLayout(popup, duration)
  if not popup then
    return
  end
  EnsureCopyPanelPopupLayoutHook(popup)
  local now = (GetTime and GetTime()) or 0
  popup.__lidCopyPanelLayoutUntil = now + (tonumber(duration) or 0.4)
  LayoutCopyPanelPopup(popup)
end

StaticPopupDialogs["LIDCOUNCIL_RENAME_PANEL"] = {
  text = "Rename panel:",
  button1 = "Confirm",
  button2 = "Cancel",
  maxLetters = MAX_PANEL_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      HookPopupMaxLetters(self, MAX_PANEL_NAME)
      editBox:SetText(GetSelectedPanelName() or "")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
    end
  end,
  OnAccept = function(self)
    if not GetSelectedPanelName() then
      return
    end
    RenameSelectedPanel(GetPopupText(self))
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_RESET_MINIMAP"] = {
  text = "Are you sure you want to reset the Minimap Icon?",
  button1 = "Yes",
  button2 = "Cancel",
  OnAccept = function()
    local root = RootDB()
    root.ui = root.ui or {}
    root.ui.minimap = root.ui.minimap or {}

    local defaultSize = 28
    if root.ui.editorScalePreset == "4K" then
      defaultSize = 37
    end
    root.ui.minimap.size = defaultSize
    root.ui.minimap.angle = 45
    root.ui.minimap.alpha = 1
    root.ui.minimap.onlyOnHover = false

    local currentEditor = GetEditor()
    if currentEditor and currentEditor.minimapSizeSlider then
      currentEditor.minimapSizeSlider:SetValueSilent(defaultSize)
    end
    if currentEditor and currentEditor.minimapAlphaSlider then
      currentEditor.minimapAlphaSlider:SetValueSilent(100)
    end
    if currentEditor and currentEditor.minimapHoverCheck then
      currentEditor.minimapHoverCheck:SetChecked(false)
    end
    local updateFn = _G.LIDCOUNCIL_UpdateMinimapButton
    if updateFn then
      updateFn()
    end
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_COPY_PANEL"] = {
  text = "Copy panel to new name:",
  button1 = "Confirm",
  button2 = "Cancel",
  maxLetters = MAX_PANEL_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      HookPopupMaxLetters(self, MAX_PANEL_NAME)
      editBox:SetText("")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
    end
    local label, dropdown = EnsureCopyPanelProfileControls(self)
    if label and dropdown then
      local profiles = GetCopyPanelTargetProfiles()
      local root = RootDB()
      local defaultProfile = root.currentProfile
      if defaultProfile == nil or defaultProfile == "" then
        defaultProfile = profiles[1]
      end
      if defaultProfile == "Default" and profiles[1] then
        defaultProfile = profiles[1]
      end
      self.__lidCopyPanelProfiles = profiles
      self.__lidCopyProfileSelected = defaultProfile
      self.__lidCopyProfilePage = GetCopyPanelProfileSelectedPage(profiles, defaultProfile)

      if dropdown.__lidcouncilCustomDropdown then
        dropdown:SetMenuBuilder(function()
          return BuildCopyPanelProfilePagedMenu(self, dropdown)
        end)
        dropdown:SetSelectedValue(self.__lidCopyProfileSelected)
        dropdown:SetText(self.__lidCopyProfileSelected or "(select profile)")
      else
        UIDropDownMenu_Initialize(dropdown, function(_, level)
          if level ~= 1 then
            return
          end
          local menu = BuildCopyPanelProfilePagedMenu(self, dropdown)
          for _, entry in ipairs(menu.entries or {}) do
            local info = UIDropDownMenu_CreateInfo()
            info.text = entry.text
            info.value = entry.value
            info.checked = entry.checked
            info.isTitle = entry.isTitle
            info.notCheckable = entry.notCheckable
            info.disabled = entry.disabled
            info.keepShownOnClick = entry.keepShownOnClick
            info.func = function()
              if type(entry.func) == "function" then
                entry.func()
                UIDropDownMenu_Refresh(dropdown)
              end
            end
            UIDropDownMenu_AddButton(info, level)
          end
        end)
        UIDropDownMenu_SetSelectedValue(dropdown, self.__lidCopyProfileSelected)
        UIDropDownMenu_SetText(dropdown, self.__lidCopyProfileSelected or "(select profile)")
      end
      RequestCopyPanelPopupLayout(self, 0.5)
    end
  end,
  OnAccept = function(self)
    if not GetSelectedPanelName() then
      return
    end
    CopySelectedPanelToProfile(GetPopupText(self), self.__lidCopyProfileSelected)
  end,
  OnHide = function(self)
    HideCopyPanelProfileControls(self)
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_CREATE_PANEL"] = {
  text = "Enter Name for your new Panel:",
  button1 = "Create",
  button2 = "Cancel",
  maxLetters = MAX_PANEL_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      HookPopupMaxLetters(self, MAX_PANEL_NAME)
      editBox:SetText("")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
    end
  end,
  OnAccept = function(self)
    CreateNewPanelNamed(GetPopupText(self))
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_NEED_PROFILE"] = {
  text = "No active profile. :(\nPlease activate a Profile first:\n\n1. go to Profiles\n2. select a Profile\n3. click \"Activate\"\n4. The profile should be highlight purple now",
  button1 = "OK Boss!",
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_CREATE_BG"] = {
  text = "Enter the name of your file\n(without .tga)",
  button1 = "Create",
  button2 = "Cancel",
  maxLetters = MAX_BACKGROUND_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      editBox:SetText("")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
      HookPopupMaxLetters(self, MAX_BACKGROUND_NAME)
    end
  end,
  OnAccept = function(self)
    CreateBackgroundNamed(GetPopupText(self))
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_CREATE_BG_CATEGORY"] = {
  text = "Enter the name of your new category, for example \"Character Images\"",
  button1 = "Create",
  button2 = "Cancel",
  maxLetters = MAX_BG_CATEGORY_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      editBox:SetText("")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
      HookPopupMaxLetters(self, MAX_BG_CATEGORY_NAME)
    end
  end,
  OnAccept = function(self)
    CreateBackgroundCategoryNamed(GetPopupText(self))
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_RENAME_BG_CATEGORY"] = {
  text = "Rename category:",
  button1 = "Confirm",
  button2 = "Cancel",
  maxLetters = MAX_BG_CATEGORY_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      editBox:SetText(GetSelectedBackgroundCategory() or "")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
      HookPopupMaxLetters(self, MAX_BG_CATEGORY_NAME)
    end
  end,
  OnAccept = function(self)
    local selectedCategory = GetSelectedBackgroundCategory()
    if not selectedCategory then
      return
    end
    RenameBackgroundCategory(selectedCategory, GetPopupText(self))
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_DELETE_BG_CATEGORY"] = {
  text = "Are you sure you want to delete \"%s\"?",
  button1 = "Delete",
  button2 = "Cancel",
  OnShow = function(self)
    HookPopupEnterAccept(self)
  end,
  OnAccept = function()
    local selectedCategory = GetSelectedBackgroundCategory()
    if selectedCategory then
      DeleteBackgroundCategory(selectedCategory)
    end
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_CREATE_BG_CATEGORY_GROUP"] = {
  text = "Create new category group:",
  button1 = "Create",
  button2 = "Cancel",
  maxLetters = MAX_BG_CATEGORY_GROUP_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      editBox:SetText("")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
      HookPopupMaxLetters(self, MAX_BG_CATEGORY_GROUP_NAME)
    end
  end,
  OnAccept = function(self)
    CreateBackgroundCategoryGroupNamed(GetPopupText(self))
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_RENAME_BG_CATEGORY_GROUP"] = {
  text = "Rename category group:",
  button1 = "Confirm",
  button2 = "Cancel",
  maxLetters = MAX_BG_CATEGORY_GROUP_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      editBox:SetText(GetSelectedBackgroundCategoryGroup() or "")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
      HookPopupMaxLetters(self, MAX_BG_CATEGORY_GROUP_NAME)
    end
  end,
  OnAccept = function(self)
    local selectedGroup = GetSelectedBackgroundCategoryGroup()
    if not selectedGroup then
      return
    end
    RenameBackgroundCategoryGroup(selectedGroup, GetPopupText(self))
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_DELETE_BG_CATEGORY_GROUP"] = {
  text = "Delete the category group \"%s\"?\nCategories inside the group will remain and become groupless.",
  button1 = "Delete",
  button2 = "Cancel",
  OnShow = function(self)
    HookPopupEnterAccept(self)
  end,
  OnAccept = function()
    local selectedGroup = GetSelectedBackgroundCategoryGroup()
    if selectedGroup then
      DeleteBackgroundCategoryGroup(selectedGroup)
    end
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_NEED_BG_CATEGORY"] = {
  text = "Select or create a category first.",
  button1 = "OK",
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_RENAME_BG"] = {
  text = "Rename background (without .tga):",
  button1 = "Confirm",
  button2 = "Cancel",
  maxLetters = MAX_BACKGROUND_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      HookPopupMaxLetters(self, MAX_BACKGROUND_NAME)
      editBox:SetText(GetSelectedBackgroundName() or "")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
    end
  end,
  OnAccept = function(self)
    local selectedBackground = GetSelectedBackgroundName()
    if selectedBackground then
      RenameBackground(selectedBackground, GetPopupText(self))
    end
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_DELETE_BG"] = {
  text = "Are you sure you want to delete the background \"%s\"?",
  button1 = "Delete",
  button2 = "Cancel",
  OnShow = function(self)
    HookPopupEnterAccept(self)
  end,
  OnAccept = function()
    local selectedBackground = GetSelectedBackgroundName()
    if not selectedBackground then
      return
    end
    DeleteBackground(selectedBackground)
    local currentEditor = GetEditor()
    if currentEditor and currentEditor.RefreshBackgroundListDetailsSection then
      currentEditor:RefreshBackgroundListDetailsSection()
    elseif currentEditor and currentEditor.RefreshBackgroundsSection then
      currentEditor:RefreshBackgroundsSection()
    elseif currentEditor and currentEditor.Refresh then
      currentEditor:Refresh()
    end
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_DELETE_PANEL"] = {
  text = "Are you sure you want to delete the panel \"%s\"?",
  button1 = "Delete",
  button2 = "Cancel",
  OnShow = function(self)
    HookPopupEnterAccept(self)
  end,
  OnAccept = function()
    DeleteSelectedPanel()
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_RENAME_PROFILE"] = {
  text = "Rename profile:",
  button1 = "Confirm",
  button2 = "Cancel",
  maxLetters = MAX_PROFILE_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local currentEditor = GetEditor()
    local editBox = GetPopupEditBox(self)
    if editBox then
      HookPopupMaxLetters(self, MAX_PROFILE_NAME)
      editBox:SetText(currentEditor and currentEditor.selectedProfileName or "")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
    end
  end,
  OnAccept = function(self)
    local currentEditor = GetEditor()
    if not currentEditor or not currentEditor.selectedProfileName then
      return
    end
    local text = TrimName(GetPopupText(self))
    if text == "" then
      Print("Please enter a profile name.")
      return
    end
    local ok, resolvedName = GetEditorProfileHelpers().RenameProfile(currentEditor.selectedProfileName, text)
    if not ok then
      return
    end
    local nextName = tostring(resolvedName or text)
    currentEditor.selectedProfileName = nextName
    currentEditor.selectedLootProfileName = nextName
    currentEditor.selectedProfileGroupName = nil
    currentEditor.selectedLootProfileGroupName = nil
    if currentEditor.RefreshLootProfilePage then
      currentEditor:RefreshLootProfilePage()
    elseif currentEditor.RefreshProfilesSection then
      currentEditor:RefreshProfilesSection()
    elseif currentEditor.Refresh then
      currentEditor:Refresh()
    end
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_CREATE_PROFILE"] = {
  text = "Create new profile:",
  button1 = "Create",
  button2 = "Cancel",
  maxLetters = MAX_PROFILE_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      HookPopupMaxLetters(self, MAX_PROFILE_NAME)
      editBox:SetText("")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
    end
  end,
  OnAccept = function(self)
    local text = TrimName(GetPopupText(self))
    if text == "" then
      Print("Please enter a profile name.")
      return
    end
    GetEditorProfileHelpers().CreateProfileNamed(text)
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_CREATE_PROFILE_GROUP"] = {
  text = "Create new profile group:",
  button1 = "Create",
  button2 = "Cancel",
  maxLetters = MAX_PROFILE_GROUP_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      HookPopupMaxLetters(self, MAX_PROFILE_GROUP_NAME)
      editBox:SetText("")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
    end
  end,
  OnAccept = function(self)
    local text = TrimName(GetPopupText(self))
    if text == "" then
      Print("Please enter a group name.")
      return
    end
    GetEditorProfileHelpers().CreateProfileGroupNamed(text)
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_RENAME_PROFILE_GROUP"] = {
  text = "Rename profile group:",
  button1 = "Confirm",
  button2 = "Cancel",
  maxLetters = MAX_PROFILE_GROUP_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local currentEditor = GetEditor()
    local editBox = GetPopupEditBox(self)
    if editBox then
      HookPopupMaxLetters(self, MAX_PROFILE_GROUP_NAME)
      editBox:SetText(currentEditor and currentEditor.selectedProfileGroupName or "")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
    end
  end,
  OnAccept = function(self)
    local currentEditor = GetEditor()
    if not currentEditor or not currentEditor.selectedProfileGroupName then
      return
    end
    local text = TrimName(GetPopupText(self))
    if text == "" then
      Print("Please enter a group name.")
      return
    end
    GetEditorProfileHelpers().RenameProfileGroup(currentEditor.selectedProfileGroupName, text)
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_DELETE_PROFILE_GROUP"] = {
  text = "Delete the profile group \"%s\"?\nProfiles inside the group will remain and become groupless.",
  button1 = "Delete",
  button2 = "Cancel",
  OnShow = function(self)
    HookPopupEnterAccept(self)
  end,
  OnAccept = function()
    local currentEditor = GetEditor()
    local groupName = currentEditor and (currentEditor.selectedLootProfileGroupName or currentEditor.selectedProfileGroupName) or nil
    if currentEditor and groupName then
      GetEditorProfileHelpers().DeleteProfileGroup(groupName)
      currentEditor.selectedProfileGroupName = nil
      currentEditor.selectedLootProfileGroupName = nil
      if currentEditor.RefreshLootProfilePage then
        currentEditor:RefreshLootProfilePage()
      elseif currentEditor.RefreshProfilesSection then
        currentEditor:RefreshProfilesSection()
      elseif currentEditor.Refresh then
        currentEditor:Refresh()
      end
    end
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_COPY_PROFILE"] = {
  text = "Copy profile to new name:",
  button1 = "Confirm",
  button2 = "Cancel",
  maxLetters = MAX_PROFILE_NAME,
  hasEditBox = true,
  OnShow = function(self)
    local editBox = GetPopupEditBox(self)
    if editBox then
      HookPopupMaxLetters(self, MAX_PROFILE_NAME)
      editBox:SetText("")
      editBox:HighlightText()
      editBox:SetFocus()
      HookPopupEnterAccept(self)
    end
  end,
  OnAccept = function(self)
    local currentEditor = GetEditor()
    if not currentEditor or not currentEditor.selectedProfileName then
      return
    end
    local text = TrimName(GetPopupText(self))
    if text == "" then
      Print("Please enter a profile name.")
      return
    end
    local copiedName = GetEditorProfileHelpers().CopyProfileFrom(currentEditor.selectedProfileName, text)
    if copiedName then
      currentEditor.selectedProfileName = copiedName
      currentEditor.selectedLootProfileName = copiedName
      currentEditor.selectedProfileGroupName = nil
      currentEditor.selectedLootProfileGroupName = nil
      if currentEditor.RefreshLootProfilePage then
        currentEditor:RefreshLootProfilePage()
      elseif currentEditor.RefreshProfilesSection then
        currentEditor:RefreshProfilesSection()
      elseif currentEditor.Refresh then
        currentEditor:Refresh()
      end
    end
  end,
  EditBoxOnEnterPressed = PopupEditBoxConfirm,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_DELETE_PROFILE"] = {
  text = "Are you sure you want to delete the Profile \"%s\"?",
  button1 = "Delete",
  button2 = "Cancel",
  OnShow = function(self)
    HookPopupEnterAccept(self)
    local currentEditor = GetEditor()
    local profileName = currentEditor and currentEditor.selectedProfileName or ""
    local getLootProfileIdentityInfo = ResolveOptionalApiFunction("LIDCOUNCIL_GetLootProfileIdentityInfo")
    local identity = type(getLootProfileIdentityInfo) == "function" and getLootProfileIdentityInfo(profileName) or nil
    local isSharedReplica = type(identity) == "table" and tostring(identity.syncMode or ""):upper() == "SHARED"
    if self.button1 and self.button1.SetText then
      self.button1:SetText("Delete Profile")
    end
    if self.text and self.text.SetText then
      if isSharedReplica then
        self.text:SetText(string.format(
          "Only the local copy will be deleted. It is not possible to delete a profile for everyone.\n\nShared profile copies can be received again later from a session host.\n\nAre you sure you want to delete the Profile \"%s\"?",
          tostring(profileName or "")
        ))
      else
        self.text:SetText(string.format(
          "Only the local copy will be deleted. It is not possible to delete a profile for everyone.\n\nAre you sure you want to delete the Profile \"%s\"?",
          tostring(profileName or "")
        ))
      end
    end
  end,
  OnAccept = function()
    local currentEditor = GetEditor()
    if not currentEditor or not currentEditor.selectedProfileName then
      return
    end
    local ok = GetEditorProfileHelpers().DeleteProfile(currentEditor.selectedProfileName)
    if not ok then
      return
    end
    currentEditor.selectedProfileName = nil
    currentEditor.selectedLootProfileName = nil
    EnsureDefaults()
    RebuildAllPanels()
    local refreshed = false
    if currentEditor.RefreshLootProfilePage then
      currentEditor:RefreshLootProfilePage()
      refreshed = true
    end
    if currentEditor.RefreshProfilesSection then
      currentEditor:RefreshProfilesSection()
      refreshed = true
    end
    if not refreshed and currentEditor.Refresh then
      currentEditor:Refresh()
    end
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_CLEAR_SIMULATION_PROFILE_CONTENT"] = {
  text = "Clear all Simulation content?\n\nThis removes session history, loot list data, member assignments, live board history, and the selected raid from the Simulation profile while keeping roll settings, point settings, and the rights policy.",
  button1 = "Clear Content",
  button2 = "Cancel",
  OnShow = function(self)
    HookPopupEnterAccept(self)
  end,
  OnAccept = function()
    local currentEditor = GetEditor()
    local profileName = currentEditor and currentEditor.selectedProfileName or "Simulation"
    local resetSimulationProfileContent = ResolveOptionalApiFunction("LIDCOUNCIL_ResetSimulationProfileContent")
    if type(resetSimulationProfileContent) ~= "function" then
      Print("Simulation reset API unavailable.")
      return
    end
    local ok, result = resetSimulationProfileContent(profileName)
    if not ok then
      Print(tostring(result or "Could not clear the Simulation content."))
      return
    end
    local refreshLiveLootBoard = ResolveOptionalApiFunction("LIDCOUNCIL_RefreshLiveLootBoard")
    if type(refreshLiveLootBoard) == "function" then
      refreshLiveLootBoard()
    end
    if currentEditor and currentEditor.lootProfilesFeedback then
      currentEditor.lootProfilesFeedback:SetText(tostring(result or "Simulation content cleared."))
      if currentEditor.lootProfilesFeedback.SetTextColor then
        currentEditor.lootProfilesFeedback:SetTextColor(0.30, 0.90, 0.36, 1.00)
      end
    else
      Print(tostring(result or "Simulation content cleared."))
    end
    if currentEditor then
      if currentEditor.RefreshLootProfilePage then
        currentEditor:RefreshLootProfilePage()
      elseif currentEditor.Refresh then
        currentEditor:Refresh()
      end
    end
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_SIMULATION_PROFILE_CREATED"] = {
  text = "Simulation Profile created - go to Profile to start using it for Simulations.",
  button1 = "Thanks!",
  OnShow = function(self)
    HookPopupEnterAccept(self)
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_DELETE_SIMULATION_PROFILE"] = {
  text = "Delete the local Simulation profile?\n\nThis removes only the local testing profile on this client.",
  button1 = "Delete",
  button2 = "Cancel",
  OnShow = function(self)
    HookPopupEnterAccept(self)
  end,
  OnAccept = function()
    local root = RootDB()
    local currentEditor = GetEditor()
    local ok, result = GetEditorProfileHelpers().DeleteProfile("Simulation")
    if not ok then
      return
    end

    ClearSimulationDeveloperState(root)
    MoveAwayFromSimulationProfile(root, currentEditor)
    EnsureDefaults()
    RebuildAllPanels()

    if currentEditor then
      if currentEditor.RefreshDeveloperSection then
        currentEditor:RefreshDeveloperSection()
      end
      if currentEditor.RefreshAbout then
        currentEditor:RefreshAbout()
      end
      if currentEditor.Refresh then
        currentEditor:Refresh()
      end
    end
    Print("Simulation profile deleted.")
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
}

StaticPopupDialogs["LIDCOUNCIL_ACTIVE_SESSION_PROFILE_LOCK"] = {
  text = "A session is still running. Please stop the session before activating another profile.",
  button1 = "OK",
  OnShow = function(self)
    HookPopupEnterAccept(self)
  end,
  timeout = 0,
  whileDead = true,
  hideOnEscape = true,
  preferredIndex = 3,
}
