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 lootListData = INTERNAL_API.LIDCOUNCIL_LootListData_Impl
if type(lootListData) ~= "table" then
  error("LidCouncil missing loot list data helpers.")
end

local RootDB = shared.RootDB
local ApplyFrameSkin = shared.ApplyFrameSkin
local GetLootProfile = shared.GetLootProfile
local GetPrimaryLootProfileName = shared.GetPrimaryLootProfileName
local IsLootProfileVisibleInEditor = shared.IsLootProfileVisibleInEditor or function(_, profileName)
  return profileName ~= nil and profileName ~= ""
end
local GetLootProfileAccessInfo = shared.GetLootProfileAccessInfo
local TrimText = shared.TrimText
local FormatDateTime = shared.FormatDateTime
local ClampLayoutValue = shared.ClampLayoutValue
local SetControlWidth = shared.SetControlWidth
local GetFontStringWidth = shared.GetFontStringWidth
local FlowLayoutControls = shared.FlowLayoutControls

local EnsureLootLedgerMetaLocal = lootListData.EnsureLootLedgerMetaLocal
local ToggleLootLedgerGroupCollapsedLocal = lootListData.ToggleLootLedgerGroupCollapsedLocal
local NormalizeLootLedgerRoleLocal = lootListData.NormalizeLootLedgerRoleLocal
local BuildLootLedgerNavRows = lootListData.BuildLootLedgerNavRows
local GetEditorThemePalette = type(INTERNAL_API.LIDCOUNCIL_GetEditorThemePalette_Impl) == "function" and INTERNAL_API.LIDCOUNCIL_GetEditorThemePalette_Impl or nil
local EnsureLootLedgerRowFrames
local GetSelectedLootLedgerRow
local GetClassColorForRow
local BuildSpecLabel
local GetLootLedgerHeaderIconData
local RefreshLootListTableView
local EnsureLootLedgerHistoryRows
local EnsureLootLedgerMemberRows
local ResolveLootLedgerEntryIcon
local BuildLootLedgerHistoryEntries
local FormatLootLedgerPointBehaviorLabel
local BuildLootLedgerAwardInsight
local BuildLootLedgerNeedDiceInsight
local BuildNeedDiceSummaryText
local BuildBisItemSummaryText
local ApplyLootLedgerTextureIcon
local UpdateLootLedgerDetailLayout

local function BuildLootListInlineIconText(iconData)
  if type(iconData) ~= "table" or TrimText(iconData.texture) == "" then
    return ""
  end
  if type(iconData.left) == "number" and type(iconData.right) == "number" and type(iconData.top) == "number" and type(iconData.bottom) == "number" then
    local fileWidth = tonumber(iconData.fileWidth) or 256
    local fileHeight = tonumber(iconData.fileHeight) or 256
    return string.format(
      "|T%s:14:14:0:0:%d:%d:%d:%d:%d:%d|t ",
      tostring(iconData.texture),
      fileWidth,
      fileHeight,
      math.floor((tonumber(iconData.left) or 0) * fileWidth),
      math.floor((tonumber(iconData.right) or 1) * fileWidth),
      math.floor((tonumber(iconData.top) or 0) * fileHeight),
      math.floor((tonumber(iconData.bottom) or 1) * fileHeight)
    )
  end
  return string.format("|T%s:14:14:0:0|t ", tostring(iconData.texture))
end

local function BuildLootLedgerMainDropdownText(row)
  if type(row) ~= "table" then
    return "(select main)"
  end
  local iconText = BuildLootListInlineIconText(GetLootLedgerHeaderIconData(row))
  local r, g, b = GetClassColorForRow(row)
  local colorHex = string.format("%02x%02x%02x", math.floor((r or 1) * 255), math.floor((g or 1) * 255), math.floor((b or 1) * 255))
  return string.format(
    "%s|cff%s%s|r | %s | %d pts",
    iconText,
    colorHex,
    tostring(row.character or "?"),
    tostring(BuildSpecLabel(row)),
    tonumber(row.totalPoints) or 0
  )
end

local function GetLootListViewMode()
  local root = RootDB()
  root.ui = root.ui or {}
  local mode = TrimText(root.ui.lootLedgerViewMode)
  if mode ~= "DETAILS" then
    mode = "LIST_ONLY"
  end
  root.ui.lootLedgerViewMode = mode
  return mode
end

local function ResolveEffectiveLootListProfileName(requestedName)
  local root = RootDB()
  local resolvedName = TrimText(GetPrimaryLootProfileName(requestedName))
  if resolvedName ~= "" and not IsLootProfileVisibleInEditor(root, resolvedName) then
    resolvedName = ""
  end
  if resolvedName ~= "" then
    return resolvedName
  end
  resolvedName = TrimText(root and root.currentProfile or "")
  if resolvedName ~= "" and not IsLootProfileVisibleInEditor(root, resolvedName) then
    resolvedName = TrimText(type(root.ui) == "table" and root.ui.lastNonSimulationProfile or "")
  end
  if resolvedName ~= "" then
    return resolvedName
  end
  return "Default"
end

local CreateLootListDetailsHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootListDetailsHelpers_Impl
if type(CreateLootListDetailsHelpers) ~= "function" then
  error("LidCouncil missing loot list details helpers.")
end

local lootListDetailsHelpers = CreateLootListDetailsHelpers({
  ApplyFrameSkin = ApplyFrameSkin,
  TrimText = TrimText,
  FormatDateTime = FormatDateTime,
  ClampLayoutValue = ClampLayoutValue,
  SetControlWidth = SetControlWidth,
  GetFontStringWidth = GetFontStringWidth,
  FlowLayoutControls = FlowLayoutControls,
})

EnsureLootLedgerHistoryRows = lootListDetailsHelpers.EnsureLootLedgerHistoryRows
EnsureLootLedgerMemberRows = lootListDetailsHelpers.EnsureLootLedgerMemberRows
ResolveLootLedgerEntryIcon = lootListDetailsHelpers.ResolveLootLedgerEntryIcon
BuildLootLedgerHistoryEntries = lootListDetailsHelpers.BuildLootLedgerHistoryEntries
FormatLootLedgerPointBehaviorLabel = lootListDetailsHelpers.FormatLootLedgerPointBehaviorLabel
BuildLootLedgerAwardInsight = lootListDetailsHelpers.BuildLootLedgerAwardInsight
BuildLootLedgerNeedDiceInsight = lootListDetailsHelpers.BuildLootLedgerNeedDiceInsight
BuildNeedDiceSummaryText = lootListDetailsHelpers.BuildNeedDiceSummaryText
BuildBisItemSummaryText = lootListDetailsHelpers.BuildBisItemSummaryText
ApplyLootLedgerTextureIcon = lootListDetailsHelpers.ApplyLootLedgerTextureIcon
UpdateLootLedgerDetailLayout = lootListDetailsHelpers.UpdateLootLedgerDetailLayout

local CreateLootListTableHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootListTableHelpers_Impl
if type(CreateLootListTableHelpers) ~= "function" then
  error("LidCouncil missing loot list table helpers.")
end

local lootListTableHelpers = CreateLootListTableHelpers({
  TrimText = TrimText,
  ClampLayoutValue = ClampLayoutValue,
  BuildLootLedgerNavRows = BuildLootLedgerNavRows,
  ToggleLootLedgerGroupCollapsedLocal = ToggleLootLedgerGroupCollapsedLocal,
  ApplyLootLedgerTextureIcon = ApplyLootLedgerTextureIcon,
  GetEditorThemePalette = GetEditorThemePalette,
})

GetClassColorForRow = lootListTableHelpers.GetClassColorForRow
BuildSpecLabel = lootListTableHelpers.BuildSpecLabel
GetLootLedgerHeaderIconData = lootListTableHelpers.GetLootLedgerHeaderIconData
EnsureLootLedgerRowFrames = lootListTableHelpers.EnsureLootLedgerRowFrames
GetSelectedLootLedgerRow = lootListTableHelpers.GetSelectedLootLedgerRow
RefreshLootListTableView = lootListTableHelpers.RefreshLootListTableView

local function RefreshLootListPage(self, page)
  if not self or not page then
    return
  end

  if self.lootLedgerSearchEdit and (GetCurrentKeyBoardFocus == nil or GetCurrentKeyBoardFocus() ~= self.lootLedgerSearchEdit) then
    local desiredSearchText = self.__lootLedgerSearchText or ""
    if self.lootLedgerSearchEdit.GetText and self.lootLedgerSearchEdit:GetText() ~= desiredSearchText then
      self.lootLedgerSearchEdit:SetText(desiredSearchText)
    end
  end

  local root = RootDB()
  local resolvedProfileName = ResolveEffectiveLootListProfileName(root.currentProfile)
  local profile, profileName = GetLootProfile(resolvedProfileName)
  local access = GetLootProfileAccessInfo(profileName)
  local pageWidth = (page.GetWidth and page:GetWidth()) or (self.scrollChild and self.scrollChild:GetWidth()) or 980
  local viewMode = GetLootListViewMode()
  local detailsMode = viewMode == "DETAILS"
  local popupOpen = self.__lootLedgerPopupOpen and self.lootListRightBg and self.lootListRightBg:GetParent() ~= page
  local tableState = RefreshLootListTableView(self, page, {
    profile = profile,
    profileName = profileName,
    pageWidth = pageWidth,
    detailsMode = detailsMode,
    popupOpen = popupOpen,
  })
  local showRightPane = tableState and tableState.showRightPane or false
  local selectedRow = tableState and tableState.selectedRow or nil
  local allCharactersByKey = tableState and tableState.allCharactersByKey or {}

  local selectedCharacter = selectedRow and selectedRow.character or nil
  local detailContentWidth = math.max(540, math.floor((self.lootListRightBg and self.lootListRightBg:GetWidth() or 620) - 40))
  local rightWidth = math.max(320, detailContentWidth - 18)
  local metaByCharacter = EnsureLootLedgerMetaLocal(profile)
  local selectedMeta = selectedCharacter and metaByCharacter[selectedCharacter] or nil
  if self.__lootLedgerPendingRoleCharacter and (not selectedCharacter or string.lower(tostring(self.__lootLedgerPendingRoleCharacter or "")) ~= string.lower(tostring(selectedCharacter or ""))) then
    self.__lootLedgerPendingRole = nil
    self.__lootLedgerPendingRoleCharacter = nil
  end
  local selectedRole = NormalizeLootLedgerRoleLocal(selectedRow and selectedRow.mainAltRole or (selectedMeta and selectedMeta.mainAltRole))
  if self.__lootLedgerPendingRoleCharacter and selectedCharacter and string.lower(tostring(self.__lootLedgerPendingRoleCharacter or "")) == string.lower(tostring(selectedCharacter or "")) then
    selectedRole = NormalizeLootLedgerRoleLocal(self.__lootLedgerPendingRole)
  end
  local summaryTarget = TrimText(selectedRow and selectedRow.mainCharacter or (selectedMeta and selectedMeta.mainCharacter) or "")
  if summaryTarget ~= "" and not allCharactersByKey[summaryTarget] then
    summaryTarget = ""
  end
  self.__lootLedgerShowMainAssignment = selectedRole == "ALT"

  if self.backgroundsCurrentLabel then
    self.backgroundsCurrentLabel:SetText("Current Profile: " .. tostring(profileName))
  end

  local textR, textG, textB, textA = GetClassColorForRow(selectedRow)
  ApplyLootLedgerTextureIcon(self.lootLedgerHeroIcon, GetLootLedgerHeaderIconData(selectedRow))
  if self.lootLedgerSelectedLabel then
    self.lootLedgerSelectedLabel:SetText(tostring(selectedCharacter or "(no character selected)"))
    self.lootLedgerSelectedLabel:SetTextColor(textR, textG, textB, textA)
  end
  if self.lootLedgerTotalLabel then
    local classText = selectedRow and TrimText(selectedRow.className) or ""
    local specText = selectedRow and BuildSpecLabel(selectedRow) or ""
    local headerLine = specText ~= "" and specText or "Unknown Specialization"
    if classText ~= "" and classText ~= specText then
      headerLine = headerLine .. " | " .. classText
    end
    self.lootLedgerTotalLabel:SetText(headerLine)
    self.lootLedgerTotalLabel:SetTextColor(textR, textG, textB, textA)
  end
  if self.lootLedgerSummaryText then
    local ownItemCount = tonumber(selectedRow and selectedRow.ownItemCount) or tonumber(selectedRow and selectedRow.itemCount) or 0
    local ownSessionCount = tonumber(selectedRow and selectedRow.ownSessionCount) or tonumber(selectedRow and selectedRow.sessionCount) or 0
    local ownPointCount = tonumber(selectedRow and selectedRow.ownTotalPoints) or tonumber(selectedRow and selectedRow.totalPoints) or 0
    local ownPenaltyCount = tonumber(selectedRow and selectedRow.ownPenaltyPoints) or tonumber(selectedRow and selectedRow.penaltyPoints) or 0
    local groupPointTotal = tonumber(selectedRow and selectedRow.groupTotalPoints) or ownPointCount
    local groupPenaltyCount = tonumber(selectedRow and selectedRow.groupPenaltyPoints) or ownPenaltyCount
    local awardCounters, bisItems = BuildLootLedgerAwardInsight(profile, selectedRow)
    local needDiceInsight = BuildLootLedgerNeedDiceInsight(profile, selectedRow)
    local awardSuffix = string.format(
      "\nBiS Awards: %d (%s)\nOff-Spec Awards: %d | Transmog Awards: %d | Disenchant Awards: %d\n%s",
      tonumber(awardCounters and awardCounters.bis) or 0,
      BuildBisItemSummaryText(bisItems),
      tonumber(awardCounters and awardCounters.offSpec) or 0,
      tonumber(awardCounters and awardCounters.transmog) or 0,
      tonumber(awardCounters and awardCounters.disenchant) or 0,
      BuildNeedDiceSummaryText(needDiceInsight)
    )
    local penaltySuffix = ""
    if ownPenaltyCount > 0 or groupPenaltyCount > 0 then
      penaltySuffix = string.format("\nPenalty: own %d, group %d.", ownPenaltyCount, groupPenaltyCount)
    end
    if not selectedRow then
      self.lootLedgerSummaryText:SetText("Select a character from the Loot List on the left.")
    elseif selectedRole == "ALT" then
      self.lootLedgerSummaryText:SetText(
        string.format(
          "Role: Alt\nAssigned Main: %s\nOwn: %d sessions, %d items, %d points.\nTotal: %d group points.%s",
          summaryTarget ~= "" and summaryTarget or "None",
          ownSessionCount,
          ownItemCount,
          ownPointCount,
          groupPointTotal,
          penaltySuffix .. awardSuffix
        )
      )
    elseif tonumber(selectedRow.summaryMemberCount) and tonumber(selectedRow.summaryMemberCount) > 1 then
      local linkedNames = {}
      for _, memberKey in ipairs(selectedRow.summaryMembers or {}) do
        if memberKey ~= selectedRow.character then
          linkedNames[#linkedNames + 1] = memberKey
        end
      end
      self.lootLedgerSummaryText:SetText(
        string.format(
          "Role: Main\nOwn: %d sessions, %d items, %d points.\nTotal: %d group points across %d characters.\nAttached Alts: %s%s",
          ownSessionCount,
          ownItemCount,
          ownPointCount,
          groupPointTotal,
          tonumber(selectedRow.summaryMemberCount) or 1,
          #linkedNames > 0 and table.concat(linkedNames, ", ") or "None",
          penaltySuffix .. awardSuffix
        )
      )
    else
      self.lootLedgerSummaryText:SetText(
        string.format(
          "Role: Main\nOwn: %d sessions, %d items, %d points.\nTotal: %d group points.\nNo Alts are attached yet.%s",
          ownSessionCount,
          ownItemCount,
          ownPointCount,
          groupPointTotal,
          penaltySuffix .. awardSuffix
        )
      )
    end
  end

  if self.lootLedgerStatCards then
    if self.lootLedgerStatCards.sessions and self.lootLedgerStatCards.sessions.value then
      self.lootLedgerStatCards.sessions.value:SetText(tostring(tonumber(selectedRow and selectedRow.ownSessionCount) or tonumber(selectedRow and selectedRow.sessionCount) or 0))
    end
    if self.lootLedgerStatCards.items and self.lootLedgerStatCards.items.value then
      self.lootLedgerStatCards.items.value:SetText(tostring(tonumber(selectedRow and selectedRow.ownItemCount) or tonumber(selectedRow and selectedRow.itemCount) or 0))
    end
    if self.lootLedgerStatCards.points and self.lootLedgerStatCards.points.value then
      self.lootLedgerStatCards.points.value:SetText(tostring(tonumber(selectedRow and selectedRow.ownTotalPoints) or tonumber(selectedRow and selectedRow.totalPoints) or 0))
    end
    if self.lootLedgerStatCards.total and self.lootLedgerStatCards.total.value then
      self.lootLedgerStatCards.total.value:SetText(tostring(tonumber(selectedRow and selectedRow.groupTotalPoints) or tonumber(selectedRow and selectedRow.totalPoints) or 0))
    end
    if self.lootLedgerStatCards.bis and self.lootLedgerStatCards.bis.value then
      self.lootLedgerStatCards.bis.value:SetText(tostring(tonumber(selectedRow and selectedRow.ownBisCount) or tonumber(selectedRow and selectedRow.bisCount) or 0))
    end
    if self.lootLedgerStatCards.offspec and self.lootLedgerStatCards.offspec.value then
      self.lootLedgerStatCards.offspec.value:SetText(tostring(tonumber(selectedRow and selectedRow.ownOffSpecCount) or tonumber(selectedRow and selectedRow.offSpecCount) or 0))
    end
    if self.lootLedgerStatCards.transmog and self.lootLedgerStatCards.transmog.value then
      self.lootLedgerStatCards.transmog.value:SetText(tostring(tonumber(selectedRow and selectedRow.ownTransmogCount) or tonumber(selectedRow and selectedRow.transmogCount) or 0))
    end
    if self.lootLedgerStatCards.disenchant and self.lootLedgerStatCards.disenchant.value then
      self.lootLedgerStatCards.disenchant.value:SetText(tostring(tonumber(selectedRow and selectedRow.ownDisenchantCount) or tonumber(selectedRow and selectedRow.disenchantCount) or 0))
    end
  end

  local membersHeaderText = "Main and Alt"
  local membersInfoText = ""
  local memberCards = {}

  if not selectedRow then
    membersInfoText = "No Loot List selection available."
  elseif selectedRole == "ALT" then
    membersHeaderText = "Assigned Main"
    if summaryTarget == "" then
      membersInfoText = "This character is marked as an Alt, but no Main is assigned yet. Choose a Main from the dropdown and press Apply."
    else
      local targetRow = allCharactersByKey and allCharactersByKey[summaryTarget] or nil
      if targetRow then
        memberCards[#memberCards + 1] = targetRow
      else
        membersInfoText = "The assigned Main is no longer available in this Loot List."
      end
    end
  else
    membersHeaderText = "Attached Alts"
    for _, memberName in ipairs(selectedRow.summaryMembers or {}) do
      if memberName ~= selectedRow.character then
        local row = allCharactersByKey and allCharactersByKey[memberName] or nil
        if row then
          memberCards[#memberCards + 1] = row
        end
      end
    end
    table.sort(memberCards, function(a, b)
      return string.lower(tostring(a and a.character or "")) < string.lower(tostring(b and b.character or ""))
    end)
    if #memberCards == 0 then
      membersInfoText = "No Alts are attached to this Main yet."
    end
  end

  if self.lootLedgerMembersHeader then
    self.lootLedgerMembersHeader:SetText(membersHeaderText)
  end
  if self.lootLedgerMembersText then
    self.lootLedgerMembersText:SetText(membersInfoText)
    self.lootLedgerMembersText:SetShown(TrimText(membersInfoText) ~= "")
  end

  self.lootLedgerMembersRows = EnsureLootLedgerMemberRows(self.lootLedgerMembersRows, self.lootLedgerMembersRowsFrame, math.max(1, #memberCards))
  local memberCardWidth = rightWidth
  local memberNameWidth = math.max(160, memberCardWidth - 180)
  for index = 1, #self.lootLedgerMembersRows do
    local rowFrame = self.lootLedgerMembersRows[index]
    local memberRow = memberCards[index]
    if memberRow then
      local memberTextR, memberTextG, memberTextB, memberTextA = GetClassColorForRow(memberRow)
      local roleLabel = NormalizeLootLedgerRoleLocal(memberRow.mainAltRole) == "ALT" and "Alt" or "Main"
      local classText = TrimText(memberRow.className)
      local specText = BuildSpecLabel(memberRow)
      local specLine = specText
      if classText ~= "" and classText ~= specText then
        specLine = specLine .. " | " .. classText
      end

      rowFrame:ClearAllPoints()
      rowFrame:SetPoint("TOPLEFT", 0, -((index - 1) * 58))
      rowFrame:SetSize(memberCardWidth, 52)
      rowFrame:Show()

      if rowFrame.__bg then
        if (index % 2) == 0 then
          rowFrame.__bg:SetVertexColor(0.10, 0.06, 0.08, 0.46)
        else
          rowFrame.__bg:SetVertexColor(0.08, 0.05, 0.06, 0.42)
        end
      end
      if rowFrame.__accent then
        rowFrame.__accent:SetVertexColor(memberTextR, memberTextG, memberTextB, 0.95)
      end
      if rowFrame.__icon then
        ApplyLootLedgerTextureIcon(rowFrame.__icon, GetLootLedgerHeaderIconData(memberRow))
      end
      if rowFrame.__nameText then
        rowFrame.__nameText:SetWidth(memberNameWidth)
        rowFrame.__nameText:SetText(tostring(memberRow.character or "?"))
        rowFrame.__nameText:SetTextColor(memberTextR, memberTextG, memberTextB, memberTextA)
      end
      if rowFrame.__roleText then
        rowFrame.__roleText:SetWidth(88)
        rowFrame.__roleText:SetText(roleLabel)
        if roleLabel == "Alt" then
          rowFrame.__roleText:SetTextColor(0.92, 0.77, 0.28, 1)
        else
          rowFrame.__roleText:SetTextColor(0.46, 0.88, 0.62, 1)
        end
      end
      if rowFrame.__specText then
        rowFrame.__specText:SetWidth(memberCardWidth - 64)
        rowFrame.__specText:SetText(specLine)
        rowFrame.__specText:SetTextColor(0.84, 0.84, 0.88, 1)
      end
      if rowFrame.__statsText then
        local sharedGroupPoints = tonumber(selectedRow and selectedRow.groupTotalPoints) or tonumber(memberRow.groupTotalPoints) or tonumber(memberRow.totalPoints) or 0
        rowFrame.__statsText:SetText(string.format(
          "Sessions %d   Items %d   Points %d   Total %d",
          tonumber(memberRow.sessionCount) or 0,
          tonumber(memberRow.itemCount) or 0,
          tonumber(memberRow.totalPoints) or 0,
          sharedGroupPoints
        ))
        rowFrame.__statsText:SetTextColor(0.76, 0.76, 0.80, 1)
      end
    else
      rowFrame:Hide()
    end
  end
  self.lootLedgerMembersRowsHeight = (#memberCards > 0) and ((((#memberCards) - 1) * 58) + 52) or 0

  if self.lootLedgerCharacterNoteEdit and (GetCurrentKeyBoardFocus == nil or GetCurrentKeyBoardFocus() ~= self.lootLedgerCharacterNoteEdit) then
    self.lootLedgerCharacterNoteEdit:SetText(selectedRow and TrimText(selectedRow.note) or "")
  end

  if self.lootLedgerRoleDropdown then
    if self.lootLedgerRoleDropdown.SetMenuBuilder then
      self.lootLedgerRoleDropdown:SetMenuBuilder(function(control)
        local currentValue = NormalizeLootLedgerRoleLocal((control and control.GetSelectedValue and control:GetSelectedValue()) or selectedRole)
        return {
          width = 140,
          entries = {
            {
              text = "Main",
              checked = currentValue == "MAIN",
              func = function()
                control:SetSelectedValue("MAIN")
                control:SetText("Main")
                self.__lootLedgerPendingRole = "MAIN"
                self.__lootLedgerPendingRoleCharacter = selectedCharacter
                if self.RefreshLootListPage then
                  self:RefreshLootListPage()
                end
              end,
            },
            {
              text = "Alt",
              checked = currentValue == "ALT",
              func = function()
                control:SetSelectedValue("ALT")
                control:SetText("Alt")
                self.__lootLedgerPendingRole = "ALT"
                self.__lootLedgerPendingRoleCharacter = selectedCharacter
                if self.RefreshLootListPage then
                  self:RefreshLootListPage()
                end
              end,
            },
          },
        }
      end)
      self.lootLedgerRoleDropdown:SetSelectedValue(selectedRole)
      self.lootLedgerRoleDropdown:SetText(selectedRole == "ALT" and "Alt" or "Main")
    elseif self.lootLedgerRoleDropdown.SetText then
      self.lootLedgerRoleDropdown:SetText(selectedRole == "ALT" and "Alt" or "Main")
    end
    if self.lootLedgerRoleDropdown.Enable then
      if access.canEditMainAlt and selectedCharacter then
        self.lootLedgerRoleDropdown:Enable()
      else
        self.lootLedgerRoleDropdown:Disable()
      end
    end
  end

  if self.lootLedgerSummaryDropdown then
    if self.lootLedgerSummaryDropdown.SetMenuBuilder then
      self.lootLedgerSummaryDropdown:SetMenuBuilder(function(control)
        local entries = {}
        local candidateKeys = {}
        for candidateKey, candidate in pairs(allCharactersByKey or {}) do
          if candidate.character ~= selectedCharacter and NormalizeLootLedgerRoleLocal(candidate.mainAltRole) == "MAIN" then
            candidateKeys[#candidateKeys + 1] = candidateKey
          end
        end
        table.sort(candidateKeys, function(a, b)
          return string.lower(tostring(a or "")) < string.lower(tostring(b or ""))
        end)
        for _, candidateKey in ipairs(candidateKeys) do
          local candidate = allCharactersByKey[candidateKey]
          if candidate then
            local entryText = BuildLootLedgerMainDropdownText(candidate)
            entries[#entries + 1] = {
              text = entryText,
              searchText = string.format(
                "%s %s %s",
                tostring(candidate.character or ""),
                tostring(candidate.specName or ""),
                tostring(candidate.className or "")
              ),
              checked = string.lower(tostring(candidate.character or "")) == string.lower(summaryTarget),
              func = function()
                control:SetSelectedValue(candidate.character)
                control:SetText(entryText)
              end,
            }
          end
        end
        if #entries == 0 then
          entries[1] = {
            text = "No Main characters available",
            disabled = true,
            notCheckable = true,
          }
        end
        return {
          width = math.max(320, math.floor((self.lootListRightBg and self.lootListRightBg:GetWidth() or 620) - 250)),
          entries = entries,
          enableSearch = true,
          searchPlaceholder = "Search Character-Realm",
        }
      end)
      if selectedRole ~= "ALT" then
        self.lootLedgerSummaryDropdown:SetSelectedValue(nil)
        self.lootLedgerSummaryDropdown:SetText("(mains cannot be attached)")
      elseif summaryTarget ~= "" and allCharactersByKey[summaryTarget] then
        local targetRow = allCharactersByKey[summaryTarget]
        self.lootLedgerSummaryDropdown:SetSelectedValue(summaryTarget)
        self.lootLedgerSummaryDropdown:SetText(BuildLootLedgerMainDropdownText(targetRow))
      else
        self.lootLedgerSummaryDropdown:SetSelectedValue(nil)
        self.lootLedgerSummaryDropdown:SetText(selectedCharacter and "(select main)" or "(select a character first)")
      end
    elseif self.lootLedgerSummaryDropdown.SetText then
      if selectedRole ~= "ALT" then
        self.lootLedgerSummaryDropdown:SetText("(mains cannot be attached)")
      else
        self.lootLedgerSummaryDropdown:SetText(summaryTarget)
      end
    end
    if self.lootLedgerSummaryDropdown.Enable then
      if access.canEditMainAlt and selectedCharacter and selectedRole == "ALT" then
        self.lootLedgerSummaryDropdown:Enable()
      else
        self.lootLedgerSummaryDropdown:Disable()
      end
    end
  end

  if self.lootLedgerCharacterEdit and (GetCurrentKeyBoardFocus == nil or GetCurrentKeyBoardFocus() ~= self.lootLedgerCharacterEdit) then
    self.lootLedgerCharacterEdit:SetText(selectedCharacter or "")
  end
  if self.lootLedgerCharacterNoteEdit and self.lootLedgerCharacterNoteEdit.SetEnabled then
    self.lootLedgerCharacterNoteEdit:SetEnabled(access.canEditNotes and selectedCharacter ~= nil)
  end
  if self.lootLedgerAddEntryBtn and self.lootLedgerAddEntryBtn.Enable then
    if selectedCharacter and access.canEditManualPoints then
      self.lootLedgerAddEntryBtn:Enable()
    else
      self.lootLedgerAddEntryBtn:Disable()
    end
  end
  local detailSelectionScope = tostring(selectedType or "") .. ":" .. tostring(selectedKey or selectedCharacter or "")
  if self.__lootLedgerHistorySelectionScope ~= detailSelectionScope then
    self.__lootLedgerHistorySelectionScope = detailSelectionScope
    self.selectedLootLedgerHistoryEntryId = nil
    self.selectedLootLedgerHistoryOwner = nil
  end
  if self.lootLedgerDeleteEntryBtn and self.lootLedgerDeleteEntryBtn.Enable then
    if access.canEditManualPoints and TrimText(self.selectedLootLedgerHistoryEntryId) ~= "" and TrimText(self.selectedLootLedgerHistoryOwner) ~= "" then
      self.lootLedgerDeleteEntryBtn:Enable()
    else
      self.lootLedgerDeleteEntryBtn:Disable()
    end
  end
  if self.lootLedgerDeleteCharacterBtn and self.lootLedgerDeleteCharacterBtn.Enable then
    if selectedCharacter and access.canDeleteLootListCharacter then
      self.lootLedgerDeleteCharacterBtn:Enable()
    else
      self.lootLedgerDeleteCharacterBtn:Disable()
    end
  end
  if self.lootLedgerSummaryLinkBtn and self.lootLedgerSummaryLinkBtn.Enable then
    if selectedCharacter and access.canEditMainAlt then
      self.lootLedgerSummaryLinkBtn:Enable()
    else
      self.lootLedgerSummaryLinkBtn:Disable()
    end
  end
  if self.lootLedgerSummaryClearBtn and self.lootLedgerSummaryClearBtn.Enable then
    if selectedCharacter and access.canEditMainAlt then
      self.lootLedgerSummaryClearBtn:Enable()
    else
      self.lootLedgerSummaryClearBtn:Disable()
    end
  end
  if self.lootLedgerAddGroupBtn and self.lootLedgerAddGroupBtn.Enable then
    if access.canEditLootList then self.lootLedgerAddGroupBtn:Enable() else self.lootLedgerAddGroupBtn:Disable() end
  end
  if self.lootLedgerDeleteGroupBtn and self.lootLedgerDeleteGroupBtn.Enable then
    if access.canEditLootList and tostring(self.selectedLootLedgerType or "") == "group" then
      self.lootLedgerDeleteGroupBtn:Enable()
    else
      self.lootLedgerDeleteGroupBtn:Disable()
    end
  end
  if self.lootLedgerSeedTestBtn then
    local showSeedTestBtn = TrimText(profileName) == "Simulation"
    self.lootLedgerSeedTestBtn:SetShown(showSeedTestBtn)
    if self.lootLedgerSeedTestBtn.Enable then
      if showSeedTestBtn and access.canEditLootList then
        self.lootLedgerSeedTestBtn:Enable()
      else
        self.lootLedgerSeedTestBtn:Disable()
      end
    end
    if self.UpdateLootListToolbarLayout then
      self:UpdateLootListToolbarLayout()
    end
  end

  local historyEntries = BuildLootLedgerHistoryEntries(profile, selectedRow)
  local function IsManualHistoryEntry(entry)
    if type(entry) ~= "table" then
      return false
    end
    if entry.isManual == true then
      return true
    end
    return TrimText(entry.itemLink) == ""
      and tonumber(entry.itemID) == nil
      and TrimText(entry.itemIcon) == "Interface\\Icons\\INV_Misc_Note_06"
  end
  local function FormatHistoryRollText(entry)
    if type(entry) ~= "table" then
      return ""
    end
    local label = TrimText(entry.rollOptionLabel)
    if label == "" then
      label = FormatLootLedgerPointBehaviorLabel(entry.pointBehavior)
    end
    if label == "" then
      return ""
    end
    local rollValue = tonumber(entry.rollValue)
    if rollValue then
      return string.format("%s (%d)", label, math.floor(rollValue + 0.5))
    end
    return label
  end

  local selectedHistoryEntryId = TrimText(self.selectedLootLedgerHistoryEntryId)
  local selectedHistoryOwner = TrimText(self.selectedLootLedgerHistoryOwner)
  local selectedHistoryStillExists = false
  self.lootLedgerHistoryRows = EnsureLootLedgerHistoryRows(self.lootLedgerHistoryRows, self.lootLedgerHistoryRowsFrame, math.max(1, #historyEntries))
  local historyItemWidth = math.max(170, rightWidth - 250)
  local historyReceivedX = math.max(186, rightWidth - 236)
  local historyPointsX = math.max(352, rightWidth - 74)
  for index = 1, #self.lootLedgerHistoryRows do
    local rowFrame = self.lootLedgerHistoryRows[index]
    local entry = historyEntries[index]
    if entry then
      local rowName = TrimText(entry.itemName)
      if rowName == "" then
        local itemLink = TrimText(entry.itemLink)
        rowName = TrimText(itemLink:match("%[(.-)%]") or itemLink)
      end
      if rowName == "" then
        rowName = "?"
      end
      if tonumber(entry.itemLevel) then
        rowName = string.format("%s (iLvl %d)", rowName, tonumber(entry.itemLevel))
      end
      local rollText = FormatHistoryRollText(entry)
      if rollText ~= "" then
        rowName = string.format("%s | %s", rowName, rollText)
      end
      if tonumber(selectedRow and selectedRow.summaryMemberCount) and tonumber(selectedRow.summaryMemberCount) > 1 then
        rowName = tostring(entry.owner or "?") .. " - " .. rowName
      end
      local isManualEntry = IsManualHistoryEntry(entry)
      if isManualEntry and TrimText(entry.note) ~= "" then
        rowName = rowName .. " | " .. tostring(entry.note)
      end
      if isManualEntry and TrimText(entry.grantedBy) ~= "" then
        rowName = rowName .. " | by " .. tostring(entry.grantedBy)
      end

      rowFrame:ClearAllPoints()
      rowFrame:SetPoint("TOPLEFT", 0, -((index - 1) * 26))
      rowFrame:SetSize(rightWidth, 24)
      rowFrame:Show()

      if rowFrame.__bg then
        local isSelectedHistory = TrimText(entry.entryId) ~= "" and TrimText(entry.entryId) == selectedHistoryEntryId and TrimText(entry.owner) == selectedHistoryOwner
        if isSelectedHistory then
          selectedHistoryStillExists = true
          rowFrame.__bg:SetVertexColor(0.26, 0.18, 0.06, 0.88)
        elseif (index % 2) == 0 then
          rowFrame.__bg:SetVertexColor(0.10, 0.06, 0.08, 0.76)
        else
          rowFrame.__bg:SetVertexColor(0.07, 0.04, 0.05, 0.72)
        end
      end
      if rowFrame.__icon then
        rowFrame.__icon:SetTexture(ResolveLootLedgerEntryIcon(entry))
        rowFrame.__icon:SetTexCoord(0, 1, 0, 1)
      end
      if rowFrame.__nameText then
        rowFrame.__nameText:ClearAllPoints()
        rowFrame.__nameText:SetPoint("LEFT", rowFrame.__icon, "RIGHT", 8, 0)
        rowFrame.__nameText:SetWidth(historyItemWidth - 26)
        rowFrame.__nameText:SetText(rowName)
        local rollColor = type(entry.rollOptionColor) == "table" and entry.rollOptionColor or nil
        local quality = tonumber(entry.itemQuality)
        if rollColor and tonumber(rollColor[1]) and tonumber(rollColor[2]) and tonumber(rollColor[3]) then
          rowFrame.__nameText:SetTextColor(tonumber(rollColor[1]), tonumber(rollColor[2]), tonumber(rollColor[3]), 1)
        elseif quality and type(GetItemQualityColor) == "function" then
          local qualityR, qualityG, qualityB = GetItemQualityColor(quality)
          rowFrame.__nameText:SetTextColor(tonumber(qualityR) or 1, tonumber(qualityG) or 1, tonumber(qualityB) or 1, 1)
        else
          rowFrame.__nameText:SetTextColor(1, 1, 1, 1)
        end
      end
      if rowFrame.__receivedText then
        rowFrame.__receivedText:ClearAllPoints()
        rowFrame.__receivedText:SetPoint("LEFT", historyReceivedX, 0)
        rowFrame.__receivedText:SetText(FormatDateTime(entry.awardedAt))
        rowFrame.__receivedText:SetTextColor(1, 1, 1, 1)
      end
      if rowFrame.__pointsText then
        rowFrame.__pointsText:ClearAllPoints()
        rowFrame.__pointsText:SetPoint("LEFT", historyPointsX, 0)
        rowFrame.__pointsText:SetText(tostring(tonumber(entry.points) or 0))
        rowFrame.__pointsText:SetTextColor(1, 1, 1, 1)
      end
      rowFrame:EnableMouse(access.canEditManualPoints and IsManualHistoryEntry(entry))
      rowFrame:SetScript("OnMouseUp", function()
        if not access.canEditManualPoints or not IsManualHistoryEntry(entry) then
          return
        end
        self.selectedLootLedgerHistoryEntryId = TrimText(entry.entryId)
        self.selectedLootLedgerHistoryOwner = TrimText(entry.owner)
        if self.RefreshLootListPage then
          self:RefreshLootListPage()
        elseif self.Refresh then
          self:Refresh()
        end
      end)
    else
      rowFrame:EnableMouse(false)
      rowFrame:SetScript("OnMouseUp", nil)
      rowFrame:Hide()
    end
  end
  if (not selectedHistoryStillExists) and selectedHistoryEntryId ~= "" then
    self.selectedLootLedgerHistoryEntryId = nil
    self.selectedLootLedgerHistoryOwner = nil
  end
  self.lootLedgerHistoryRowsHeight = math.max(1, #historyEntries * 26)

  if not selectedRow then
    self.lootLedgerHistoryText:SetText("No Loot List entry selected.")
  elseif #historyEntries == 0 then
    self.lootLedgerHistoryText:SetText("No awarded items recorded yet for this character.")
  elseif tonumber(selectedRow.summaryMemberCount) and tonumber(selectedRow.summaryMemberCount) > 1 then
    self.lootLedgerHistoryText:SetText("Showing the combined loot history for the linked characters above.")
  else
    self.lootLedgerHistoryText:SetText("")
  end

  if showRightPane then
    UpdateLootLedgerDetailLayout(self)
  end
  if self.UpdateScrollLayout then
    self:UpdateScrollLayout()
  end
end

INTERNAL_API.LIDCOUNCIL_LootListRendering_Impl = {
  GetClassColorForRow = GetClassColorForRow,
  BuildSpecLabel = BuildSpecLabel,
  GetLootLedgerHeaderIconData = GetLootLedgerHeaderIconData,
  EnsureLootLedgerRowFrames = EnsureLootLedgerRowFrames,
  GetSelectedLootLedgerRow = GetSelectedLootLedgerRow,
  EnsureLootLedgerHistoryRows = EnsureLootLedgerHistoryRows,
  EnsureLootLedgerMemberRows = EnsureLootLedgerMemberRows,
  ResolveLootLedgerEntryIcon = ResolveLootLedgerEntryIcon,
  BuildLootLedgerHistoryEntries = BuildLootLedgerHistoryEntries,
  ApplyLootLedgerTextureIcon = ApplyLootLedgerTextureIcon,
  UpdateLootLedgerDetailLayout = UpdateLootLedgerDetailLayout,
  RefreshLootListPage = RefreshLootListPage,
}
