local EnsureApiRegistry = rawget(_G, "LIDCOUNCIL_EnsureApiRegistry")
local Compat = _G.LIDCOUNCIL_Compat
local API, INTERNAL_API
if type(EnsureApiRegistry) == "function" then
  API, INTERNAL_API = EnsureApiRegistry()
else
  API = rawget(_G, "LIDCOUNCIL_API")
  if type(API) ~= "table" then
    API = {}
    _G.LIDCOUNCIL_API = API
  end
  if type(API.__internal) ~= "table" then
    API.__internal = {}
  end
  INTERNAL_API = API.__internal
end

local function RequireApi(name, value)
  if value == nil then
    value = rawget(_G, name)
  end
  if value == nil then
    local api = rawget(_G, "LIDCOUNCIL_API")
    if type(api) == "table" then
      value = api[name]
    end
  end
  if value == nil then
    error("LidCouncil missing API: " .. tostring(name))
  end
  return value
end

local function ResolveOptionalFunction(name)
  local value = rawget(_G, name)
  if type(value) == "function" then
    return value
  end
  local api = rawget(_G, "LIDCOUNCIL_API")
  if type(api) == "table" and type(api[name]) == "function" then
    return api[name]
  end
  return nil
end

local function PublishApi(name, value, opts)
  API[name] = value
  if type(opts) == "table" and opts.global == false then
    _G[name] = nil
    return
  end
  _G[name] = value
end

local RootDB = RequireApi("LIDCOUNCIL_RootDB", _G.LIDCOUNCIL_RootDB)
local Print = RequireApi("LIDCOUNCIL_Print", _G.LIDCOUNCIL_Print)
local DeepCopy = RequireApi("LIDCOUNCIL_DeepCopy", _G.LIDCOUNCIL_DeepCopy)
local GetCharacterKey = RequireApi("LIDCOUNCIL_GetCharacterKey", _G.LIDCOUNCIL_GetCharacterKey)
local GetLootProfile = RequireApi("LIDCOUNCIL_GetLootProfile", _G.LIDCOUNCIL_GetLootProfile)
local GetActiveLootSession = RequireApi("LIDCOUNCIL_GetActiveLootSession", _G.LIDCOUNCIL_GetActiveLootSession)
local GetLootProfileRole = RequireApi("LIDCOUNCIL_GetLootProfileRole", _G.LIDCOUNCIL_GetLootProfileRole)
local GetLootProfileAccessInfo = RequireApi("LIDCOUNCIL_GetLootProfileAccessInfo", _G.LIDCOUNCIL_GetLootProfileAccessInfo)
local GetLootProfileAccessInfoForRole = RequireApi("LIDCOUNCIL_GetLootProfileAccessInfoForRole", _G.LIDCOUNCIL_GetLootProfileAccessInfoForRole)
local GetEnabledLootProfileName = RequireApi("LIDCOUNCIL_GetEnabledLootProfileName", _G.LIDCOUNCIL_GetEnabledLootProfileName)
local AddLootLedgerEntry = RequireApi("LIDCOUNCIL_AddLootLedgerEntry", _G.LIDCOUNCIL_AddLootLedgerEntry)
local TouchLootProfileDomain = ResolveOptionalFunction("LIDCOUNCIL_TouchLootProfileDomain")
local ResolveLootPointValue = RequireApi("LIDCOUNCIL_ResolveLootPointValue", _G.LIDCOUNCIL_ResolveLootPointValue)
local ApplyFrameSkin = RequireApi("LIDCOUNCIL_ApplyFrameSkin", _G.LIDCOUNCIL_ApplyFrameSkin)

local HasJoinedActiveLootSession = ResolveOptionalFunction("LIDCOUNCIL_HasJoinedActiveLootSession")
local SendSessionComm = ResolveOptionalFunction("LIDCOUNCIL_SendSessionComm")
local NormalizeCharacterKey = ResolveOptionalFunction("LIDCOUNCIL_NormalizeCharacterKey")
local RemoveLootLedgerEntry = ResolveOptionalFunction("LIDCOUNCIL_RemoveLootLedgerEntry")
  or ResolveOptionalFunction("RemoveLootLedgerEntry")
-- Core exposes the ledger reader through the public LidCouncil API. Using the
-- unprefixed name leaves the board without totals, so every optional metric
-- renders as "-" even when the Loot List is populated.
local GetLootLedgerCharacters = ResolveOptionalFunction("LIDCOUNCIL_GetLootLedgerCharacters")
local GetLocalAutoPassEnabled = ResolveOptionalFunction("LIDCOUNCIL_GetLocalAutoPassEnabled")
local ClassifyLootRollItem = ResolveOptionalFunction("LIDCOUNCIL_ClassifyLootRollItem")
local GetLootProfileRevisionSummary = ResolveOptionalFunction("LIDCOUNCIL_GetLootProfileRevisionSummary")
local GetLootProfileId = ResolveOptionalFunction("LIDCOUNCIL_GetLootProfileId")
local GetActiveProfileSyncStatus = ResolveOptionalFunction("LIDCOUNCIL_GetActiveProfileSyncStatus")
local GetLootProfilePermissionPolicyDiagnostics = ResolveOptionalFunction("LIDCOUNCIL_GetLootProfilePermissionPolicyDiagnostics")
local RecordLootRollStat = ResolveOptionalFunction("LIDCOUNCIL_RecordLootRollStat")
local RecordLootVoteStat = ResolveOptionalFunction("LIDCOUNCIL_RecordLootVoteStat")

if type(NormalizeCharacterKey) ~= "function" then
  NormalizeCharacterKey = function(value)
    value = tostring(value or "")
    value = value:gsub("^%s+", ""):gsub("%s+$", "")
    value = value:gsub("%s*%-%s*", "-")
    value = value:gsub("%s+", "")
    return value
  end
end

local DEFAULT_OPTIONS = {
  { key = "need", label = "Need", color = { 0.22, 0.88, 0.32 }, icon = "Interface\\Buttons\\UI-GroupLoot-Dice-Up" },
  { key = "greed", label = "Greed", color = { 0.95, 0.82, 0.22 }, icon = "Interface\\Buttons\\UI-GroupLoot-Coin-Up" },
  { key = "pass", label = "Pass", color = { 0.62, 0.62, 0.62 }, icon = "Interface\\Buttons\\UI-GroupLoot-Pass-Up" },
}
local pendingColor = { 0.72, 0.72, 0.76 }
local CLASS_ICON_TEXTURE = "Interface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES"
local NOTE_ICON_TEXTURE = "Interface\\Buttons\\UI-GuildButton-OfficerNote-Up"
local MAX_SELECTION_NOTE_LENGTH = 120
local SIMULATION_ITEM_COUNT = 10
local REAL_SIMULATION_ITEM_COUNT = 5
local REAL_SIMULATION_ITEM_PREFIX = "TESTSIM-"
local SIMULATION_SAMPLE_MEMBERS = {
  { key = "Tharion-Illidan", name = "Tharion-Illidan", className = "Warrior", classFile = "WARRIOR", specName = "Fury", specIcon = "Interface\\Icons\\Ability_Warrior_InnerRage", note = "Main melee" },
  { key = "Elaris-Area52", name = "Elaris-Area52", className = "Priest", classFile = "PRIEST", specName = "Holy", specIcon = "Interface\\Icons\\Spell_Holy_GuardianSpirit", note = "Healing lead" },
  { key = "Myrddin-Stormrage", name = "Myrddin-Stormrage", className = "Mage", classFile = "MAGE", specName = "Frost", specIcon = "Interface\\Icons\\Spell_Frost_FrostBolt02", note = "Ranged main" },
  { key = "Kaevor-Sargeras", name = "Kaevor-Sargeras", className = "Druid", classFile = "DRUID", specName = "Guardian", specIcon = "Interface\\Icons\\Ability_Racial_BearForm", note = "Tank main" },
  { key = "Rynessa-Tichondrius", name = "Rynessa-Tichondrius", className = "Hunter", classFile = "HUNTER", specName = "Beast Mastery", specIcon = "Interface\\Icons\\Ability_Hunter_BeastTaming", note = "Tharion alt" },
  { key = "Vorlan-Hyjal", name = "Vorlan-Hyjal", className = "Paladin", classFile = "PALADIN", specName = "Retribution", specIcon = "Interface\\Icons\\Spell_Holy_AuraOfLight", note = "Weekend alt" },
  { key = "Serapha-Proudmoore", name = "Serapha-Proudmoore", className = "Shaman", classFile = "SHAMAN", specName = "Restoration", specIcon = "Interface\\Icons\\Spell_Nature_MagicImmunity", note = "Raid healer alt" },
  { key = "Nythera-Dalaran", name = "Nythera-Dalaran", className = "Warlock", classFile = "WARLOCK", specName = "Affliction", specIcon = "Interface\\Icons\\Spell_Shadow_DeathCoil", note = "Caster alt" },
  { key = "Kharos-MalGanis", name = "Kharos-MalGanis", className = "Demon Hunter", classFile = "DEMONHUNTER", specName = "Havoc", specIcon = "Interface\\Icons\\Ability_DemonHunter_SpecDPS", note = "Farm alt" },
  { key = "Talvyr-Stormreaver", name = "Talvyr-Stormreaver", className = "Monk", classFile = "MONK", specName = "Windwalker", specIcon = "Interface\\Icons\\Spell_Monk_WindWalker_Spec", note = "Fast alt" },
}

local runtime = {
  sessionId = nil,
  profileName = nil,
  host = nil,
  boardId = nil,
  boardUpdatedAt = 0,
  historyProfileName = nil,
  itemCounts = {},
  itemOrder = {},
  items = {},
  popupQueue = {},
  pendingChoiceReceipts = {},
  pendingVoteReceipts = {},
  pendingItemReports = {},
  pendingAwardReceipts = {},
  pendingTradeReceipts = {},
  localRollItemKeys = {},
  hostRollItemKeys = {},
  hostReportItemKeys = {},
  selectedItemKey = nil,
  selectedMemberKey = nil,
  lastReceivedOpcode = nil,
  lastReceivedSender = nil,
  lastBoardSyncSender = nil,
  lastBoardSyncReceiver = nil,
  lastItemOpenReceiver = nil,
  itemOpenReceiverReplay = nil,
  lastItemOpenDispatch = nil,
  lastChoicePopupState = nil,
  lastChoiceReceiptRecovery = nil,
  lastChoiceMirrorDispatch = nil,
  lastBoardSyncAdmissionPlan = nil,
  lastBoardSyncAdmissionFailure = nil,
  lastBoardSyncStagedDispatch = nil,
  lastRealSimulationRun = nil,
  pendingRealSimulationItemLoad = nil,
  lastRealSimulationRequestAt = 0,
  realSimulationRequestSequence = 0,
  realSimulationDebouncedRequests = 0,
  lastLiveTransportTest = nil,
}

local function NormalizeRollOptionsList(options)
  if type(options) ~= "table" then
    return nil
  end

  local ordered = {}
  local numericKeys = {}
  for key, value in pairs(options) do
    if type(key) == "number" and type(value) == "table" then
      numericKeys[#numericKeys + 1] = key
    end
  end
  table.sort(numericKeys)

  for _, key in ipairs(numericKeys) do
    local option = options[key]
    if type(option) == "table" then
      ordered[#ordered + 1] = option
    end
  end

  if #ordered == 0 then
    return nil
  end
  return ordered
end

local uiState = {
  boardFrame = nil,
  choicePopup = nil,
  notePopup = nil,
  historyPopup = nil,
  previewState = nil,
  collapsed = false,
}
local MarkAwardOnEntry
local ClearAwardOnEntry
local ResolveDefaultOptionIcon
local PrimeSequence
local GetSelfKey

local CreateLootRuntimeHistoryHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootRuntimeHistoryHelpers_Impl
if type(CreateLootRuntimeHistoryHelpers) ~= "function" then
  error("LidCouncil missing loot runtime history helpers.")
end

local CreateLootRuntimeCommHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootRuntimeCommHelpers_Impl
if type(CreateLootRuntimeCommHelpers) ~= "function" then
  error("LidCouncil missing loot runtime comm helpers.")
end

local CreateLootRuntimeAwardHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootRuntimeAwardHelpers_Impl
if type(CreateLootRuntimeAwardHelpers) ~= "function" then
  error("LidCouncil missing loot runtime award helpers.")
end

local CreateLootRuntimeStateHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootRuntimeStateHelpers_Impl
if type(CreateLootRuntimeStateHelpers) ~= "function" then
  error("LidCouncil missing loot runtime state helpers.")
end

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

local function IsRealSimulationItemKey(itemKey)
  local resolvedKey = TrimText(itemKey)
  return resolvedKey ~= "" and string.sub(resolvedKey, 1, #REAL_SIMULATION_ITEM_PREFIX) == REAL_SIMULATION_ITEM_PREFIX
end

local function ExtractItemID(value)
  if type(value) == "number" then
    return math.floor(value)
  end
  local text = TrimText(value)
  if text == "" then
    return nil
  end
  local direct = tonumber(text)
  if direct then
    return math.floor(direct)
  end
  local linkID = text:match("item:(%d+)")
  if linkID then
    return tonumber(linkID)
  end
  return nil
end

local function NormalizeSelectionNote(value)
  if value == nil or value == false then
    return ""
  end
  local text = tostring(value or "")
  text = text:gsub("[\r\n\t]+", " ")
  text = TrimText(text)
  if #text > MAX_SELECTION_NOTE_LENGTH then
    text = text:sub(1, MAX_SELECTION_NOTE_LENGTH)
  end
  return text
end

local function ExtractItemLinkName(value)
  local text = TrimText(value)
  if text == "" then
    return ""
  end
  local name = text:match("%[(.-)%]")
  return TrimText(name)
end

local function GetFirstDetailedItemLevel(link)
  if type(link) ~= "string" or link == "" then
    return nil
  end
  if type(C_Item) == "table" and type(C_Item.GetDetailedItemLevelInfo) == "function" then
    local ok, itemLevel = pcall(C_Item.GetDetailedItemLevelInfo, link)
    if ok and tonumber(itemLevel) and tonumber(itemLevel) > 0 then
      return tonumber(itemLevel)
    end
  end
  if type(GetDetailedItemLevelInfo) == "function" then
    local ok, itemLevel = pcall(GetDetailedItemLevelInfo, link)
    if ok and tonumber(itemLevel) and tonumber(itemLevel) > 0 then
      return tonumber(itemLevel)
    end
  end
  return nil
end

local function RefreshEditor(opts)
  if type(INTERNAL_API.LIDCOUNCIL_RequestCombatSafeEditorRefresh_Impl) == "function" then
    INTERNAL_API.LIDCOUNCIL_RequestCombatSafeEditorRefresh_Impl(opts)
    return
  end
  local editor = rawget(_G, "LIDCOUNCIL_Editor")
  if editor and editor.__lidCouncilEditor and editor.IsShown and editor:IsShown() then
    local requestWorkflowRefresh = type(editor.RequestWorkflowRefresh) == "function"
      and editor.RequestWorkflowRefresh
      or (type(INTERNAL_API.LIDCOUNCIL_RequestEditorWorkflowRefresh_Impl) == "function"
        and INTERNAL_API.LIDCOUNCIL_RequestEditorWorkflowRefresh_Impl
        or nil)
    if type(requestWorkflowRefresh) == "function" then
      requestWorkflowRefresh(editor, opts)
    elseif editor.Refresh then
      editor:Refresh()
    end
  end
end

local function ColorToHex(color)
  local r = math.floor(math.max(0, math.min(1, tonumber(color and color[1]) or 1)) * 255 + 0.5)
  local g = math.floor(math.max(0, math.min(1, tonumber(color and color[2]) or 1)) * 255 + 0.5)
  local b = math.floor(math.max(0, math.min(1, tonumber(color and color[3]) or 1)) * 255 + 0.5)
  return string.format("%02x%02x%02x", r, g, b)
end

local function WrapColor(text, color)
  return "|cff" .. ColorToHex(color) .. tostring(text or "") .. "|r"
end

local function ResolveOptionIconTexture(icon, optionKey, label)
  if type(icon) == "number" then
    return icon
  end
  local text = TrimText(icon)
  if text ~= "" then
    local numeric = tonumber(text)
    if numeric then
      return numeric
    end
    return text
  end
  return ResolveDefaultOptionIcon(optionKey, label)
end

local function BuildSelectionState(optionKey, label, color, rollValue, icon, note, pointBehavior)
  return {
    optionKey = TrimText(optionKey or label),
    label = TrimText(label or optionKey),
    color = DeepCopy(color or { 0.82, 0.82, 0.86 }),
    icon = ResolveOptionIconTexture(icon, optionKey, label),
    note = NormalizeSelectionNote(note),
    rollValue = tonumber(rollValue),
    pointBehavior = TrimText(pointBehavior),
  }
end

ResolveDefaultOptionIcon = function(optionKey, label)
  local text = string.lower(TrimText(optionKey ~= "" and optionKey or label))
  if text == "need" then
    return "Interface\\Buttons\\UI-GroupLoot-Dice-Up"
  elseif text == "greed" then
    return "Interface\\Buttons\\UI-GroupLoot-Coin-Up"
  elseif text == "pass" then
    return "Interface\\Buttons\\UI-GroupLoot-Pass-Up"
  elseif text == "disenchant" then
    return "Interface\\Icons\\inv_enchant_disenchant"
  end
  return nil
end

local function BuildPendingSelection()
  return BuildSelectionState("pending", "Pending", pendingColor, nil, nil, nil, "NONE")
end

local function ResolveSimulationSourceProfileName(sourceProfileName)
  local root = RootDB()
  local requestedName = TrimText(sourceProfileName)
  if requestedName == "Simulation" and root.profiles and root.profiles.Simulation then
    return "Simulation"
  end
  if requestedName ~= "" and requestedName ~= "Simulation" and root.profiles and root.profiles[requestedName] then
    return requestedName
  end

  local fallbackName = TrimText(root.ui and root.ui.lastNonSimulationProfile or "")
  if fallbackName ~= "" and fallbackName ~= "Simulation" and root.profiles and root.profiles[fallbackName] then
    return fallbackName
  end

  local activeSession, activeProfileName = GetActiveLootSession()
  if activeSession and TrimText(activeProfileName) ~= "" and activeProfileName ~= "Simulation" and root.profiles and root.profiles[activeProfileName] then
    return TrimText(activeProfileName)
  end

  if type(root.profiles) == "table" then
    for profileName in pairs(root.profiles) do
      local resolvedName = TrimText(profileName)
      if resolvedName ~= "" and resolvedName ~= "Simulation" and resolvedName ~= "Default" then
        return resolvedName
      end
    end
  end

  if root.profiles and root.profiles.Default then
    return "Default"
  end
  return requestedName ~= "" and requestedName or "Default"
end

local function EnsureSimulationProfile(sourceProfileName)
  local root = RootDB()
  local resolvedSourceName = ResolveSimulationSourceProfileName(sourceProfileName)
  local _, resolvedSourceProfileName = GetLootProfile(resolvedSourceName)
  local storedSimulationProfile = type(root.profiles) == "table" and root.profiles.Simulation or nil
  if type(storedSimulationProfile) ~= "table" then
    return nil, nil, resolvedSourceProfileName, "Simulation profile not found. Create it in Developer Mode first."
  end
  local simulationProfile, simulationProfileName = GetLootProfile("Simulation")
  local simulationEnabled = simulationProfile
    and simulationProfile.settings
    and simulationProfile.settings.enabled
    and true or false

  simulationProfile.settings = type(simulationProfile.settings) == "table" and simulationProfile.settings or {}
  if resolvedSourceProfileName ~= "Simulation" then
    simulationProfile.__lastSimulationSourceProfileName = resolvedSourceProfileName
  end
  simulationProfile.settings = simulationProfile.settings or {}
  simulationProfile.settings.enabled = simulationEnabled
  simulationProfile.meta = simulationProfile.meta or {}

  return simulationProfile, simulationProfileName, resolvedSourceProfileName, nil
end

local function NextLiveBoardId()
  local root = RootDB()
  root.liveBoardSerial = math.max(0, tonumber(root.liveBoardSerial) or 0) + 1
  return "board-" .. tostring(root.liveBoardSerial)
end

local lootRuntimeHistoryHelpers = CreateLootRuntimeHistoryHelpers({
  RootDB = RootDB,
  DeepCopy = DeepCopy,
  GetCharacterKey = GetCharacterKey,
  GetLootProfile = GetLootProfile,
  TrimText = TrimText,
  ExtractItemID = ExtractItemID,
  NormalizeSelectionNote = NormalizeSelectionNote,
  NormalizeCharacterKey = NormalizeCharacterKey,
  NextLiveBoardId = NextLiveBoardId,
  TouchLootProfileDomain = TouchLootProfileDomain,
  GetLootProfileDomainRevision = ResolveOptionalFunction("LIDCOUNCIL_GetLootProfileDomainRevision"),
  runtime = runtime,
  uiState = uiState,
  ResolveSelfKey = function()
    if type(GetSelfKey) == "function" then
      return GetSelfKey()
    end
    return ""
  end,
  PrimeSequenceItemKey = function(itemKey)
    if type(PrimeSequence) == "function" then
      PrimeSequence(itemKey)
    end
  end,
})

local EnsureRuntimeBoardContext = lootRuntimeHistoryHelpers.EnsureRuntimeBoardContext
local EnsurePreviewBoardContext = lootRuntimeHistoryHelpers.EnsurePreviewBoardContext
local NormalizeEntryVotes = lootRuntimeHistoryHelpers.NormalizeEntryVotes
local GetEntryVoteTargetForVoter = lootRuntimeHistoryHelpers.GetEntryVoteTargetForVoter
local SetEntryVoteTarget = lootRuntimeHistoryHelpers.SetEntryVoteTarget
local GetEntryVoteVoterKeys = lootRuntimeHistoryHelpers.GetEntryVoteVoterKeys
local GetEntryVoteCount = lootRuntimeHistoryHelpers.GetEntryVoteCount
local NormalizeVoteSequence = lootRuntimeHistoryHelpers.NormalizeVoteSequence
local BuildRuntimeBoardHistorySnapshot = lootRuntimeHistoryHelpers.BuildRuntimeBoardHistorySnapshot
local PersistRuntimeBoardHistory = lootRuntimeHistoryHelpers.PersistRuntimeBoardHistory
local GetLatestRuntimeBoardSnapshot = lootRuntimeHistoryHelpers.GetLatestRuntimeBoardSnapshot
local RestoreRuntimeBoardSnapshot = lootRuntimeHistoryHelpers.RestoreRuntimeBoardSnapshot
local BuildPreviewBoardHistorySnapshot = lootRuntimeHistoryHelpers.BuildPreviewBoardHistorySnapshot
local PersistPreviewBoardHistory = lootRuntimeHistoryHelpers.PersistPreviewBoardHistory
local GetLiveBoardHistoryEntries = lootRuntimeHistoryHelpers.GetLiveBoardHistoryEntries
local GetLiveBoardHistoryPage = lootRuntimeHistoryHelpers.GetLiveBoardHistoryPage
local GetLiveBoardHistorySnapshot = lootRuntimeHistoryHelpers.GetLiveBoardHistorySnapshot
local RestoreLatestPreviewBoardState = lootRuntimeHistoryHelpers.RestoreLatestPreviewBoardState

local lootRuntimeStateHelpers = CreateLootRuntimeStateHelpers({
  RootDB = RootDB,
  GetCharacterKey = GetCharacterKey,
  GetLootProfile = GetLootProfile,
  GetActiveLootSession = GetActiveLootSession,
  HasJoinedActiveLootSession = HasJoinedActiveLootSession,
  NormalizeCharacterKey = NormalizeCharacterKey,
  DEFAULT_OPTIONS = DEFAULT_OPTIONS,
  CLASS_ICON_TEXTURE = CLASS_ICON_TEXTURE,
  runtime = runtime,
  uiState = uiState,
  TrimText = TrimText,
  ExtractItemID = ExtractItemID,
  RefreshEditor = RefreshEditor,
  ResolveOptionIconTexture = ResolveOptionIconTexture,
  NormalizeRollOptionsList = NormalizeRollOptionsList,
  EnsureRuntimeBoardContext = EnsureRuntimeBoardContext,
  GetLatestRuntimeBoardSnapshot = GetLatestRuntimeBoardSnapshot,
  RestoreRuntimeBoardSnapshot = RestoreRuntimeBoardSnapshot,
  PersistRuntimeBoardHistory = PersistRuntimeBoardHistory,
  NormalizeEntryVotes = NormalizeEntryVotes,
  ResolveDefaultOptionIcon = ResolveDefaultOptionIcon,
})

local ClearRuntimeState = lootRuntimeStateHelpers.ClearRuntimeState
local ClearRuntimeAndRefresh = lootRuntimeStateHelpers.ClearRuntimeAndRefresh
local EnsureRuntimeSession = lootRuntimeStateHelpers.EnsureRuntimeSession
local ResolveRollOptions = lootRuntimeStateHelpers.ResolveRollOptions
local ResolveRollOption = lootRuntimeStateHelpers.ResolveRollOption
GetSelfKey = lootRuntimeStateHelpers.GetSelfKey
local NormalizeRealmName = lootRuntimeStateHelpers.NormalizeRealmName
local GetLocalRealmName = lootRuntimeStateHelpers.GetLocalRealmName
local BuildNormalizedCharacterKey = lootRuntimeStateHelpers.BuildNormalizedCharacterKey
local ResolveSessionUnit = lootRuntimeStateHelpers.ResolveSessionUnit
local ResolveStoredMemberIconData = lootRuntimeStateHelpers.ResolveStoredMemberIconData
local ResolveMemberIconData = lootRuntimeStateHelpers.ResolveMemberIconData
local BuildInlineIconTag = lootRuntimeStateHelpers.BuildInlineIconTag
local BuildMemberDisplayText = lootRuntimeStateHelpers.BuildMemberDisplayText
local IsSelfHost = lootRuntimeStateHelpers.IsSelfHost
local GetJoinedSessionState = lootRuntimeStateHelpers.GetJoinedSessionState
local GetBroadcastDistribution = lootRuntimeStateHelpers.GetBroadcastDistribution
local ParseItemSequence = lootRuntimeStateHelpers.ParseItemSequence
PrimeSequence = lootRuntimeStateHelpers.PrimeSequence
local NextItemKey = lootRuntimeStateHelpers.NextItemKey
local QueueContains = lootRuntimeStateHelpers.QueueContains
local EnsureLiveEntry = lootRuntimeStateHelpers.EnsureLiveEntry
local GetTrackedItemCount = lootRuntimeStateHelpers.GetTrackedItemCount
local BuildPreviewSummary = lootRuntimeStateHelpers.BuildPreviewSummary
local GetLiveLootBoardSummary = lootRuntimeStateHelpers.GetLiveLootBoardSummary

local function GetLiveLootRuntimeDiagnostics()
  local root = RootDB()
  local ui = type(root) == "table" and type(root.ui) == "table" and root.ui or {}
  local activeSession, activeProfileName = GetActiveLootSession()
  local preview = uiState.previewState or (uiState.boardFrame and uiState.boardFrame.__previewState)
  local summary = GetLiveLootBoardSummary()
  local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
  local joinedMemberCount = 0
  local diagnosticsProfileName = TrimText(activeProfileName)
  if diagnosticsProfileName == "" then
    diagnosticsProfileName = TrimText(type(root) == "table" and root.currentProfile or "")
  end

  if type(activeSession) == "table" then
    if TrimText(activeSession.host) ~= "" then
      joinedMemberCount = joinedMemberCount + 1
    end
    for memberKey, member in pairs(activeSession.members or {}) do
      if NormalizeCharacterKey(memberKey) ~= NormalizeCharacterKey(activeSession.host) and tostring(type(member) == "table" and member.status or "JOINED") == "JOINED" then
        joinedMemberCount = joinedMemberCount + 1
      end
    end
  end

  local localRole = ""
  if diagnosticsProfileName ~= "" and selfKey ~= "" then
    localRole = TrimText(GetLootProfileRole(diagnosticsProfileName, selfKey))
  end

  local boardMode = "none"
  local boardId = TrimText(runtime.boardId)
  local selectedItemKey = TrimText(runtime.selectedItemKey)
  if type(preview) == "table" then
    boardMode = preview.isSimulation and "simulation" or "preview"
    boardId = TrimText(preview.boardId)
    selectedItemKey = TrimText(preview.selectedItemKey)
  elseif TrimText(runtime.sessionId) ~= "" and #runtime.itemOrder > 0 then
    boardMode = "live"
  end

  local revisionSummary = nil
  if diagnosticsProfileName ~= "" and type(GetLootProfileRevisionSummary) == "function" then
    local resolvedRevisionSummary = GetLootProfileRevisionSummary(diagnosticsProfileName)
    if type(resolvedRevisionSummary) == "table" then
      revisionSummary = resolvedRevisionSummary
    end
  end
  local sharedProfileSyncStatus = type(GetActiveProfileSyncStatus) == "function" and GetActiveProfileSyncStatus() or nil
  local permissionPolicyDiagnostics = diagnosticsProfileName ~= ""
    and type(GetLootProfilePermissionPolicyDiagnostics) == "function"
    and GetLootProfilePermissionPolicyDiagnostics(diagnosticsProfileName)
    or nil
  local localAccess = diagnosticsProfileName ~= "" and GetLootProfileAccessInfo(diagnosticsProfileName, selfKey) or nil
  local localAccessSummaryParts = {}
  if type(localAccess) == "table" then
    if localAccess.canEditRaidSettings then
      localAccessSummaryParts[#localAccessSummaryParts + 1] = "Raid"
    end
    if localAccess.canEditRollSettings then
      localAccessSummaryParts[#localAccessSummaryParts + 1] = "Roll"
    end
    if localAccess.canEditPointSettings then
      localAccessSummaryParts[#localAccessSummaryParts + 1] = "Point"
    end
    if localAccess.canManageSession then
      localAccessSummaryParts[#localAccessSummaryParts + 1] = "Session"
    end
    if localAccess.canOpenLiveBoard then
      localAccessSummaryParts[#localAccessSummaryParts + 1] = "LiveBoard"
    end
    if localAccess.canEditLootList then
      localAccessSummaryParts[#localAccessSummaryParts + 1] = "LootList"
    end
  end
  local syncCounts = type(sharedProfileSyncStatus) == "table" and type(sharedProfileSyncStatus.candidateCounts) == "table"
    and sharedProfileSyncStatus.candidateCounts
    or {}
  local activeSessionId = TrimText(type(activeSession) == "table" and activeSession.id or "")
  local criticalReceipts = {
    waiting = 0,
    unconfirmed = 0,
    details = {},
    lastConfirmed = nil,
  }
  local lastConfirmedAt = 0

  local function AddPendingCriticalReceipts(receipts, kind, targetField, defaultTarget)
    if type(receipts) ~= "table" or activeSessionId == "" then
      return
    end
    for _, receipt in pairs(receipts) do
      if type(receipt) == "table" and TrimText(receipt.sessionId) == activeSessionId then
        local state = string.lower(TrimText(receipt.state))
        if state == "waiting" or state == "queue_grace" or state == "unconfirmed" then
          if state == "waiting" or state == "queue_grace" then
            criticalReceipts.waiting = criticalReceipts.waiting + 1
          else
            criticalReceipts.unconfirmed = criticalReceipts.unconfirmed + 1
          end
          if #criticalReceipts.details < 3 then
            local target = targetField ~= "" and TrimText(receipt[targetField]) or ""
            criticalReceipts.details[#criticalReceipts.details + 1] = {
              kind = kind,
              state = state,
              target = target ~= "" and target or defaultTarget,
              itemKey = TrimText(receipt.itemKey),
              attempts = math.max(0, tonumber(receipt.attempts) or 0),
            }
          end
        end
      end
    end
  end

  local function ReadConfirmedCriticalReceipt(kind, receipt, targetField, defaultTarget)
    if type(receipt) ~= "table" or TrimText(receipt.sessionId) ~= activeSessionId then
      return
    end
    local state = string.lower(TrimText(receipt.state))
    if state ~= "" and state ~= "confirmed" then
      return
    end
    local confirmedAt = math.max(0, tonumber(receipt.confirmedAt or receipt.changedAt or receipt.selectedAt) or 0)
    if confirmedAt < lastConfirmedAt then
      return
    end
    lastConfirmedAt = confirmedAt
    local target = targetField ~= "" and TrimText(receipt[targetField]) or ""
    criticalReceipts.lastConfirmed = {
      kind = kind,
      target = target ~= "" and target or defaultTarget,
      itemKey = TrimText(receipt.itemKey),
      attempts = math.max(0, tonumber(receipt.attempts) or 0),
    }
  end

  local sessionHost = TrimText(type(activeSession) == "table" and activeSession.host or "Host")
  AddPendingCriticalReceipts(runtime.pendingChoiceReceipts, "Choice", "host", sessionHost)
  AddPendingCriticalReceipts(runtime.pendingVoteReceipts, "Vote", "host", sessionHost)
  AddPendingCriticalReceipts(runtime.pendingItemReports, "Item Report", "host", sessionHost)
  AddPendingCriticalReceipts(runtime.pendingAwardReceipts, "Award", "memberKey", "Recipient")
  AddPendingCriticalReceipts(runtime.pendingTradeReceipts, "Trade State", "memberKey", "Recipient")
  ReadConfirmedCriticalReceipt("Choice", runtime.lastChoiceReceipt, "", sessionHost)
  ReadConfirmedCriticalReceipt("Vote", runtime.lastVoteReceipt, "", sessionHost)
  ReadConfirmedCriticalReceipt("Item Report", runtime.lastItemReportReceipt, "", sessionHost)
  ReadConfirmedCriticalReceipt("Award", runtime.lastAwardReceipt, "memberKey", "Recipient")
  ReadConfirmedCriticalReceipt("Trade State", runtime.lastTradeReceipt, "memberKey", "Recipient")
  local itemDispatch = type(runtime.lastItemOpenDispatch) == "table" and runtime.lastItemOpenDispatch or nil
  if type(itemDispatch) == "table" and TrimText(itemDispatch.sessionId) == activeSessionId then
    for _, target in pairs(type(itemDispatch.targets) == "table" and itemDispatch.targets or {}) do
      local state = string.lower(TrimText(type(target) == "table" and target.state or "pending"))
      if state == "pending" then
        criticalReceipts.waiting = criticalReceipts.waiting + 1
      elseif state == "failed" then
        criticalReceipts.unconfirmed = criticalReceipts.unconfirmed + 1
      end
      if state ~= "acknowledged" and #criticalReceipts.details < 3 then
        criticalReceipts.details[#criticalReceipts.details + 1] = {
          kind = "Item Delivery",
          state = state == "failed" and "unconfirmed" or "waiting",
          target = TrimText(target.targetKey),
          itemKey = TrimText(itemDispatch.itemKey),
          attempts = math.max(0, tonumber(target.attempts) or 0),
        }
      end
    end
  end
  local choiceMirrorDispatch = type(runtime.lastChoiceMirrorDispatch) == "table"
    and runtime.lastChoiceMirrorDispatch
    or nil
  if type(choiceMirrorDispatch) == "table" and TrimText(choiceMirrorDispatch.sessionId) == activeSessionId then
    for _, target in pairs(type(choiceMirrorDispatch.targets) == "table" and choiceMirrorDispatch.targets or {}) do
      local state = string.lower(TrimText(type(target) == "table" and target.state or "pending"))
      if state == "pending" then
        criticalReceipts.waiting = criticalReceipts.waiting + 1
      elseif state == "failed" then
        criticalReceipts.unconfirmed = criticalReceipts.unconfirmed + 1
      end
      if state ~= "acknowledged" and #criticalReceipts.details < 3 then
        criticalReceipts.details[#criticalReceipts.details + 1] = {
          kind = "Council Choice Mirror",
          state = state == "failed" and "unconfirmed" or "waiting",
          target = TrimText(target.targetKey),
          itemKey = TrimText(choiceMirrorDispatch.itemKey),
          attempts = math.max(0, tonumber(target.attempts) or 0),
        }
      end
    end
  end

  return {
    schemaVersion = tonumber(type(root) == "table" and root.__schemaVersion) or 0,
    currentProfile = TrimText(type(root) == "table" and root.currentProfile or ""),
    enabledProfile = TrimText(GetEnabledLootProfileName()),
    activeProfileId = diagnosticsProfileName ~= "" and type(GetLootProfileId) == "function" and TrimText(select(1, GetLootProfileId(diagnosticsProfileName)) or "") or "",
    settingsRevision = tonumber(type(revisionSummary) == "table" and revisionSummary.settings) or 0,
    permissionsRevision = tonumber(type(revisionSummary) == "table" and revisionSummary.permissions) or 0,
    operationalRevision = tonumber(type(revisionSummary) == "table" and revisionSummary.operational) or 0,
    activeSessionId = TrimText(type(activeSession) == "table" and activeSession.id or ""),
    sessionHost = TrimText(type(activeSession) == "table" and activeSession.host or ""),
    isSessionHost = type(activeSession) == "table" and IsSelfHost(activeSession) == true or false,
    localRole = localRole,
    localAccessSummary = table.concat(localAccessSummaryParts, ", "),
    boardMode = boardMode,
    boardId = boardId,
    selectedItemKey = selectedItemKey,
    joinedMemberCount = joinedMemberCount,
    itemCount = tonumber(summary and summary.itemCount) or 0,
    pendingChoices = tonumber(summary and summary.pendingChoices) or 0,
    unassignedItems = tonumber(summary and summary.unassignedItems) or 0,
    lastBoardSyncSender = TrimText(runtime.lastBoardSyncSender),
    boardSyncReceiver = DeepCopy(type(runtime.lastBoardSyncReceiver) == "table" and runtime.lastBoardSyncReceiver or {}),
    itemOpenReceiver = DeepCopy(type(runtime.lastItemOpenReceiver) == "table" and runtime.lastItemOpenReceiver or {}),
    itemOpenDispatch = DeepCopy(type(runtime.lastItemOpenDispatch) == "table" and runtime.lastItemOpenDispatch or {}),
    choicePopupState = DeepCopy(type(runtime.lastChoicePopupState) == "table" and runtime.lastChoicePopupState or {}),
    choiceReceiptRecovery = DeepCopy(type(runtime.lastChoiceReceiptRecovery) == "table"
      and runtime.lastChoiceReceiptRecovery or {}),
    choiceMirrorDispatch = DeepCopy(type(runtime.lastChoiceMirrorDispatch) == "table"
      and runtime.lastChoiceMirrorDispatch or {}),
    boardSyncAdmissionPlan = DeepCopy(type(runtime.lastBoardSyncAdmissionPlan) == "table"
      and runtime.lastBoardSyncAdmissionPlan or {}),
    boardSyncStagedDispatch = DeepCopy(type(runtime.lastBoardSyncStagedDispatch) == "table"
      and runtime.lastBoardSyncStagedDispatch or {}),
    lastOpcode = TrimText(runtime.lastReceivedOpcode),
    lastSender = TrimText(runtime.lastReceivedSender),
    criticalReceipts = criticalReceipts,
    realSimulation = DeepCopy(type(runtime.lastRealSimulationRun) == "table" and runtime.lastRealSimulationRun or {}),
    liveTransportTest = DeepCopy(type(runtime.lastLiveTransportTest) == "table" and runtime.lastLiveTransportTest or {}),
    sharedProfileSyncMode = TrimText(type(sharedProfileSyncStatus) == "table" and sharedProfileSyncStatus.mode or ""),
    sharedProfileSyncSeverity = TrimText(type(sharedProfileSyncStatus) == "table" and sharedProfileSyncStatus.severity or ""),
    sharedProfileSyncMessage = TrimText(type(sharedProfileSyncStatus) == "table" and sharedProfileSyncStatus.message or ""),
    sharedProfileSyncSender = TrimText(type(sharedProfileSyncStatus) == "table" and sharedProfileSyncStatus.sender or ""),
    sharedProfileSyncUpdatedAt = tonumber(type(sharedProfileSyncStatus) == "table" and sharedProfileSyncStatus.updatedAt) or 0,
    sharedProfileSyncRemoteDomains = type(sharedProfileSyncStatus) == "table" and table.concat(sharedProfileSyncStatus.remoteDomains or {}, ", ") or "",
    sharedProfileSyncLocalDomains = type(sharedProfileSyncStatus) == "table" and table.concat(sharedProfileSyncStatus.localDomains or {}, ", ") or "",
    sharedProfileSyncRemoteNewerCount = tonumber(syncCounts.remote_newer) or 0,
    sharedProfileSyncDivergedCount = tonumber(syncCounts.diverged) or 0,
    sharedProfileSyncLocalNewerCount = tonumber(syncCounts.local_newer) or 0,
    sharedProfileSyncSameCount = tonumber(syncCounts.same) or 0,
    permissionPolicyVersion = tonumber(type(permissionPolicyDiagnostics) == "table" and permissionPolicyDiagnostics.version) or 0,
    permissionPolicyHasOverrides = type(permissionPolicyDiagnostics) == "table" and permissionPolicyDiagnostics.hasOverrides == true or false,
    permissionPolicyCouncilOverrideCount = tonumber(type(permissionPolicyDiagnostics) == "table" and permissionPolicyDiagnostics.councilOverrideCount) or 0,
    permissionPolicySessionHostOverrideCount = tonumber(type(permissionPolicyDiagnostics) == "table" and permissionPolicyDiagnostics.sessionHostOverrideCount) or 0,
    permissionPolicyRaiderOverrideCount = tonumber(type(permissionPolicyDiagnostics) == "table" and permissionPolicyDiagnostics.raiderOverrideCount) or 0,
    permissionPolicyCouncilOverrides = type(permissionPolicyDiagnostics) == "table" and table.concat(permissionPolicyDiagnostics.councilOverrides or {}, ", ") or "",
    permissionPolicySessionHostOverrides = type(permissionPolicyDiagnostics) == "table" and table.concat(permissionPolicyDiagnostics.sessionHostOverrides or {}, ", ") or "",
    permissionPolicyRaiderOverrides = type(permissionPolicyDiagnostics) == "table" and table.concat(permissionPolicyDiagnostics.raiderOverrides or {}, ", ") or "",
    developerMode = ui.developerMode == true,
  }
end

local function GetSimulationImpl()
  local impl = INTERNAL_API.LIDCOUNCIL_LootRuntimeSimulation_Impl
  if type(impl) ~= "table" then
    error("LidCouncil missing loot runtime simulation implementation.")
  end
  return impl
end

local function CallSimulationFunction(name, ...)
  local fn = GetSimulationImpl()[name]
  if type(fn) ~= "function" then
    error("LidCouncil missing loot runtime simulation function: " .. tostring(name))
  end
  return fn(...)
end

local function GetSelectionPriority(selection)
  return CallSimulationFunction("GetSelectionPriority", selection)
end

local function GetSelectionRollValue(selection)
  return CallSimulationFunction("GetSelectionRollValue", selection)
end

local function FormatSelectionLabel(selection)
  return CallSimulationFunction("FormatSelectionLabel", selection)
end

local function BuildRealSimulationItemDefs(profileName, count)
  return CallSimulationFunction("BuildRealSimulationItemDefs", profileName, count)
end
local lootRuntimeAwardHelpers = CreateLootRuntimeAwardHelpers({
  Print = Print,
  DeepCopy = DeepCopy,
  GetLootLedgerCharacters = GetLootLedgerCharacters,
  AddLootLedgerEntry = AddLootLedgerEntry,
  ResolveLootAwardOutcome = ResolveLootAwardOutcome,
  RemoveLootLedgerEntry = RemoveLootLedgerEntry,
  TrimText = TrimText,
  NormalizeSelectionNote = NormalizeSelectionNote,
  ResolveOptionIconTexture = ResolveOptionIconTexture,
  PersistRuntimeBoardHistory = PersistRuntimeBoardHistory,
  GetActiveLootSession = GetActiveLootSession,
  EnsureRuntimeSession = EnsureRuntimeSession,
  EnsureLiveEntry = EnsureLiveEntry,
  NormalizeCharacterKey = NormalizeCharacterKey,
  ResolveRollOptions = ResolveRollOptions,
  GetSelectionRollValue = GetSelectionRollValue,
  IsRealSimulationItemKey = IsRealSimulationItemKey,
  IsSelfHost = IsSelfHost,
  RecordLootRollStat = RecordLootRollStat,
  RefreshEditor = RefreshEditor,
  runtime = runtime,
  uiState = uiState,
})

local ResolveLootLedgerTotals = lootRuntimeAwardHelpers.ResolveLootLedgerTotals
local GetAwardCandidateRows = lootRuntimeAwardHelpers.GetAwardCandidateRows
local EnsureSelectedMember = lootRuntimeAwardHelpers.EnsureSelectedMember
local CycleSelectedMember = lootRuntimeAwardHelpers.CycleSelectedMember
local BuildAwardNote = lootRuntimeAwardHelpers.BuildAwardNote
MarkAwardOnEntry = lootRuntimeAwardHelpers.MarkAwardOnEntry
ClearAwardOnEntry = lootRuntimeAwardHelpers.ClearAwardOnEntry
local RemoveAwardFromEntry = lootRuntimeAwardHelpers.RemoveAwardFromEntry
local ApplyAwardMessage = lootRuntimeAwardHelpers.ApplyAwardMessage
local ShouldDeferRuntimeUiRefresh = lootRuntimeAwardHelpers.ShouldDeferRuntimeUiRefresh
local QueueDeferredRuntimeUiRefresh = lootRuntimeAwardHelpers.QueueDeferredRuntimeUiRefresh
local FlushDeferredRuntimeUiRefresh = lootRuntimeAwardHelpers.FlushDeferredRuntimeUiRefresh
local RefreshBoardAndEditor = lootRuntimeAwardHelpers.RefreshBoardAndEditor
local RecordChoice = lootRuntimeAwardHelpers.RecordChoice

local lootListData = type(INTERNAL_API.LIDCOUNCIL_LootListData_Impl) == "table"
  and INTERNAL_API.LIDCOUNCIL_LootListData_Impl
  or {}

local lootRuntimeCommHelpers = CreateLootRuntimeCommHelpers({
  Print = Print,
  DeepCopy = DeepCopy,
  TrimText = TrimText,
  ExtractItemID = ExtractItemID,
  NormalizeSelectionNote = NormalizeSelectionNote,
  NormalizeCharacterKey = NormalizeCharacterKey,
  GetActiveLootSession = GetActiveLootSession,
  GetLootProfile = GetLootProfile,
  GetLootProfileRole = GetLootProfileRole,
  GetLootProfileAccessInfo = GetLootProfileAccessInfo,
  IsSelfHost = IsSelfHost,
  EnsureRuntimeSession = EnsureRuntimeSession,
  ResolveRollOption = ResolveRollOption,
  ResolveRollOptions = ResolveRollOptions,
  EnsureLiveEntry = EnsureLiveEntry,
  NextItemKey = NextItemKey,
  QueueContains = QueueContains,
  GetBroadcastDistribution = GetBroadcastDistribution,
  SendSessionComm = SendSessionComm,
  GetSessionCommQueueStatus = ResolveOptionalFunction("LIDCOUNCIL_GetSessionCommQueueStatus"),
  ValidateCommPayload = INTERNAL_API.LIDCOUNCIL_ValidateCommPayload_Impl,
  RefreshBoardAndEditor = RefreshBoardAndEditor,
  RecordChoice = RecordChoice,
  RecordLootVoteStat = RecordLootVoteStat,
  IsRealSimulationItemKey = IsRealSimulationItemKey,
  ClassifyLootRollItem = ClassifyLootRollItem,
  AddLootLedgerEntry = AddLootLedgerEntry,
  RemoveLootLedgerEntry = RemoveLootLedgerEntry,
  NormalizeLootLedgerRoleLocal = lootListData.NormalizeLootLedgerRoleLocal,
  SetLootLedgerMainAltRole = lootListData.SetLootLedgerMainAltRole,
  SetLootLedgerCharacterNote = lootListData.SetLootLedgerCharacterNote,
  SetLootLedgerMainCharacter = lootListData.SetLootLedgerMainCharacter,
  ClearLootLedgerMainCharacter = lootListData.ClearLootLedgerMainCharacter,
  DeleteLootLedgerCharacter = lootListData.DeleteLootLedgerCharacter,
  BuildLootLedgerNavRows = lootListData.BuildLootLedgerNavRows,
  ApplyAwardMessage = ApplyAwardMessage,
  RemoveAwardFromEntry = RemoveAwardFromEntry,
  NormalizeEntryVotes = NormalizeEntryVotes,
  NormalizeVoteSequence = NormalizeVoteSequence,
  SetEntryVoteTarget = SetEntryVoteTarget,
  PersistRuntimeBoardHistory = PersistRuntimeBoardHistory,
  BuildRuntimeBoardHistorySnapshot = BuildRuntimeBoardHistorySnapshot,
  GetLatestRuntimeBoardSnapshot = GetLatestRuntimeBoardSnapshot,
  RestoreRuntimeBoardSnapshot = RestoreRuntimeBoardSnapshot,
  GetSelfKey = GetSelfKey,
  PrimeSequence = PrimeSequence,
  ClearPreviewState = function()
    uiState.previewState = nil
    if uiState.boardFrame then
      uiState.boardFrame.__previewState = nil
    end
  end,
  RefreshChoicePopup = function(...)
    local fn = INTERNAL_API.LIDCOUNCIL_RefreshChoicePopup_Impl
    if type(fn) == "function" then
      return fn(...)
    end
  end,
  RearmUnconfirmedChoiceReceipts = function(...)
    local fn = INTERNAL_API.LIDCOUNCIL_RearmUnconfirmedChoiceReceipts_Impl
    if type(fn) == "function" then
      return fn(...)
    end
  end,
  runtime = runtime,
})

local SendActiveLiveBoardSyncFlow = lootRuntimeCommHelpers.SendActiveLiveBoardSyncFlow
local ReportLootRollToHost = lootRuntimeCommHelpers.ReportLootRollToHost
local OpenAuthoritativeLootItem = lootRuntimeCommHelpers.OpenAuthoritativeLootItem
local RequestManualLootLedgerEntryFlow = lootRuntimeCommHelpers.RequestManualLootLedgerEntryFlow
local RequestManualLootLedgerDeleteFlow = lootRuntimeCommHelpers.RequestManualLootLedgerDeleteFlow
local RequestLootLedgerMainAltFlow = lootRuntimeCommHelpers.RequestLootLedgerMainAltFlow
local RequestLootLedgerCharacterNoteFlow = lootRuntimeCommHelpers.RequestLootLedgerCharacterNoteFlow
local RequestLootLedgerCharacterDeleteFlow = lootRuntimeCommHelpers.RequestLootLedgerCharacterDeleteFlow
local HandleRuntimeSessionComm = lootRuntimeCommHelpers.HandleSessionComm
local SendChoicePacket = lootRuntimeCommHelpers.SendChoicePacket
local BroadcastAuthoritativeChoice = lootRuntimeCommHelpers.BroadcastAuthoritativeChoice
INTERNAL_API.LIDCOUNCIL_HandleLootRuntimeSessionComm_Impl = HandleRuntimeSessionComm
INTERNAL_API.LIDCOUNCIL_RunChoiceBurstValidation_Impl = lootRuntimeCommHelpers.RunChoiceBurstValidation
INTERNAL_API.LIDCOUNCIL_RunBoardSyncReceiptValidation_Impl = lootRuntimeCommHelpers.RunBoardSyncReceiptValidation

INTERNAL_API.LIDCOUNCIL_LootRuntimeShared_Impl = {
  RequireApi = RequireApi,
  ResolveOptionalFunction = ResolveOptionalFunction,
  RootDB = RootDB,
  Print = Print,
  DeepCopy = DeepCopy,
  GetCharacterKey = GetCharacterKey,
  GetLootProfile = GetLootProfile,
  GetActiveLootSession = GetActiveLootSession,
  GetLootProfileAccessInfo = GetLootProfileAccessInfo,
  GetLootProfileAccessInfoForRole = GetLootProfileAccessInfoForRole,
  AddLootLedgerEntry = AddLootLedgerEntry,
  ResolveLootPointValue = ResolveLootPointValue,
  ResolveLootAwardOutcome = ResolveLootAwardOutcome,
  ApplyFrameSkin = ApplyFrameSkin,
  HasJoinedActiveLootSession = HasJoinedActiveLootSession,
  SendSessionComm = SendSessionComm,
  SendChoicePacket = SendChoicePacket,
  SendAwardPacket = lootRuntimeCommHelpers.SendAwardPacket,
  BroadcastAuthoritativeChoice = BroadcastAuthoritativeChoice,
  NormalizeCharacterKey = NormalizeCharacterKey,
  DEFAULT_OPTIONS = DEFAULT_OPTIONS,
  pendingColor = pendingColor,
  CLASS_ICON_TEXTURE = CLASS_ICON_TEXTURE,
  NOTE_ICON_TEXTURE = NOTE_ICON_TEXTURE,
  MAX_SELECTION_NOTE_LENGTH = MAX_SELECTION_NOTE_LENGTH,
  SIMULATION_ITEM_COUNT = SIMULATION_ITEM_COUNT,
  REAL_SIMULATION_ITEM_COUNT = REAL_SIMULATION_ITEM_COUNT,
  REAL_SIMULATION_ITEM_PREFIX = REAL_SIMULATION_ITEM_PREFIX,
  SIMULATION_SAMPLE_MEMBERS = SIMULATION_SAMPLE_MEMBERS,
  RuntimeState = runtime,
  UIState = uiState,
  TrimText = TrimText,
  IsRealSimulationItemKey = IsRealSimulationItemKey,
  ExtractItemID = ExtractItemID,
  NormalizeSelectionNote = NormalizeSelectionNote,
  ExtractItemLinkName = ExtractItemLinkName,
  GetFirstDetailedItemLevel = GetFirstDetailedItemLevel,
  RefreshEditor = RefreshEditor,
  ColorToHex = ColorToHex,
  WrapColor = WrapColor,
  ResolveOptionIconTexture = ResolveOptionIconTexture,
  BuildSelectionState = BuildSelectionState,
  BuildPendingSelection = BuildPendingSelection,
  EnsureSimulationProfile = EnsureSimulationProfile,
  BuildRealSimulationItemDefs = BuildRealSimulationItemDefs,
  NextLiveBoardId = NextLiveBoardId,
  EnsureRuntimeBoardContext = EnsureRuntimeBoardContext,
  EnsurePreviewBoardContext = EnsurePreviewBoardContext,
  PersistRuntimeBoardHistory = PersistRuntimeBoardHistory,
  PersistPreviewBoardHistory = PersistPreviewBoardHistory,
  GetLiveBoardHistoryEntries = GetLiveBoardHistoryEntries,
  GetLiveBoardHistoryPage = GetLiveBoardHistoryPage,
  GetLiveBoardHistorySnapshot = GetLiveBoardHistorySnapshot,
  RestoreLatestPreviewBoardState = RestoreLatestPreviewBoardState,
  ResolveLootLedgerTotals = ResolveLootLedgerTotals,
  ClearRuntimeState = ClearRuntimeState,
  ClearRuntimeAndRefresh = ClearRuntimeAndRefresh,
  EnsureRuntimeSession = EnsureRuntimeSession,
  ResolveRollOptions = ResolveRollOptions,
  ResolveRollOption = ResolveRollOption,
  GetSelfKey = GetSelfKey,
  NormalizeRealmName = NormalizeRealmName,
  GetLocalRealmName = GetLocalRealmName,
  BuildNormalizedCharacterKey = BuildNormalizedCharacterKey,
  ResolveSessionUnit = ResolveSessionUnit,
  ResolveStoredMemberIconData = ResolveStoredMemberIconData,
  ResolveMemberIconData = ResolveMemberIconData,
  BuildInlineIconTag = BuildInlineIconTag,
  BuildMemberDisplayText = BuildMemberDisplayText,
  GetLootProfileAccessInfo = GetLootProfileAccessInfo,
  IsSelfHost = IsSelfHost,
  GetJoinedSessionState = GetJoinedSessionState,
  GetBroadcastDistribution = GetBroadcastDistribution,
  ParseItemSequence = ParseItemSequence,
  PrimeSequence = PrimeSequence,
  NextItemKey = NextItemKey,
  QueueContains = QueueContains,
  EnsureLiveEntry = EnsureLiveEntry,
  GetTrackedItemCount = GetTrackedItemCount,
  BuildPreviewSummary = BuildPreviewSummary,
  GetLiveLootBoardSummary = GetLiveLootBoardSummary,
  GetSelectionPriority = GetSelectionPriority,
  GetSelectionRollValue = GetSelectionRollValue,
  FormatSelectionLabel = FormatSelectionLabel,
  GetAwardCandidateRows = GetAwardCandidateRows,
  EnsureSelectedMember = EnsureSelectedMember,
  CycleSelectedMember = CycleSelectedMember,
  BuildAwardNote = BuildAwardNote,
  MarkAwardOnEntry = MarkAwardOnEntry,
  ClearAwardOnEntry = ClearAwardOnEntry,
  RemoveAwardFromEntry = RemoveAwardFromEntry,
  ApplyAwardMessage = ApplyAwardMessage,
  RefreshBoardAndEditor = RefreshBoardAndEditor,
  RecordChoice = RecordChoice,
  RecordLootVoteStat = RecordLootVoteStat,
  NormalizeEntryVotes = NormalizeEntryVotes,
  GetEntryVoteTargetForVoter = GetEntryVoteTargetForVoter,
  SetEntryVoteTarget = SetEntryVoteTarget,
  GetEntryVoteVoterKeys = GetEntryVoteVoterKeys,
  GetEntryVoteCount = GetEntryVoteCount,
}

local function GetUiImpl()
  local impl = INTERNAL_API.LIDCOUNCIL_LootRuntimeUi_Impl
  if type(impl) ~= "table" then
    error("LidCouncil missing loot runtime UI implementation.")
  end
  return impl
end

local function CallUiFunction(name, ...)
  local fn = GetUiImpl()[name]
  if type(fn) ~= "function" then
    error("LidCouncil missing loot runtime UI function: " .. tostring(name))
  end
  return fn(...)
end

local function OpenLiveLootBoard()
  return CallUiFunction("OpenLiveLootBoard")
end

local function CloseLiveLootBoard()
  return CallUiFunction("CloseLiveLootBoard")
end

local function AttachLiveLootBoard(parent)
  return CallUiFunction("AttachLiveLootBoard", parent)
end

local function AttachLiveLootBoardHistory(parent, profileName)
  return CallUiFunction("AttachLiveLootBoardHistory", parent, profileName)
end

local function PopoutLiveLootBoard()
  return CallUiFunction("PopoutLiveLootBoard")
end

local function PreviewLiveLootBoard(profileName)
  return CallUiFunction("PreviewLiveLootBoard", profileName)
end

local function RefreshLiveLootBoard()
  return CallUiFunction("RefreshLiveLootBoard")
end

local function PreviewRollChoicePopup(profileName)
  return CallUiFunction("PreviewRollChoicePopup", profileName)
end

local function RunLiveLootSimulation(profileName)
  return CallUiFunction("RunLiveLootSimulation", profileName)
end

local function RunLiveLootRealSimulation(profileName)
  return CallUiFunction("RunLiveLootRealSimulation", profileName)
end

local function RefreshChoicePopup(opts)
  opts = type(opts) == "table" and opts or {}
  local reason = string.lower(TrimText(opts.reason))
  if type(ShouldDeferRuntimeUiRefresh) == "function"
    and ShouldDeferRuntimeUiRefresh(reason) then
    local activeSession, activeProfileName = GetActiveLootSession()
    local now = (type(GetServerTime) == "function" and GetServerTime()) or (time and time() or 0)
    runtime.lastChoicePopupState = {
      sessionId = TrimText(type(activeSession) == "table" and activeSession.id or ""),
      profileName = TrimText(activeProfileName),
      state = "deferred",
      reason = "combat_ui_deferred",
      itemKey = TrimText(opts.itemKey),
      queueCount = #(runtime.popupQueue or {}),
      inCombat = true,
      updatedAt = now,
    }
    local receiver = type(runtime.lastBoardSyncReceiver) == "table" and runtime.lastBoardSyncReceiver or nil
    if type(receiver) == "table"
      and runtime.lastChoicePopupState.sessionId ~= ""
      and runtime.lastChoicePopupState.sessionId == TrimText(receiver.sessionId)
      and runtime.lastChoicePopupState.profileName == TrimText(receiver.profileName)
    then
      receiver.popupState = "deferred"
      receiver.popupReason = "combat_ui_deferred"
      receiver.popupQueueCount = runtime.lastChoicePopupState.queueCount
      receiver.popupOpened = false
      receiver.updatedAt = now
    end
    if type(QueueDeferredRuntimeUiRefresh) == "function" then
      QueueDeferredRuntimeUiRefresh({
        reason = reason,
        itemKey = TrimText(opts.itemKey),
        refreshBoard = false,
        choicePopup = true,
      })
    end
    return false
  end
  return CallUiFunction("RefreshChoicePopup")
end

if type(INTERNAL_API.LIDCOUNCIL_RegisterCombatUiRefreshChannel_Impl) ~= "function"
  or not INTERNAL_API.LIDCOUNCIL_RegisterCombatUiRefreshChannel_Impl(
    "RUNTIME",
    "LootRollRuntime",
    function()
      if type(FlushDeferredRuntimeUiRefresh) == "function" then
        local flushed, refreshChoicePopup = FlushDeferredRuntimeUiRefresh()
        if flushed and refreshChoicePopup then
          RefreshChoicePopup({ forceImmediate = true, reason = "sync" })
        end
      end
    end
  )
then
  error("LidCouncil missing combat UI refresh coordinator.")
end

local function ScheduleAutoPassLootRoll(rollID)
  if type(RollOnLoot) ~= "function" then
    return
  end
  local resolvedRollID = tonumber(rollID)
  if not resolvedRollID then
    return
  end
  if type(Compat) == "table" and type(Compat.After) == "function" then
    Compat.After(0.05, function()
      pcall(RollOnLoot, resolvedRollID, 0)
    end)
  else
    pcall(RollOnLoot, resolvedRollID, 0)
  end
end

local function TrackLootRoll(rollID)
  local joined, activeSession, profileName = GetJoinedSessionState()
  if not joined or not activeSession then
    return
  end
  if not EnsureRuntimeSession(activeSession, profileName) then
    return
  end

  local texture, name, _, quality = nil, nil, nil, nil
  if type(GetLootRollItemInfo) == "function" then
    texture, name, _, quality = GetLootRollItemInfo(rollID)
  end
  local link = type(GetLootRollItemLink) == "function" and GetLootRollItemLink(rollID) or nil
  local itemID = ExtractItemID(link)
  local itemLevel = GetFirstDetailedItemLevel(link)
  if (not itemLevel or itemLevel < 100) and link and type(GetItemInfo) == "function" then
    local _, _, _, resolvedLevel = GetItemInfo(link)
    local fallbackLevel = tonumber(resolvedLevel)
    if fallbackLevel and fallbackLevel >= 100 then
      itemLevel = fallbackLevel
    end
  end
  local difficultyID, difficultyName
  if type(GetInstanceInfo) == "function" then
    local _, _, resolvedDifficultyID, resolvedDifficultyName = GetInstanceInfo()
    difficultyID = tonumber(resolvedDifficultyID) or nil
    difficultyName = TrimText(resolvedDifficultyName)
  end

  local payload = {
    rollID = tonumber(rollID),
    name = TrimText(name ~= "" and name or ExtractItemLinkName(link)),
    link = link,
    icon = texture,
    quality = quality,
    itemID = itemID,
    itemLevel = itemLevel,
    difficultyID = difficultyID,
    difficultyName = difficultyName,
    createdAt = (type(GetServerTime) == "function" and GetServerTime()) or (time and time() or 0),
  }
  local classification = type(ClassifyLootRollItem) == "function" and ClassifyLootRollItem(payload) or nil
  if type(classification) == "table" then
    payload.distributionMode = classification.distributionMode
    payload.collectibleKind = classification.collectibleKind
  end

  if IsSelfHost(activeSession) then
    OpenAuthoritativeLootItem(activeSession, profileName, payload, GetSelfKey(), rollID)
    OpenLiveLootBoard()
  else
    ReportLootRollToHost(activeSession, profileName, payload)
  end

  local localAutoPassEnabled = true
  if type(GetLocalAutoPassEnabled) == "function" then
    localAutoPassEnabled = GetLocalAutoPassEnabled() and true or false
  end
  if localAutoPassEnabled and (type(classification) ~= "table" or classification.autoPassAllowed ~= false) then
    ScheduleAutoPassLootRoll(rollID)
  end
end

local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("START_LOOT_ROLL")
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
eventFrame:SetScript("OnEvent", function(_, event, ...)
  if event == "PLAYER_ENTERING_WORLD" then
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or string.upper(tostring(activeSession.status or "ACTIVE")) ~= "ACTIVE" then
      ClearRuntimeState()
      uiState.previewState = RestoreLatestPreviewBoardState(RootDB() and RootDB().currentProfile or nil)
    else
      uiState.previewState = nil
      EnsureRuntimeSession(activeSession, profileName)
      local rearmChoices = INTERNAL_API.LIDCOUNCIL_RearmUnconfirmedChoiceReceipts_Impl
      if type(rearmChoices) == "function" then
        rearmChoices({ reason = "player_entering_world" })
      end
    end
    return
  end

  if event == "START_LOOT_ROLL" then
    local rollID = ...
    if tonumber(rollID) then
      TrackLootRoll(tonumber(rollID))
    end
    return
  end
end)

PublishApi("LIDCOUNCIL_OpenLiveLootBoard", OpenLiveLootBoard, { global = false })
PublishApi("LIDCOUNCIL_CloseLiveLootBoard", CloseLiveLootBoard, { global = false })
PublishApi("LIDCOUNCIL_GetLiveLootBoardSummary", GetLiveLootBoardSummary, { global = false })
PublishApi("LIDCOUNCIL_GetLiveLootRealSimulationStatus", function()
  local status = type(runtime.lastRealSimulationRun) == "table" and runtime.lastRealSimulationRun or nil
  if type(status) ~= "table" then
    return nil
  end
  return {
    sessionId = TrimText(status.sessionId),
    statusText = TrimText(status.statusText),
    dispatchState = TrimText(status.dispatchState),
  }
end, { global = false })
PublishApi("LIDCOUNCIL_GetLiveLootRuntimeDiagnostics", GetLiveLootRuntimeDiagnostics, { global = false })
PublishApi("LIDCOUNCIL_GetLiveLootBoardHistoryEntries", GetLiveBoardHistoryEntries, { global = false })
PublishApi("LIDCOUNCIL_ClearLiveLootRuntime", ClearRuntimeAndRefresh, { global = false })
PublishApi("LIDCOUNCIL_PreviewRollChoicePopup", PreviewRollChoicePopup, { global = false })
PublishApi("LIDCOUNCIL_PreviewLiveLootBoard", PreviewLiveLootBoard, { global = false })
PublishApi("LIDCOUNCIL_RefreshLiveLootBoard", RefreshLiveLootBoard, { global = false })
PublishApi("LIDCOUNCIL_AttachLiveLootBoard", AttachLiveLootBoard, { global = false })
PublishApi("LIDCOUNCIL_AttachLiveLootBoardHistory", AttachLiveLootBoardHistory, { global = false })
PublishApi("LIDCOUNCIL_PopoutLiveLootBoard", PopoutLiveLootBoard, { global = false })
PublishApi("LIDCOUNCIL_RunLiveLootSimulation", RunLiveLootSimulation, { global = false })
PublishApi("LIDCOUNCIL_RunLiveLootRealSimulation", RunLiveLootRealSimulation, { global = false })
PublishApi("LIDCOUNCIL_RunLiveLootTransportTest", function(profileName)
  return CallUiFunction("RunLiveLootTransportTest", profileName)
end, { global = false })
PublishApi("LIDCOUNCIL_OpenTransportSimulationItemFlow", lootRuntimeCommHelpers.OpenTransportSimulationItem, { global = false })
PublishApi("LIDCOUNCIL_SendActiveLiveBoardSyncFlow", SendActiveLiveBoardSyncFlow, { global = false })
PublishApi("LIDCOUNCIL_RequestManualLootLedgerEntryFlow", RequestManualLootLedgerEntryFlow, { global = false })
PublishApi("LIDCOUNCIL_RequestManualLootLedgerDeleteFlow", RequestManualLootLedgerDeleteFlow, { global = false })
PublishApi("LIDCOUNCIL_RequestLootLedgerMainAltFlow", RequestLootLedgerMainAltFlow, { global = false })
PublishApi("LIDCOUNCIL_RequestLootLedgerCharacterNoteFlow", RequestLootLedgerCharacterNoteFlow, { global = false })
PublishApi("LIDCOUNCIL_RequestLootLedgerCharacterDeleteFlow", RequestLootLedgerCharacterDeleteFlow, { global = false })
