local API = rawget(_G, "LIDCOUNCIL_API")
if type(API) ~= "table" then
  API = {}
  _G.LIDCOUNCIL_API = API
end
API.__internal = API.__internal or {}
local INTERNAL_API = API.__internal

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 ResolveOptionalValue(name)
  local api = rawget(_G, "LIDCOUNCIL_API")
  if type(api) == "table" and api[name] ~= nil then
    return api[name]
  end
  return rawget(_G, name)
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 ParseSessionComm = ResolveOptionalFunction("LIDCOUNCIL_ParseSessionComm")
local NormalizeCharacterKey = ResolveOptionalFunction("LIDCOUNCIL_NormalizeCharacterKey")
local RemoveLootLedgerEntry = ResolveOptionalFunction("RemoveLootLedgerEntry")
local GetLootLedgerCharacters = ResolveOptionalFunction("GetLootLedgerCharacters")
local GetLocalAutoPassEnabled = ResolveOptionalFunction("LIDCOUNCIL_GetLocalAutoPassEnabled")
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")
local COMM_PREFIX = tostring(ResolveOptionalValue("LIDCOUNCIL_COMM_PREFIX") or "LIDLOOT1")

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 = {},
  localRollItemKeys = {},
  hostRollItemKeys = {},
  hostReportItemKeys = {},
  selectedItemKey = nil,
  selectedMemberKey = nil,
  lastReceivedOpcode = nil,
  lastReceivedSender = nil,
  lastBoardSyncSender = 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)
  local editor = rawget(_G, "LIDCOUNCIL_Editor")
  if editor and editor.__lidCouncilEditor and editor.IsShown and editor:IsShown() then
    if editor.RefreshLootWorkflowSections then
      editor:RefreshLootWorkflowSections(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,
  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 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 {}

  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 ""),
    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),
    lastOpcode = TrimText(runtime.lastReceivedOpcode),
    lastSender = TrimText(runtime.lastReceivedSender),
    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 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,
  TrimText = TrimText,
  ExtractItemID = ExtractItemID,
  NormalizeSelectionNote = NormalizeSelectionNote,
  NormalizeCharacterKey = NormalizeCharacterKey,
  GetActiveLootSession = GetActiveLootSession,
  GetLootProfile = GetLootProfile,
  GetLootProfileRole = GetLootProfileRole,
  GetLootProfileAccessInfo = GetLootProfileAccessInfo,
  IsSelfHost = IsSelfHost,
  EnsureRuntimeSession = EnsureRuntimeSession,
  ResolveRollOption = ResolveRollOption,
  EnsureLiveEntry = EnsureLiveEntry,
  NextItemKey = NextItemKey,
  QueueContains = QueueContains,
  GetBroadcastDistribution = GetBroadcastDistribution,
  SendSessionComm = SendSessionComm,
  RefreshBoardAndEditor = RefreshBoardAndEditor,
  RecordChoice = RecordChoice,
  RecordLootVoteStat = RecordLootVoteStat,
  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,
  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

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,
  ParseSessionComm = ParseSessionComm,
  NormalizeCharacterKey = NormalizeCharacterKey,
  COMM_PREFIX = COMM_PREFIX,
  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,
  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()
  return CallUiFunction("RefreshChoicePopup")
end

local function ScheduleAutoPassLootRoll(rollID)
  if type(RollOnLoot) ~= "function" then
    return
  end
  local resolvedRollID = tonumber(rollID)
  if not resolvedRollID then
    return
  end
  if type(C_Timer) == "table" and type(C_Timer.After) == "function" then
    C_Timer.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),
  }

  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 then
    ScheduleAutoPassLootRoll(rollID)
  end
end

local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("START_LOOT_ROLL")
eventFrame:RegisterEvent("CHAT_MSG_ADDON")
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)
    end
    return
  end

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

  if event == "CHAT_MSG_ADDON" then
    local prefix, message, _, sender = ...
    if prefix ~= COMM_PREFIX or type(ParseSessionComm) ~= "function" then
      return
    end
    local fields = ParseSessionComm(message)
    if HandleRuntimeSessionComm(fields, sender) then
      return
    elseif fields[1] == "STOP" then
      ClearRuntimeAndRefresh()
    end
  end
end)

PublishApi("LIDCOUNCIL_OpenLiveLootBoard", OpenLiveLootBoard, { global = false })
PublishApi("LIDCOUNCIL_CloseLiveLootBoard", CloseLiveLootBoard, { global = false })
PublishApi("LIDCOUNCIL_GetLiveLootBoardSummary", GetLiveLootBoardSummary, { 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_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 })
