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 SetDropdownSelection = INTERNAL_API.LIDPANELS_SetDropdownSelection_Impl
local GetDropdownMenuWidth = INTERNAL_API.LIDPANELS_GetDropdownMenuWidth_Impl
local CreatePanelAssetPickers = INTERNAL_API.LIDPANELS_CreatePanelAssetPickers_Impl
if type(RequireApi) ~= "function"
  or type(SetDropdownSelection) ~= "function"
  or type(GetDropdownMenuWidth) ~= "function"
  or type(CreatePanelAssetPickers) ~= "function" then
  error("LidPanels missing background section helpers.")
end

local DB = RequireApi("LIDPANELS_DB", _G.LIDPANELS_DB)
local BuildBackgroundList = RequireApi("LIDPANELS_BuildBackgroundList", _G.LIDPANELS_BuildBackgroundList)
local RebuildAllPanels = RequireApi("LIDPANELS_RebuildAllPanels", _G.LIDPANELS_RebuildAllPanels)
local EnsureGradientTables = RequireApi("LIDPANELS_EnsureGradientTables", _G.LIDPANELS_EnsureGradientTables)
local GetSelectedPanelName = RequireApi("LIDPANELS_GetSelectedPanelName", _G.LIDPANELS_GetSelectedPanelName)
local CreateCustomDropdownControl = RequireApi("LIDPANELS_CreateCustomDropdownControl", _G.LIDPANELS_CreateCustomDropdownControl)

local function RefreshPanelProperties(editor)
  if editor and editor.RefreshPanelPropertiesSection then
    editor:RefreshPanelPropertiesSection()
  elseif editor and editor.RefreshPanelsSection then
    editor:RefreshPanelsSection()
  elseif editor and editor.Refresh then
    editor:Refresh()
  end
end

local function CreatePanelBackgroundSection(editor, props)
  if not editor or not props then
    return {}
  end

  local colorDesc = props:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  colorDesc:SetPoint("TOPLEFT", 0, -466)
  colorDesc:SetText("Choose a background style for your panel:")
  editor.colorDesc = colorDesc

  local modeSingleCheck = CreateFrame("CheckButton", "LIDPANELS_ModeSingleCheck", props, "UICheckButtonTemplate")
  modeSingleCheck:SetPoint("TOPLEFT", 0, -488)
  _G[modeSingleCheck:GetName() .. "Text"]:SetText("Unicolor")
  editor.modeSingleCheck = modeSingleCheck

  local modeDualCheck = CreateFrame("CheckButton", "LIDPANELS_ModeDualCheck", props, "UICheckButtonTemplate")
  modeDualCheck:SetPoint("TOPLEFT", 120, -488)
  _G[modeDualCheck:GetName() .. "Text"]:SetText("Gradient")
  editor.modeDualCheck = modeDualCheck

  local modeBgCheck = CreateFrame("CheckButton", "LIDPANELS_ModeBgCheck", props, "UICheckButtonTemplate")
  modeBgCheck:SetPoint("TOPLEFT", 240, -488)
  _G[modeBgCheck:GetName() .. "Text"]:SetText("Background")
  editor.modeBgCheck = modeBgCheck

  local modeTextureCheck = CreateFrame("CheckButton", "LIDPANELS_ModeTextureCheck", props, "UICheckButtonTemplate")
  modeTextureCheck:SetPoint("TOPLEFT", 0, -510)
  _G[modeTextureCheck:GetName() .. "Text"]:SetText("Textures")
  editor.modeTextureCheck = modeTextureCheck

  local modeIconCheck = CreateFrame("CheckButton", "LIDPANELS_ModeIconCheck", props, "UICheckButtonTemplate")
  modeIconCheck:SetPoint("TOPLEFT", 120, -510)
  _G[modeIconCheck:GetName() .. "Text"]:SetText("Icon")
  editor.modeIconCheck = modeIconCheck

  local modeModelCheck = CreateFrame("CheckButton", "LIDPANELS_ModeModelCheck", props, "UICheckButtonTemplate")
  modeModelCheck:SetPoint("TOPLEFT", 240, -510)
  _G[modeModelCheck:GetName() .. "Text"]:SetText("Model")
  editor.modeModelCheck = modeModelCheck

  local function GetColorMode(panel)
    local explicit = panel and panel.designMode
    if explicit == "SINGLE" or explicit == "DUAL" or explicit == "BG" or explicit == "TEX" or explicit == "ICON" or explicit == "MODEL" then
      return explicit
    end
    if panel and panel.bgType == "MODEL" then return "MODEL" end
    if panel and panel.bgType == "ICON" then return "ICON" end
    if panel and panel.bgType == "TEX" then return "TEX" end
    if panel and (panel.bgType == "TALENT" or panel.bgType == "CUSTOM") then return "BG" end
    if panel and panel.bg and panel.bg ~= "NONE" then return "BG" end
    if panel and panel.gradient then return "DUAL" end
    return "SINGLE"
  end

  local function ClearPanelBackgroundState(panel)
    if not panel then return end
    panel.bg = "NONE"
    panel.bgType = nil
    panel.bgIconName = nil
    panel.bgTextureName = nil
    panel.bgModelId = nil
    panel.bgModelName = nil
    panel.bgModelSettings = nil
    panel.bgTexCoord = nil
    panel.bgChoiceKey = nil
  end

  local function SetColorMode(mode)
    if not GetSelectedPanelName() then return end
    local panel = DB().panels[GetSelectedPanelName()]
    if not panel then return end
    panel.color = panel.color or { 0.05, 0.05, 0.07, 0.8 }
    local oldMode = GetColorMode(panel)
    panel.designMode = mode
    if mode == "BG" then
      panel.gradient = nil
      if oldMode ~= "BG" then
        ClearPanelBackgroundState(panel)
      elseif not panel.bg then
        panel.bg = "NONE"
      end
    elseif mode == "TEX" then
      panel.gradient = nil
      if oldMode ~= "TEX" then
        ClearPanelBackgroundState(panel)
      end
    elseif mode == "ICON" then
      panel.gradient = nil
      if oldMode ~= "ICON" then
        ClearPanelBackgroundState(panel)
      end
    elseif mode == "MODEL" then
      panel.gradient = nil
      if oldMode ~= "MODEL" then
        ClearPanelBackgroundState(panel)
      end
    elseif mode == "DUAL" then
      ClearPanelBackgroundState(panel)
      if not panel.gradient then
        local alpha = (panel.color and panel.color[4] ~= nil) and panel.color[4] or 0.8
        panel.gradient = {
          dir = "VERTICAL",
          c1 = { panel.color[1] or 0.05, panel.color[2] or 0.05, panel.color[3] or 0.07, alpha },
          c2 = { 0.0, 0.0, 0.0, alpha },
        }
      end
      EnsureGradientTables(panel)
    else
      ClearPanelBackgroundState(panel)
      panel.gradient = nil
    end
    RebuildAllPanels()
    RefreshPanelProperties(editor)
  end

  modeSingleCheck:SetScript("OnClick", function()
    SetColorMode("SINGLE")
  end)
  modeDualCheck:SetScript("OnClick", function()
    SetColorMode("DUAL")
  end)
  modeBgCheck:SetScript("OnClick", function()
    SetColorMode("BG")
  end)
  modeTextureCheck:SetScript("OnClick", function()
    SetColorMode("TEX")
  end)
  modeIconCheck:SetScript("OnClick", function()
    SetColorMode("ICON")
  end)
  modeModelCheck:SetScript("OnClick", function()
    SetColorMode("MODEL")
  end)

  local bgLabel = props:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  bgLabel:SetPoint("TOPLEFT", 0, -554)
  bgLabel:SetText("Talent Backgrounds:")
  editor.bgLabel = bgLabel

  local bgDrop = CreateCustomDropdownControl(editor, props, {
    width = 220,
    text = "None",
  })
  bgDrop:SetPoint("TOPLEFT", -12, -568)
  editor.bgDrop = bgDrop

  local customBgLabel = props:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  customBgLabel:SetPoint("TOPLEFT", 0, -608)
  customBgLabel:SetText("Custom Backgrounds:")
  editor.customBgLabel = customBgLabel

  local customBgDrop = CreateCustomDropdownControl(editor, props, {
    width = 220,
    text = "None",
  })
  customBgDrop:SetPoint("TOPLEFT", -12, -622)
  editor.customBgDrop = customBgDrop

  local textureBgLabel = props:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  textureBgLabel:SetPoint("TOPLEFT", 0, -554)
  textureBgLabel:SetText("Textures:")
  editor.textureBgLabel = textureBgLabel

  local texturePickBtn = CreateFrame("Button", nil, props, "UIPanelButtonTemplate")
  texturePickBtn:SetSize(160, 22)
  texturePickBtn:SetPoint("TOPLEFT", 0, -568)
  texturePickBtn:SetText("Select Texture")
  editor.texturePickBtn = texturePickBtn

  local texturePickBorder = CreateFrame("Frame", nil, texturePickBtn, "BackdropTemplate")
  texturePickBorder:SetPoint("TOPLEFT", -2, 2)
  texturePickBorder:SetPoint("BOTTOMRIGHT", 2, -2)
  texturePickBorder:SetBackdrop({ edgeFile = "Interface/Buttons/WHITE8x8", edgeSize = 1 })
  texturePickBorder:SetBackdropBorderColor(1.0, 0.82, 0.2, 0.9)
  texturePickBorder:Hide()
  editor.texturePickBorder = texturePickBorder

  local textureName = props:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  textureName:SetPoint("TOPLEFT", 0, -594)
  textureName:SetText("Selected: None")
  editor.textureName = textureName

  local iconBgLabel = props:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  iconBgLabel:SetPoint("TOPLEFT", 0, -554)
  iconBgLabel:SetText("Icon:")
  editor.iconBgLabel = iconBgLabel

  local iconPickBtn = CreateFrame("Button", nil, props, "UIPanelButtonTemplate")
  iconPickBtn:SetSize(160, 22)
  iconPickBtn:SetPoint("TOPLEFT", 0, -568)
  iconPickBtn:SetText("Select Icon")
  editor.iconPickBtn = iconPickBtn

  local iconPickBorder = CreateFrame("Frame", nil, iconPickBtn, "BackdropTemplate")
  iconPickBorder:SetPoint("TOPLEFT", -2, 2)
  iconPickBorder:SetPoint("BOTTOMRIGHT", 2, -2)
  iconPickBorder:SetBackdrop({ edgeFile = "Interface/Buttons/WHITE8x8", edgeSize = 1 })
  iconPickBorder:SetBackdropBorderColor(1.0, 0.82, 0.2, 0.9)
  iconPickBorder:Hide()
  editor.iconPickBorder = iconPickBorder

  local iconName = props:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  iconName:SetPoint("TOPLEFT", 0, -594)
  iconName:SetText("Selected: None")
  editor.iconName = iconName

  local modelBgLabel = props:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  modelBgLabel:SetPoint("TOPLEFT", 0, -554)
  modelBgLabel:SetText("Model:")
  editor.modelBgLabel = modelBgLabel

  local modelPickBtn = CreateFrame("Button", nil, props, "UIPanelButtonTemplate")
  modelPickBtn:SetSize(160, 22)
  modelPickBtn:SetPoint("TOPLEFT", 0, -568)
  modelPickBtn:SetText("Select Model")
  editor.modelPickBtn = modelPickBtn

  local modelPickBorder = CreateFrame("Frame", nil, modelPickBtn, "BackdropTemplate")
  modelPickBorder:SetPoint("TOPLEFT", -2, 2)
  modelPickBorder:SetPoint("BOTTOMRIGHT", 2, -2)
  modelPickBorder:SetBackdrop({ edgeFile = "Interface/Buttons/WHITE8x8", edgeSize = 1 })
  modelPickBorder:SetBackdropBorderColor(1.0, 0.82, 0.2, 0.9)
  modelPickBorder:Hide()
  editor.modelPickBorder = modelPickBorder

  local modelName = props:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  modelName:SetPoint("TOPLEFT", 0, -594)
  modelName:SetText("Selected: None")
  editor.modelName = modelName

  local bgPreview = CreateFrame("Frame", nil, props, "BackdropTemplate")
  bgPreview:SetSize(160, 90)
  bgPreview:SetPoint("TOPLEFT", 260, -568)
  bgPreview:SetBackdrop({
    bgFile = "Interface/Buttons/WHITE8x8",
    edgeFile = "Interface/Buttons/WHITE8x8",
    tile = false,
    edgeSize = 1,
    insets = { left = 1, right = 1, top = 1, bottom = 1 },
  })
  bgPreview:SetBackdropColor(0, 0, 0, 0.3)
  bgPreview:SetBackdropBorderColor(0, 0, 0, 0.8)
  local bgTex = bgPreview:CreateTexture(nil, "ARTWORK")
  bgTex:SetAllPoints(true)
  bgPreview.texture = bgTex
  bgPreview:Hide()
  editor.bgPreview = bgPreview

  local bgOptions = BuildBackgroundList(true)
  if bgOptions[1] then bgOptions[1].text = "None" end
  editor.bgOptions = bgOptions

  local bgDropBorder = CreateFrame("Frame", nil, bgDrop, "BackdropTemplate")
  bgDropBorder:SetPoint("TOPLEFT", 12, 0)
  bgDropBorder:SetPoint("BOTTOMRIGHT", -12, 1)
  bgDropBorder:SetBackdrop({ edgeFile = "Interface/Buttons/WHITE8x8", edgeSize = 1 })
  bgDropBorder:SetBackdropBorderColor(1.0, 0.82, 0.2, 0.9)
  bgDropBorder:Hide()
  editor.bgDropBorder = bgDropBorder

  local customBgBorder = CreateFrame("Frame", nil, customBgDrop, "BackdropTemplate")
  customBgBorder:SetPoint("TOPLEFT", 12, 0)
  customBgBorder:SetPoint("BOTTOMRIGHT", -12, 1)
  customBgBorder:SetBackdrop({ edgeFile = "Interface/Buttons/WHITE8x8", edgeSize = 1 })
  customBgBorder:SetBackdropBorderColor(1.0, 0.82, 0.2, 0.9)
  customBgBorder:Hide()
  editor.customBgBorder = customBgBorder

  local textureEntries = INTERNAL_API.LIDPANELS_PANEL_TEXTURE_ENTRIES
  local modelEntries = INTERNAL_API.LIDPANELS_PANEL_MODEL_ENTRIES
  if type(textureEntries) ~= "table" or type(modelEntries) ~= "table" then
    error("LidPanels missing panel asset entry data.")
  end

  local assetPickers = CreatePanelAssetPickers(editor, {
    bgPreview = bgPreview,
    texturePickBtn = texturePickBtn,
    iconPickBtn = iconPickBtn,
    modelPickBtn = modelPickBtn,
    textureEntries = textureEntries,
    modelEntries = modelEntries,
    ClearPanelBackgroundState = ClearPanelBackgroundState,
  })
  local BuildCustomBackgroundOptions = assetPickers.BuildCustomBackgroundOptions
  local CopyTexCoord = assetPickers.CopyTexCoord
  local SameTexCoord = assetPickers.SameTexCoord
  local FindTalentOptionForPanel = assetPickers.FindTalentOptionForPanel
  local UpdateBgPreview = assetPickers.UpdateBgPreview
  local SetPanelBackground = assetPickers.SetPanelBackground

  local panelDropdownPageSize = 20
  editor.panelDropdownPages = editor.panelDropdownPages or { talent = 1, custom = 1 }

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

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

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

    local first = ((page - 1) * panelDropdownPageSize) + 1
    local last = math.min(total, first + panelDropdownPageSize - 1)
    if total == 0 then
      first, last = 1, 0
    end

    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 "__lidPanelsDropdownMeasurer",
      opts.minWidth or 220,
      options,
      extraLabels,
      opts.maxWidth or 420
    )

    local entries = {}
    for idx = first, last do
      local opt = options[idx]
      if opt then
        entries[#entries + 1] = {
          text = opt.text,
          value = opt.value,
          icon = opt.icon,
          iconSize = opt.iconSize or (opt.icon and 16 or nil),
          iconXOffset = opt.iconXOffset,
          checked = (opt.value == currentValue),
          func = function()
            if onSelect then
              onSelect(opt)
            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.panelDropdownPages or {}
          pagesRef[pageKey] = ClampDropdownPage(page - 1, totalPages)
          editor.panelDropdownPages = pagesRef
        end,
      }
      entries[#entries + 1] = {
        text = "Next >",
        notCheckable = true,
        disabled = (page >= totalPages),
        keepShownOnClick = true,
        func = function()
          local pagesRef = editor.panelDropdownPages or {}
          pagesRef[pageKey] = ClampDropdownPage(page + 1, totalPages)
          editor.panelDropdownPages = pagesRef
        end,
      }
    end

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

    return entries, listWidth, OnMouseWheel
  end

  bgDrop:SetMenuBuilder(function()
    local cur = "NONE"
    if GetSelectedPanelName() then
      local panel = DB().panels[GetSelectedPanelName()]
      local opt = FindTalentOptionForPanel(panel, bgOptions)
      if opt and opt.value then
        cur = opt.value
      end
    end

    local entries, listWidth, onMouseWheel = BuildPanelPagedEntries("talent", bgOptions, cur, function(opt)
      SetDropdownSelection(bgDrop, opt.value, opt.text)
      SetPanelBackground(opt.bg or opt.value, "TALENT", opt.text, nil, opt.texCoord, opt.value)
    end, {
      measurerKey = "__lidPanelsTalentBgDropdownMeasurer",
      minWidth = 220,
    })

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

  customBgDrop:SetMenuBuilder(function()
    local cur = "NONE"
    if GetSelectedPanelName() then
      local panel = DB().panels[GetSelectedPanelName()]
      if panel and panel.bg then
        cur = panel.bg
      end
    end

    local options = editor.customBgOptions
    if not options and BuildCustomBackgroundOptions then
      options = BuildCustomBackgroundOptions()
      editor.customBgOptions = options
    end
    if not options then
      options = { { text = "None", value = "NONE" } }
    end

    local entries, listWidth, onMouseWheel = BuildPanelPagedEntries("custom", options, cur, function(opt)
      SetDropdownSelection(customBgDrop, opt.value, opt.text)
      SetPanelBackground(opt.value, "CUSTOM")
    end, {
      measurerKey = "__lidPanelsCustomBgDropdownMeasurer",
      minWidth = 220,
    })

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

  return {
    GetColorMode = GetColorMode,
    bgOptions = bgOptions,
    BuildCustomBackgroundOptions = BuildCustomBackgroundOptions,
    CopyTexCoord = CopyTexCoord,
    SameTexCoord = SameTexCoord,
    FindTalentOptionForPanel = FindTalentOptionForPanel,
    UpdateBgPreview = UpdateBgPreview,
  }
end

INTERNAL_API.LIDPANELS_CreatePanelBackgroundSection_Impl = CreatePanelBackgroundSection
