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

INTERNAL_API.LIDCOUNCIL_CreateLootListAwardsViewHelpers_Impl = function(deps)
  deps = type(deps) == "table" and deps or {}

  local ApplyFrameSkin = deps.ApplyFrameSkin
  local BindMouseWheelScroll = deps.BindMouseWheelScroll
  local TrimText = deps.TrimText
  local ResolveOptionalApiFunction = deps.ResolveOptionalApiFunction

  local AWARD_ART_ROOT = "Interface\\AddOns\\LidCouncil\\Media\\LidCouncil\\FunAwards\\"
  local FEATURED_AWARD_KEYS = { "luckiest", "bis_everything", "hoarder" }
  local AWARD_STYLES = {
    luckiest = {
      art = AWARD_ART_ROOT .. "1_Luckiest_Roller.tga",
      accent = { 0.96, 0.72, 0.22 },
      metricLabel = "Average roll",
      requirement = "Requires recorded dice rolls.",
    },
    worst = {
      art = AWARD_ART_ROOT .. "2_Worst_Roller.tga",
      accent = { 0.74, 0.34, 0.27 },
      metricLabel = "Average roll",
      requirement = "Requires recorded dice rolls.",
    },
    bis_everything = {
      art = AWARD_ART_ROOT .. "3_EverythingIsBiS.tga",
      accent = { 0.70, 0.38, 0.94 },
      metricLabel = "First-option rolls",
      requirement = "Requires a player to select the first roll option.",
    },
    boss_voter = {
      art = AWARD_ART_ROOT .. "4_thebossvoter.tga",
      accent = { 0.32, 0.62, 0.94 },
      metricLabel = "Council votes",
      requirement = "Requires council votes on dropped items.",
    },
    prettiest = {
      art = AWARD_ART_ROOT .. "5_Prettiest_Raider.tga",
      accent = { 0.93, 0.48, 0.78 },
      metricLabel = "Transmog items",
      requirement = "Requires an awarded Transmog roll.",
    },
    no_respect = {
      art = AWARD_ART_ROOT .. "6_NRFTI.tga",
      accent = { 0.84, 0.44, 0.22 },
      metricLabel = "Disenchanted items",
      requirement = "Requires an awarded Disenchant roll.",
    },
    needs_loot = {
      art = AWARD_ART_ROOT .. "7_whoneedsloot.tga",
      accent = { 0.91, 0.62, 0.24 },
      metricLabel = "Pass rolls",
      requirement = "Requires pass rolls from a player.",
    },
    forgotten = {
      art = AWARD_ART_ROOT .. "8_theforgotten.tga",
      accent = { 0.57, 0.48, 0.68 },
      metricLabel = "Need rolls without loot",
      requirement = "Requires Need rolls without receiving an item.",
    },
    hoarder = {
      art = AWARD_ART_ROOT .. "9_Hoarder.tga",
      accent = { 0.89, 0.66, 0.26 },
      metricLabel = "Items received",
      requirement = "Requires awarded items in the Loot List.",
    },
  }
  local DEFAULT_AWARD_STYLE = {
    art = "Interface\\Icons\\INV_Misc_QuestionMark",
    accent = { 0.66, 0.70, 0.78 },
    metricLabel = "Result",
    requirement = "Requires qualifying real-session activity.",
  }
  local OpenAwardDetailsOverlay

  local function trim(value)
    if type(TrimText) == "function" then
      return TrimText(value)
    end
    local text = tostring(value or "")
    text = text:gsub("^%s+", "")
    text = text:gsub("%s+$", "")
    return text
  end

  local function SetWidgetShown(widget, shown)
    if not widget then
      return
    end
    if widget.SetShown then
      widget:SetShown(shown and true or false)
    elseif shown and widget.Show then
      widget:Show()
    elseif (not shown) and widget.Hide then
      widget:Hide()
    end
  end

  local function GetAwardsProvider()
    if type(ResolveOptionalApiFunction) == "function" then
      return ResolveOptionalApiFunction("LIDCOUNCIL_GetLootRollAwards")
    end
    local api = rawget(_G, "LIDCOUNCIL_API")
    if type(api) == "table" and type(api.LIDCOUNCIL_GetLootRollAwards) == "function" then
      return api.LIDCOUNCIL_GetLootRollAwards
    end
    return rawget(_G, "LIDCOUNCIL_GetLootRollAwards")
  end

  local function GetAwardStyle(award)
    local key = trim(type(award) == "table" and award.key or "")
    return AWARD_STYLES[key] or DEFAULT_AWARD_STYLE
  end

  local function GetAwardMetricParts(award, style)
    if not (award and award.hasWinner) then
      return "Not awarded yet", tostring(style.requirement or "Requires qualifying real-session activity.")
    end
    local metric = trim(type(award) == "table" and award.metric or "")
    local value, remainder = metric:match("^([%d%.]+)%s*(.*)$")
    if not value then
      return "-", style.metricLabel or "Result"
    end
    local label = trim(style.metricLabel)
    if label == "" then
      label = trim(remainder):gsub("%(s%)", "s")
    end
    return value, label ~= "" and label or "Result"
  end

  local function ShowAwardTooltip(owner, award, style)
    if not GameTooltip then
      return
    end
    GameTooltip:SetOwner(owner, "ANCHOR_RIGHT")
    GameTooltip:ClearLines()
    GameTooltip:AddLine(tostring(award and award.title or "Fun Award"), 1.00, 0.82, 0.28)
    if award and award.hasWinner then
      GameTooltip:AddLine("Winner: " .. tostring(award.winner or "Unknown"), 0.92, 0.94, 0.98)
      GameTooltip:AddLine(tostring(award.metric or "-"), 0.92, 0.94, 0.98)
    else
      GameTooltip:AddLine("Not awarded yet", 0.70, 0.72, 0.78)
      GameTooltip:AddLine(tostring(style.requirement or "Requires qualifying real-session activity."), 0.70, 0.72, 0.78, true)
    end
    GameTooltip:AddLine(" ")
    GameTooltip:AddLine(tostring(award and award.detail or ""), 0.80, 0.82, 0.87, true)
    GameTooltip:AddLine("Real sessions only. Simulations are excluded.", 0.54, 0.66, 0.74, true)
    GameTooltip:Show()
  end

  local function EnsureAwardCards(frame, count)
    frame.awardCards = frame.awardCards or {}
    while #frame.awardCards < count do
      local card = CreateFrame("Frame", nil, frame.content, "BackdropTemplate")
      card:EnableMouse(true)
      if type(ApplyFrameSkin) == "function" then
        ApplyFrameSkin(card)
      end

      local topAccent = card:CreateTexture(nil, "ARTWORK")
      topAccent:SetTexture("Interface\\Buttons\\WHITE8x8")
      topAccent:SetPoint("TOPLEFT", 1, -1)
      topAccent:SetPoint("TOPRIGHT", -1, -1)
      topAccent:SetHeight(3)
      card.topAccent = topAccent

      local title = card:CreateFontString(nil, "OVERLAY", "GameFontNormal")
      title:SetPoint("TOPLEFT", 14, -12)
      title:SetJustifyH("LEFT")
      title:SetWordWrap(false)
      card.title = title

      local featured = card:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
      featured:SetPoint("TOPRIGHT", -38, -14)
      featured:SetJustifyH("RIGHT")
      featured:SetText("FEATURED")
      featured:SetTextColor(1.00, 0.82, 0.28, 0.92)
      card.featured = featured

      local helpButton = CreateFrame("Button", nil, card, "BackdropTemplate")
      helpButton:SetSize(22, 22)
      helpButton:SetPoint("TOPRIGHT", -11, -9)
      helpButton:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 1,
      })
      helpButton:SetBackdropColor(0.035, 0.045, 0.065, 0.94)
      helpButton:SetBackdropBorderColor(0.45, 0.53, 0.66, 0.88)
      helpButton:EnableMouse(true)
      local helpText = helpButton:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
      helpText:SetAllPoints()
      helpText:SetJustifyH("CENTER")
      helpText:SetText("?")
      helpText:SetTextColor(0.82, 0.86, 0.94, 1.00)
      helpButton.text = helpText
      helpButton:SetScript("OnEnter", function(self)
        if card.__award then
          ShowAwardTooltip(self, card.__award, card.__style or DEFAULT_AWARD_STYLE)
        end
        self.text:SetTextColor(1.00, 0.82, 0.28, 1.00)
        self:SetBackdropBorderColor(1.00, 0.82, 0.28, 0.98)
      end)
      helpButton:SetScript("OnLeave", function(self)
        if GameTooltip then
          GameTooltip:Hide()
        end
        self.text:SetTextColor(0.82, 0.86, 0.94, 1.00)
        self:SetBackdropBorderColor(0.45, 0.53, 0.66, 0.88)
      end)
      card.helpButton = helpButton

      local artBackground = card:CreateTexture(nil, "BACKGROUND")
      artBackground:SetTexture("Interface\\Buttons\\WHITE8x8")
      artBackground:SetPoint("TOP", card, "TOP", 0, -39)
      artBackground:SetSize(142, 142)
      artBackground:SetVertexColor(0.01, 0.01, 0.015, 0.64)
      card.artBackground = artBackground

      local art = card:CreateTexture(nil, "ARTWORK")
      art:SetPoint("CENTER", artBackground, "CENTER", 0, 0)
      art:SetSize(128, 128)
      card.art = art

      local metricValue = card:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
      metricValue:SetJustifyH("CENTER")
      card.metricValue = metricValue

      local metricLabel = card:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
      metricLabel:SetJustifyH("CENTER")
      metricLabel:SetTextColor(0.76, 0.79, 0.86, 1.00)
      card.metricLabel = metricLabel

      local winner = card:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
      winner:SetJustifyH("CENTER")
      winner:SetWordWrap(false)
      card.winner = winner

      local winnerLabel = card:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
      winnerLabel:SetJustifyH("CENTER")
      winnerLabel:SetTextColor(0.66, 0.69, 0.75, 1.00)
      card.winnerLabel = winnerLabel

      card:SetScript("OnEnter", function(self)
        local accent = self.__accent or DEFAULT_AWARD_STYLE.accent
        self:SetBackdropBorderColor(math.min(1, (accent[1] or 0.7) + 0.16), math.min(1, (accent[2] or 0.7) + 0.16), math.min(1, (accent[3] or 0.7) + 0.16), 0.98)
        self:SetBackdropColor(0.045, 0.052, 0.070, 0.98)
      end)
      card:SetScript("OnLeave", function(self)
        local accent = self.__accent or DEFAULT_AWARD_STYLE.accent
        local alpha = self.__hasWinner and 0.74 or 0.48
        self:SetBackdropBorderColor(accent[1] or 0.66, accent[2] or 0.70, accent[3] or 0.78, alpha)
        self:SetBackdropColor(self.__hasWinner and 0.025 or 0.018, self.__hasWinner and 0.030 or 0.022, self.__hasWinner and 0.043 or 0.032, 0.98)
      end)
      card:SetScript("OnMouseUp", function(self, button)
        local overHelp = self.helpButton and self.helpButton.IsMouseOver and self.helpButton:IsMouseOver()
        if button == "LeftButton" and not overHelp and self.__award and type(OpenAwardDetailsOverlay) == "function" then
          OpenAwardDetailsOverlay(self.__awardsView, self.__award)
        end
      end)

      frame.awardCards[#frame.awardCards + 1] = card
    end
    return frame.awardCards
  end

  local function EnsureAwardsView(editor, parent)
    if not editor or not parent then
      return nil
    end
    if editor.lootLedgerAwardsView then
      return editor.lootLedgerAwardsView
    end

    local frame = CreateFrame("Frame", nil, parent, "BackdropTemplate")
    frame:SetAllPoints(parent)
    frame:EnableMouse(true)
    if type(ApplyFrameSkin) == "function" then
      ApplyFrameSkin(frame)
    end
    if frame.SetBackdropColor then
      frame:SetBackdropColor(0.025, 0.03, 0.045, 0.98)
    end

    local title = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    title:SetPoint("TOPLEFT", 18, -16)
    title:SetText("Fun Awards")
    title:SetTextColor(1.00, 0.82, 0.28, 1.00)
    frame.title = title

    local intro = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    intro:SetPoint("TOPLEFT", 18, -42)
    intro:SetPoint("TOPRIGHT", -34, -42)
    intro:SetJustifyH("LEFT")
    intro:SetText("Questionably scientific statistics from this profile's real loot history.")
    frame.intro = intro

    local scroll = CreateFrame("ScrollFrame", nil, frame, "UIPanelScrollFrameTemplate")
    scroll:SetPoint("TOPLEFT", 14, -66)
    scroll:SetPoint("BOTTOMRIGHT", -32, 14)
    if type(BindMouseWheelScroll) == "function" then
      BindMouseWheelScroll(scroll, 18)
    end
    frame.scroll = scroll

    local content = CreateFrame("Frame", nil, scroll)
    content:SetSize(560, 1)
    scroll:SetScrollChild(content)
    frame.content = content

    local featuredTitle = content:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    featuredTitle:SetText("Featured Awards")
    featuredTitle:SetTextColor(1.00, 0.82, 0.28, 1.00)
    frame.featuredTitle = featuredTitle

    local allTitle = content:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    allTitle:SetText("All Awards")
    allTitle:SetTextColor(0.90, 0.92, 0.97, 1.00)
    frame.allTitle = allTitle

    editor.lootLedgerAwardsView = frame
    frame:Hide()
    return frame
  end

  local function CreateOverlayButton(parent, text, width)
    local button = CreateFrame("Button", nil, parent, "BackdropTemplate")
    button:SetSize(width, 24)
    button:SetBackdrop({
      bgFile = "Interface\\Buttons\\WHITE8x8",
      edgeFile = "Interface\\Buttons\\WHITE8x8",
      edgeSize = 1,
    })
    button:SetBackdropColor(0.06, 0.10, 0.16, 0.98)
    button:SetBackdropBorderColor(0.38, 0.56, 0.78, 0.94)
    local label = button:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    label:SetAllPoints()
    label:SetJustifyH("CENTER")
    label:SetText(tostring(text or ""))
    button.label = label
    button:SetScript("OnEnter", function(self)
      self:SetBackdropColor(0.09, 0.15, 0.23, 0.98)
      self:SetBackdropBorderColor(1.00, 0.82, 0.28, 0.98)
      self.label:SetTextColor(1.00, 0.88, 0.50, 1.00)
    end)
    button:SetScript("OnLeave", function(self)
      self:SetBackdropColor(0.06, 0.10, 0.16, 0.98)
      self:SetBackdropBorderColor(0.38, 0.56, 0.78, 0.94)
      self.label:SetTextColor(1.00, 1.00, 1.00, 1.00)
    end)
    return button
  end

  local function CreateOverlayCloseButton(parent)
    local button = CreateFrame("Button", nil, parent, "BackdropTemplate")
    button:SetSize(28, 28)
    button:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8" })
    button:SetBackdropColor(0.02, 0.03, 0.05, 0.01)
    local label = button:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    label:SetAllPoints()
    label:SetJustifyH("CENTER")
    label:SetText("x")
    label:SetTextColor(0.74, 0.78, 0.86, 1.00)
    button.label = label
    button:SetScript("OnEnter", function(self)
      self:SetBackdropColor(0.22, 0.06, 0.05, 0.92)
      self.label:SetTextColor(1.00, 0.50, 0.42, 1.00)
    end)
    button:SetScript("OnLeave", function(self)
      self:SetBackdropColor(0.02, 0.03, 0.05, 0.01)
      self.label:SetTextColor(0.74, 0.78, 0.86, 1.00)
    end)
    return button
  end

  local function EnsureAwardDetailsOverlay(frame)
    if not frame then
      return nil
    end
    if frame.awardDetailsOverlay then
      return frame.awardDetailsOverlay
    end

    local overlay = CreateFrame("Frame", nil, frame, "BackdropTemplate")
    overlay:SetAllPoints(frame)
    overlay:SetFrameStrata("DIALOG")
    overlay:SetToplevel(true)
    if overlay.SetFrameLevel and frame.GetFrameLevel then
      overlay:SetFrameLevel((frame:GetFrameLevel() or 1) + 30)
    end
    overlay:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8" })
    overlay:SetBackdropColor(0.005, 0.008, 0.014, 0.62)
    overlay:EnableMouse(true)
    overlay:EnableKeyboard(true)

    local panel = CreateFrame("Frame", nil, overlay, "BackdropTemplate")
    panel:SetPoint("CENTER", overlay, "CENTER")
    panel:SetSize(720, 260)
    panel:SetBackdrop({
      bgFile = "Interface\\Buttons\\WHITE8x8",
      edgeFile = "Interface\\Buttons\\WHITE8x8",
      edgeSize = 1,
    })
    panel:SetBackdropColor(0.018, 0.024, 0.038, 0.99)
    panel:SetBackdropBorderColor(0.43, 0.50, 0.62, 0.92)
    panel:EnableMouse(true)
    overlay.panel = panel

    local topAccent = panel:CreateTexture(nil, "ARTWORK")
    topAccent:SetTexture("Interface\\Buttons\\WHITE8x8")
    topAccent:SetPoint("TOPLEFT", 1, -1)
    topAccent:SetPoint("TOPRIGHT", -1, -1)
    topAccent:SetHeight(2)
    topAccent:SetVertexColor(1.00, 0.82, 0.28, 0.94)
    overlay.topAccent = topAccent

    local icon = panel:CreateTexture(nil, "ARTWORK")
    icon:SetSize(52, 52)
    icon:SetPoint("TOPLEFT", 18, -16)
    overlay.icon = icon

    local title = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    title:SetPoint("TOPLEFT", icon, "TOPRIGHT", 12, -4)
    title:SetPoint("TOPRIGHT", -150, -16)
    title:SetTextColor(1.00, 0.82, 0.28, 1.00)
    overlay.title = title

    local meta = panel:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    meta:SetPoint("TOPLEFT", icon, "TOPRIGHT", 12, -30)
    meta:SetPoint("TOPRIGHT", -150, -42)
    meta:SetJustifyH("LEFT")
    meta:SetTextColor(0.78, 0.84, 0.94, 1.00)
    overlay.meta = meta

    local rule = panel:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    rule:SetPoint("TOPLEFT", 18, -83)
    rule:SetPoint("TOPRIGHT", -24, -83)
    rule:SetJustifyH("LEFT")
    rule:SetTextColor(0.66, 0.70, 0.78, 1.00)
    overlay.rule = rule

    local qualifiedBadge = CreateFrame("Frame", nil, panel, "BackdropTemplate")
    qualifiedBadge:SetSize(92, 22)
    qualifiedBadge:SetPoint("TOPRIGHT", -50, -18)
    qualifiedBadge:SetBackdrop({
      bgFile = "Interface\\Buttons\\WHITE8x8",
      edgeFile = "Interface\\Buttons\\WHITE8x8",
      edgeSize = 1,
    })
    qualifiedBadge:SetBackdropColor(0.05, 0.09, 0.14, 0.94)
    qualifiedBadge:SetBackdropBorderColor(0.30, 0.46, 0.68, 0.88)
    local qualifiedBadgeText = qualifiedBadge:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    qualifiedBadgeText:SetAllPoints()
    qualifiedBadgeText:SetJustifyH("CENTER")
    qualifiedBadgeText:SetTextColor(0.72, 0.82, 0.96, 1.00)
    qualifiedBadge.text = qualifiedBadgeText
    overlay.qualifiedBadge = qualifiedBadge

    local closeButton = CreateOverlayCloseButton(panel)
    closeButton:SetPoint("TOPRIGHT", -14, -13)
    closeButton:SetScript("OnClick", function()
      overlay:Hide()
    end)
    overlay.closeButton = closeButton

    local showAllButton = CreateOverlayButton(panel, "Show All", 102)
    showAllButton:SetPoint("BOTTOMRIGHT", -16, 14)
    showAllButton:SetScript("OnClick", function()
      overlay.__showAll = not overlay.__showAll
      if type(overlay.__refresh) == "function" then
        overlay.__refresh()
      end
    end)
    overlay.showAllButton = showAllButton

    local separator = panel:CreateTexture(nil, "ARTWORK")
    separator:SetTexture("Interface\\Buttons\\WHITE8x8")
    separator:SetPoint("TOPLEFT", 18, -108)
    separator:SetPoint("TOPRIGHT", -18, -108)
    separator:SetHeight(1)
    separator:SetVertexColor(0.33, 0.40, 0.52, 0.72)
    overlay.separator = separator

    local tableHeader = panel:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    tableHeader:SetPoint("TOPLEFT", 18, -116)
    tableHeader:SetPoint("TOPRIGHT", -28, -116)
    tableHeader:SetJustifyH("LEFT")
    tableHeader:SetTextColor(1.00, 0.82, 0.28, 0.90)
    tableHeader:SetText("Rank     Raider")
    overlay.tableHeader = tableHeader

    local tableMetricHeader = panel:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    tableMetricHeader:SetPoint("TOPRIGHT", -28, -116)
    tableMetricHeader:SetJustifyH("RIGHT")
    tableMetricHeader:SetTextColor(1.00, 0.82, 0.28, 0.90)
    overlay.tableMetricHeader = tableMetricHeader

    local scroll = CreateFrame("ScrollFrame", nil, panel, "UIPanelScrollFrameTemplate")
    scroll:SetPoint("TOPLEFT", 14, -134)
    scroll:SetPoint("BOTTOMRIGHT", -28, 14)
    if type(BindMouseWheelScroll) == "function" then
      BindMouseWheelScroll(scroll, 18)
    end
    overlay.scroll = scroll

    local content = CreateFrame("Frame", nil, scroll)
    content:SetSize(1, 1)
    scroll:SetScrollChild(content)
    overlay.content = content

    local emptyText = panel:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    emptyText:SetPoint("CENTER", panel, "CENTER", 0, 18)
    emptyText:SetWidth(480)
    emptyText:SetJustifyH("CENTER")
    emptyText:SetTextColor(0.74, 0.76, 0.82, 1.00)
    overlay.emptyText = emptyText

    overlay.rankingRows = {}
    overlay:SetScript("OnKeyDown", function(_, key)
      if key == "ESCAPE" then
        overlay:Hide()
      end
    end)
    overlay:SetScript("OnMouseUp", function(self, button)
      if button == "LeftButton" and self.panel and self.panel.IsMouseOver and not self.panel:IsMouseOver() then
        self:Hide()
      end
    end)
    frame.awardDetailsOverlay = overlay
    overlay:Hide()
    return overlay
  end

  local function EnsureAwardRankingRows(overlay, count)
    while #overlay.rankingRows < count do
      local row = CreateFrame("Frame", nil, overlay.content, "BackdropTemplate")
      row:SetHeight(46)
      row:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8" })

      local leaderStripe = row:CreateTexture(nil, "ARTWORK")
      leaderStripe:SetTexture("Interface\\Buttons\\WHITE8x8")
      leaderStripe:SetPoint("TOPLEFT", 0, 0)
      leaderStripe:SetPoint("BOTTOMLEFT", 0, 0)
      leaderStripe:SetWidth(3)
      leaderStripe:SetVertexColor(1.00, 0.82, 0.28, 0.96)
      row.leaderStripe = leaderStripe

      local rankIcon = row:CreateTexture(nil, "OVERLAY")
      rankIcon:SetSize(18, 18)
      rankIcon:SetPoint("LEFT", 8, 0)
      rankIcon:SetTexture("Interface\\GroupFrame\\UI-Group-LeaderIcon")
      row.rankIcon = rankIcon

      local rank = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
      rank:SetPoint("LEFT", 31, 0)
      rank:SetWidth(30)
      rank:SetJustifyH("CENTER")
      row.rank = rank

      local name = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
      name:SetPoint("TOPLEFT", 68, -6)
      name:SetJustifyH("LEFT")
      name:SetWordWrap(false)
      row.name = name

      local detail = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
      detail:SetPoint("TOPLEFT", 68, -25)
      detail:SetJustifyH("LEFT")
      detail:SetTextColor(0.66, 0.70, 0.78, 1.00)
      row.detail = detail

      local metric = row:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
      metric:SetPoint("TOPRIGHT", -18, -5)
      metric:SetJustifyH("RIGHT")
      row.metric = metric

      local gap = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
      gap:SetPoint("TOPRIGHT", -18, -27)
      gap:SetJustifyH("RIGHT")
      gap:SetTextColor(0.64, 0.68, 0.76, 1.00)
      row.gap = gap

      overlay.rankingRows[#overlay.rankingRows + 1] = row
    end
    return overlay.rankingRows
  end

  local function RefreshAwardDetailsOverlay(overlay, award)
    if not overlay then
      return
    end
    local ranking = type(award) == "table" and type(award.ranking) == "table" and award.ranking or {}
    local rankingRows = type(ranking.rows) == "table" and ranking.rows or {}
    local visibleCount = overlay.__showAll and #rankingRows or math.min(10, #rankingRows)
    local showAll = #rankingRows > 10
    local overlayWidth = overlay.GetWidth and tonumber(overlay:GetWidth()) or 900
    local overlayHeight = overlay.GetHeight and tonumber(overlay:GetHeight()) or 640
    local panelWidth = math.min(860, math.max(420, math.floor(overlayWidth - 72)))
    local maxPanelHeight = math.max(226, math.floor(overlayHeight * 0.76))
    local desiredPanelHeight = 152 + (math.max(1, visibleCount) * 50) + (showAll and 34 or 0)
    local panelHeight = math.min(maxPanelHeight, math.max(226, desiredPanelHeight))
    overlay.panel:SetSize(panelWidth, panelHeight)
    local contentWidth = math.max(340, panelWidth - 48)

    overlay.title:SetText(tostring(award and award.title or "Fun Award") .. " Ranking")
    local qualification = trim(ranking.qualification)
    local metricLabel = trim(ranking.metricLabel)
    local rule = trim(ranking.rule)
    overlay.icon:SetTexture(GetAwardStyle(award).art or DEFAULT_AWARD_STYLE.art)
    if overlay.icon.SetDesaturated then
      overlay.icon:SetDesaturated(not (award and award.hasWinner))
    end
    overlay.icon:SetVertexColor(1.00, 1.00, 1.00, award and award.hasWinner and 1.00 or 0.62)
    overlay.meta:SetText((rule ~= "" and rule or (metricLabel ~= "" and metricLabel or "Award result")) .. (qualification ~= "" and (" | " .. qualification) or ""))
    if #rankingRows == 0 then
      overlay.rule:SetText("No player currently qualifies for this award.")
    elseif #rankingRows == 1 then
      overlay.rule:SetText("Only one player currently qualifies for this award.")
    else
      overlay.rule:SetText(tostring(#rankingRows) .. " players currently qualify for this award.")
    end
    overlay.qualifiedBadge.text:SetText(tostring(#rankingRows) .. " qualified")
    overlay.tableHeader:SetText("Rank     Raider")
    overlay.tableMetricHeader:SetText(metricLabel)
    overlay.showAllButton:SetShown(showAll)
    overlay.showAllButton.label:SetText(overlay.__showAll and "Show Top 10" or ("Show All (" .. tostring(#rankingRows) .. ")"))
    overlay.emptyText:SetText(#rankingRows == 0 and ("No player currently qualifies.\n" .. (qualification ~= "" and qualification or "Complete real-session activity to qualify.")) or "")
    overlay.emptyText:SetShown(#rankingRows == 0)
    SetWidgetShown(overlay.separator, #rankingRows > 0)
    SetWidgetShown(overlay.tableHeader, #rankingRows > 0)
    SetWidgetShown(overlay.tableMetricHeader, #rankingRows > 0)
    SetWidgetShown(overlay.scroll, #rankingRows > 0)
    overlay.scroll:ClearAllPoints()
    overlay.scroll:SetPoint("TOPLEFT", overlay.panel, "TOPLEFT", 14, -134)
    overlay.scroll:SetPoint("BOTTOMRIGHT", overlay.panel, "BOTTOMRIGHT", -28, showAll and 42 or 14)

    EnsureAwardRankingRows(overlay, math.max(1, visibleCount))
    for index, row in ipairs(overlay.rankingRows) do
      local source = rankingRows[index]
      if source and index <= visibleCount then
        row:ClearAllPoints()
        row:SetPoint("TOPLEFT", overlay.content, "TOPLEFT", 0, -((index - 1) * 50))
        row:SetSize(contentWidth, 46)
        local leading = tonumber(source.rank) == 1
        row:SetBackdropColor(leading and 0.105 or (index % 2 == 0 and 0.032 or 0.022), leading and 0.084 or (index % 2 == 0 and 0.042 or 0.030), leading and 0.030 or (index % 2 == 0 and 0.060 or 0.046), leading and 0.96 or 0.90)
        row.name:SetWidth(math.max(120, contentWidth - 278))
        row.detail:SetWidth(math.max(120, contentWidth - 278))
        row.rank:SetText(tostring(source.rank or index))
        row.name:SetText(tostring(source.character or "Unknown"))
        row.metric:SetText(tostring(source.metric or "-"))
        row.detail:SetText(tostring(source.detail or ""))
        row.gap:SetText(trim(source.gap) ~= "" and ("Gap " .. tostring(source.gap)) or "")
        row.rankIcon:SetShown(leading)
        row.leaderStripe:SetShown(leading)
        local rankNumber = tonumber(source.rank) or index
        local rankColor = rankNumber == 1 and { 1.00, 0.82, 0.28 } or (rankNumber == 2 and { 0.80, 0.84, 0.92 } or (rankNumber == 3 and { 0.84, 0.58, 0.38 } or { 0.76, 0.80, 0.88 }))
        row.rank:SetTextColor(rankColor[1], rankColor[2], rankColor[3], 1.00)
        row.name:SetTextColor(leading and 1.00 or 0.92, leading and 0.88 or 0.94, leading and 0.54 or 0.98, 1.00)
        row.metric:SetTextColor(leading and 1.00 or 0.82, leading and 0.82 or 0.88, leading and 0.28 or 0.98, 1.00)
        row:Show()
      else
        row:Hide()
      end
    end
    overlay.content:SetSize(contentWidth, math.max(1, visibleCount * 50))
    if overlay.scroll and overlay.scroll.UpdateScrollChildRect then
      overlay.scroll:UpdateScrollChildRect()
    end
  end

  OpenAwardDetailsOverlay = function(frame, award)
    local overlay = EnsureAwardDetailsOverlay(frame)
    if not overlay then
      return
    end
    overlay.__showAll = false
    if overlay.scroll and overlay.scroll.SetVerticalScroll then
      overlay.scroll:SetVerticalScroll(0)
    end
    overlay.__refresh = function()
      RefreshAwardDetailsOverlay(overlay, award)
    end
    overlay.__refresh()
    overlay:Show()
  end

  local function GetGridMetrics(availableWidth, desiredColumns)
    local gap = 16
    local columns = math.max(1, math.floor(tonumber(desiredColumns) or 1))
    local cardWidth = math.min(380, math.floor((availableWidth - ((columns - 1) * gap)) / columns))
    if cardWidth < 250 and columns > 1 then
      return GetGridMetrics(availableWidth, columns - 1)
    end
    local gridWidth = (cardWidth * columns) + ((columns - 1) * gap)
    return columns, cardWidth, gap, math.max(0, math.floor((availableWidth - gridWidth) / 2))
  end

  local function GetColumnCount(availableWidth)
    if availableWidth >= 1550 then
      return 4
    end
    if availableWidth >= 950 then
      return 3
    end
    if availableWidth >= 620 then
      return 2
    end
    return 1
  end

  local function OrderAwards(awards)
    local byKey = {}
    for _, award in ipairs(awards or {}) do
      byKey[trim(type(award) == "table" and award.key or "")] = award
    end
    local featured = {}
    local selected = {}
    for _, key in ipairs(FEATURED_AWARD_KEYS) do
      if byKey[key] then
        featured[#featured + 1] = byKey[key]
        selected[key] = true
      end
    end
    local remaining = {}
    for _, award in ipairs(awards or {}) do
      local key = trim(type(award) == "table" and award.key or "")
      if not selected[key] then
        remaining[#remaining + 1] = award
      end
    end
    return featured, remaining
  end

  local function RefreshAwardCard(card, award, featured, width, height)
    local style = GetAwardStyle(award)
    local accent = style.accent or DEFAULT_AWARD_STYLE.accent
    local hasWinner = award and award.hasWinner == true
    local iconSize = featured and 132 or 88
    local artBoxSize = iconSize + 14
    local metricValue, metricLabel = GetAwardMetricParts(award, style)
    local titleWidth = math.max(120, width - 70)

    card:SetSize(width, height)
    card.__award = award
    card.__style = style
    card.__accent = accent
    card.__hasWinner = hasWinner
    card:SetBackdropColor(hasWinner and 0.025 or 0.018, hasWinner and 0.030 or 0.022, hasWinner and 0.043 or 0.032, 0.98)
    card:SetBackdropBorderColor(accent[1] or 0.66, accent[2] or 0.70, accent[3] or 0.78, hasWinner and 0.74 or 0.48)
    card.topAccent:SetVertexColor(accent[1] or 0.66, accent[2] or 0.70, accent[3] or 0.78, hasWinner and 0.96 or 0.40)
    card.title:SetWidth(titleWidth)
    card.title:SetText(tostring(award and award.title or "Award"))
    card.title:SetTextColor(hasWinner and 0.96 or 0.74, hasWinner and 0.94 or 0.76, hasWinner and 0.90 or 0.82, 1.00)
    card.featured:SetShown(featured and true or false)
    card.artBackground:ClearAllPoints()
    card.artBackground:SetPoint("TOP", card, "TOP", 0, featured and -39 or -35)
    card.artBackground:SetSize(artBoxSize, artBoxSize)
    card.art:SetSize(iconSize, iconSize)
    card.art:SetTexture(style.art or DEFAULT_AWARD_STYLE.art)
    if card.art.SetDesaturated then
      card.art:SetDesaturated(not hasWinner)
    end
    card.art:SetVertexColor(hasWinner and 1.00 or 0.56, hasWinner and 1.00 or 0.56, hasWinner and 1.00 or 0.60, hasWinner and 1.00 or 0.86)
    card.metricValue:ClearAllPoints()
    card.metricValue:SetPoint("TOP", card.artBackground, "BOTTOM", 0, featured and -8 or -4)
    card.metricValue:SetWidth(math.max(120, width - 28))
    if card.metricValue.SetFontObject then
      card.metricValue:SetFontObject(featured and GameFontNormalHuge or GameFontNormalLarge)
    end
    card.metricValue:SetText(metricValue)
    card.metricValue:SetTextColor(hasWinner and (accent[1] or 0.96) or 0.66, hasWinner and (accent[2] or 0.96) or 0.68, hasWinner and (accent[3] or 0.96) or 0.74, 1.00)
    card.metricLabel:ClearAllPoints()
    card.metricLabel:SetPoint("TOP", card.metricValue, "BOTTOM", 0, -2)
    card.metricLabel:SetWidth(math.max(150, width - 28))
    card.metricLabel:SetText(metricLabel)
    card.winner:ClearAllPoints()
    card.winner:SetPoint("BOTTOM", card, "BOTTOM", 0, featured and 34 or 14)
    card.winner:SetWidth(math.max(130, width - 28))
    card.winner:SetText(hasWinner and tostring(award.winner or "Unknown") or "")
    card.winner:SetTextColor(hasWinner and 0.98 or 0.62, hasWinner and 0.88 or 0.65, hasWinner and 0.54 or 0.70, 1.00)
    card.winner:SetShown(hasWinner)
    card.winnerLabel:ClearAllPoints()
    card.winnerLabel:SetPoint("TOP", card.winner, "BOTTOM", 0, -2)
    card.winnerLabel:SetWidth(math.max(150, width - 28))
    card.winnerLabel:SetText("Current winner")
    card.winnerLabel:SetTextColor(hasWinner and 0.66 or 0.54, hasWinner and 0.69 or 0.58, hasWinner and 0.75 or 0.64, 1.00)
    card.winnerLabel:SetShown(featured and hasWinner)
  end

  local function RefreshLootListAwardsView(editor, profileName, width, parent)
    local frame = EnsureAwardsView(editor, parent)
    if not frame then
      return 0
    end

    local viewportWidth = frame.scroll and frame.scroll.GetWidth and tonumber(frame.scroll:GetWidth()) or 0
    local requestedWidth = math.max(360, tonumber(width) or 540)
    local availableWidth = viewportWidth > 0 and math.max(280, math.floor(viewportWidth - 4)) or requestedWidth
    local getAwards = GetAwardsProvider()
    local report = type(getAwards) == "function" and getAwards(profileName) or nil
    local awards = type(report) == "table" and type(report.awards) == "table" and report.awards or {}
    local rankings = type(report) == "table" and type(report.rankings) == "table" and report.rankings or {}
    for _, award in ipairs(awards) do
      if type(award) == "table" then
        award.ranking = rankings[trim(award.key)]
      end
    end
    local featuredAwards, remainingAwards = OrderAwards(awards)
    local totalCards = #featuredAwards + #remainingAwards
    EnsureAwardCards(frame, math.max(1, totalCards))
    local nextCard = 1
    local top = -4
    local columnCount = GetColumnCount(availableWidth)
    local featuredColumns, featuredWidth, featuredGap, featuredLeft = GetGridMetrics(availableWidth, math.min(3, columnCount))
    local featuredHeight = 304
    frame.featuredTitle:ClearAllPoints()
    frame.featuredTitle:SetPoint("TOPLEFT", 4, top)
    SetWidgetShown(frame.featuredTitle, #featuredAwards > 0)
    top = top - 28

    for index, award in ipairs(featuredAwards) do
      local card = frame.awardCards[nextCard]
      local column = (index - 1) % featuredColumns
      local row = math.floor((index - 1) / featuredColumns)
      card:ClearAllPoints()
      card:SetPoint("TOPLEFT", frame.content, "TOPLEFT", featuredLeft + (column * (featuredWidth + featuredGap)), top - (row * (featuredHeight + featuredGap)))
      card.__awardsView = frame
      RefreshAwardCard(card, award, true, featuredWidth, featuredHeight)
      card:Show()
      nextCard = nextCard + 1
    end
    if #featuredAwards > 0 then
      top = top - (math.ceil(#featuredAwards / featuredColumns) * (featuredHeight + featuredGap)) - 14
    end

    local allColumns, allWidth, allGap, allLeft = GetGridMetrics(availableWidth, columnCount)
    local allHeight = 238
    frame.allTitle:ClearAllPoints()
    frame.allTitle:SetPoint("TOPLEFT", 4, top)
    SetWidgetShown(frame.allTitle, #remainingAwards > 0)
    top = top - (#remainingAwards > 0 and 28 or 0)
    for index, award in ipairs(remainingAwards) do
      local card = frame.awardCards[nextCard]
      local column = (index - 1) % allColumns
      local row = math.floor((index - 1) / allColumns)
      card:ClearAllPoints()
      card:SetPoint("TOPLEFT", frame.content, "TOPLEFT", allLeft + (column * (allWidth + allGap)), top - (row * (allHeight + allGap)))
      card.__awardsView = frame
      RefreshAwardCard(card, award, false, allWidth, allHeight)
      card:Show()
      nextCard = nextCard + 1
    end
    for index = nextCard, #(frame.awardCards or {}) do
      frame.awardCards[index]:Hide()
    end

    if totalCards == 0 and frame.awardCards[1] then
      local card = frame.awardCards[1]
      card:ClearAllPoints()
      card:SetPoint("TOPLEFT", frame.content, "TOPLEFT", 4, top)
      RefreshAwardCard(card, {
        title = "Fun Awards unavailable",
        winner = "No award provider found",
        metric = "-",
        detail = "Reload the addon if this stays visible.",
        hasWinner = false,
      }, false, math.min(380, availableWidth), 238)
      card:Show()
      top = top - 254
    elseif #remainingAwards > 0 then
      top = top - (math.ceil(#remainingAwards / allColumns) * (allHeight + allGap))
    end

    local contentHeight = math.max(460, math.abs(top) + 20)
    frame.content:SetSize(availableWidth, contentHeight)
    if frame.scroll and frame.scroll.UpdateScrollChildRect then
      frame.scroll:UpdateScrollChildRect()
    end
    frame:Show()
    return contentHeight
  end

  local function OpenLootListAwardsPopup(editor, profileName)
    if editor and type(editor.ShowLootListContentMode) == "function" then
      editor:ShowLootListContentMode("FUN_AWARDS")
    end
  end

  local function SetLootListAwardsViewShown(editor, shown)
    local frame = editor and editor.lootLedgerAwardsView or nil
    if not shown and frame and frame.awardDetailsOverlay then
      frame.awardDetailsOverlay:Hide()
    end
    SetWidgetShown(frame, shown)
  end

  local function IsLootListAwardsPopupShown(editor)
    local frame = editor and editor.lootLedgerAwardsView or nil
    return frame and frame.IsShown and frame:IsShown() or false
  end

  return {
    OpenLootListAwardsPopup = OpenLootListAwardsPopup,
    RefreshLootListAwardsView = RefreshLootListAwardsView,
    SetLootListAwardsViewShown = SetLootListAwardsViewShown,
    IsLootListAwardsPopupShown = IsLootListAwardsPopupShown,
  }
end
