local API = rawget(_G, "LIDCOUNCIL_API")
local INTERNAL_API = type(API) == "table" and type(API.__internal) == "table" and API.__internal or nil
if type(INTERNAL_API) ~= "table" then
  error("LidCouncil missing internal API registry.")
end

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

  local Print = deps.Print
  local TrimText = deps.TrimText
  local ExtractItemID = deps.ExtractItemID
  local NormalizeSelectionNote = deps.NormalizeSelectionNote
  local NormalizeCharacterKey = deps.NormalizeCharacterKey
  local GetActiveLootSession = deps.GetActiveLootSession
  local GetLootProfile = deps.GetLootProfile
  local GetLootProfileRole = deps.GetLootProfileRole
  local GetLootProfileAccessInfo = deps.GetLootProfileAccessInfo
  local IsSelfHost = deps.IsSelfHost
  local EnsureRuntimeSession = deps.EnsureRuntimeSession
  local ResolveRollOption = deps.ResolveRollOption
  local EnsureLiveEntry = deps.EnsureLiveEntry
  local NextItemKey = deps.NextItemKey
  local QueueContains = deps.QueueContains
  local GetBroadcastDistribution = deps.GetBroadcastDistribution
  local SendSessionComm = deps.SendSessionComm
  local RefreshBoardAndEditor = deps.RefreshBoardAndEditor
  local RecordChoice = deps.RecordChoice
  local RecordLootVoteStat = deps.RecordLootVoteStat
  local AddLootLedgerEntry = deps.AddLootLedgerEntry
  local RemoveLootLedgerEntry = deps.RemoveLootLedgerEntry
  local NormalizeLootLedgerRoleLocal = deps.NormalizeLootLedgerRoleLocal
  local SetLootLedgerMainAltRole = deps.SetLootLedgerMainAltRole
  local SetLootLedgerCharacterNote = deps.SetLootLedgerCharacterNote
  local SetLootLedgerMainCharacter = deps.SetLootLedgerMainCharacter
  local ClearLootLedgerMainCharacter = deps.ClearLootLedgerMainCharacter
  local DeleteLootLedgerCharacter = deps.DeleteLootLedgerCharacter
  local BuildLootLedgerNavRows = deps.BuildLootLedgerNavRows
  local ApplyAwardMessage = deps.ApplyAwardMessage
  local RemoveAwardFromEntry = deps.RemoveAwardFromEntry
  local NormalizeEntryVotes = deps.NormalizeEntryVotes
  local NormalizeVoteSequence = deps.NormalizeVoteSequence
  local SetEntryVoteTarget = deps.SetEntryVoteTarget
  local PersistRuntimeBoardHistory = deps.PersistRuntimeBoardHistory
  local BuildRuntimeBoardHistorySnapshot = deps.BuildRuntimeBoardHistorySnapshot
  local GetLatestRuntimeBoardSnapshot = deps.GetLatestRuntimeBoardSnapshot
  local RestoreRuntimeBoardSnapshot = deps.RestoreRuntimeBoardSnapshot
  local GetSelfKey = deps.GetSelfKey
  local PrimeSequence = deps.PrimeSequence
  local ClearPreviewState = deps.ClearPreviewState
  local RefreshChoicePopup = deps.RefreshChoicePopup
  local runtime = deps.runtime

  local incomingBoardSyncs = {}
  local GetBoardSyncToken
  local EXPECTED_FIELD_COUNTS = {
    CHOICE = 11,
    RCHOICE = 11,
    ITEM_REPORT = 12,
    ITEM_OPEN = 13,
    AWARD = 10,
    UNASSIGN = 5,
    TRADE = 7,
    VOTE = 8,
    LL_ADD_REQ = 9,
    LL_ADD = 10,
    LL_DEL_REQ = 7,
    LL_DEL = 6,
    LL_MA_REQ = 8,
    LL_MA = 8,
    LL_NOTE_REQ = 7,
    LL_NOTE = 7,
    LL_CHAR_DEL_REQ = 6,
    LL_CHAR_DEL = 6,
    BSYNC_START = 7,
    BSYNC_ITEM = 21,
    BSYNC_SEL = 17,
    BSYNC_VOTE = 8,
    BSYNC_END = 5,
  }
  local MAX_BOARD_SYNC_ITEM_NAME_LENGTH = 80
  local MAX_BOARD_SYNC_LINK_LENGTH = 128
  local MAX_BOARD_SYNC_ICON_LENGTH = 96
  local MAX_BOARD_SYNC_NOTE_LENGTH = 64
  local MAX_BOARD_SYNC_LEDGER_ID_LENGTH = 48
  local MAX_BOARD_SYNC_LABEL_LENGTH = 48
  local MAX_BOARD_SYNC_SOURCE_LENGTH = 24
  local MAX_ITEM_OPEN_NAME_LENGTH = 80
  local MAX_ITEM_OPEN_LINK_LENGTH = 192
  local MAX_ITEM_OPEN_ICON_LENGTH = 96
  local MAX_MANUAL_LEDGER_ID_LENGTH = 24
  local MAX_MANUAL_LEDGER_NAME_LENGTH = 48
  local MAX_MANUAL_LEDGER_NOTE_LENGTH = 24
  local MAX_LOOT_LEDGER_CHARACTER_LENGTH = 64
  local MAX_LOOT_LEDGER_NOTE_LENGTH = 160
  local MANUAL_LEDGER_ICON = "Interface\\Icons\\INV_Misc_Note_06"
  local AUTHORITATIVE_LOOT_ITEM_PREFIX = "LIVE-"

  local function IsLiveSession(activeSession)
    return type(activeSession) == "table" and string.upper(TrimText(activeSession.status or "ACTIVE")) == "ACTIVE"
  end

  local function DoesRuntimeSessionMatch(activeSession, activeProfileName, sessionId, profileName)
    if type(activeSession) ~= "table" or TrimText(activeSession.id) ~= TrimText(sessionId) then
      return false
    end
    local expectedProfileName = TrimText(profileName)
    if expectedProfileName == "" then
      return true
    end
    return TrimText(activeProfileName) == expectedProfileName
      or TrimText(activeSession.profileName) == expectedProfileName
      or TrimText(activeSession.remoteProfileName) == expectedProfileName
  end

  local function GetSessionCommProfileName(activeSession, fallbackProfileName)
    return TrimText(type(activeSession) == "table" and activeSession.remoteProfileName) ~= ""
      and TrimText(activeSession.remoteProfileName)
      or TrimText(fallbackProfileName)
  end

  local function NormalizeSenderKey(sender)
    return NormalizeCharacterKey(sender)
  end

  local function NormalizeComparableCharacterKey(value)
    return string.lower(NormalizeCharacterKey(value))
  end

  local function SplitCharacterKey(value)
    local normalized = NormalizeComparableCharacterKey(value)
    if normalized == "" then
      return "", ""
    end
    local name, realm = normalized:match("^([^%-]+)%-(.+)$")
    if name and name ~= "" then
      return name, realm or ""
    end
    return normalized, ""
  end

  local function AreCharacterKeysSame(left, right)
    local leftKey = NormalizeComparableCharacterKey(left)
    local rightKey = NormalizeComparableCharacterKey(right)
    if leftKey == "" or rightKey == "" then
      return false
    end
    if leftKey == rightKey then
      return true
    end
    local leftName, leftRealm = SplitCharacterKey(leftKey)
    local rightName, rightRealm = SplitCharacterKey(rightKey)
    return leftName ~= "" and leftName == rightName and (leftRealm == "" or rightRealm == "")
  end

  local function ClipBoardSyncText(value, limit)
    local text = TrimText(value)
    local maxLength = tonumber(limit) or 0
    if maxLength > 0 and #text > maxLength then
      text = text:sub(1, maxLength)
    end
    return text
  end

  local function IsSessionHostKey(activeSession, characterKey)
    return AreCharacterKeysSame(type(activeSession) == "table" and activeSession.host or "", characterKey)
  end

  local function GetSessionMember(activeSession, characterKey)
    if type(activeSession) ~= "table" or type(activeSession.members) ~= "table" then
      return nil
    end
    local resolvedKey = NormalizeCharacterKey(characterKey)
    if resolvedKey == "" then
      return nil
    end
    local direct = activeSession.members[resolvedKey]
    if type(direct) == "table" then
      return direct, resolvedKey
    end
    for storedKey, member in pairs(activeSession.members) do
      if AreCharacterKeysSame(storedKey, resolvedKey) and type(member) == "table" then
        return member, storedKey
      end
    end
    return nil
  end

  local function IsJoinedSessionCharacter(activeSession, characterKey)
    local resolvedKey = NormalizeCharacterKey(characterKey)
    if resolvedKey == "" then
      return false
    end
    if IsSessionHostKey(activeSession, resolvedKey) then
      return true
    end
    local member = GetSessionMember(activeSession, resolvedKey)
    return type(member) == "table" and TrimText(member.status or "JOINED") == "JOINED"
  end

  local function GetSessionCharacterRole(activeSession, profileName, characterKey)
    local resolvedKey = NormalizeCharacterKey(characterKey)
    if resolvedKey == "" then
      return "RAIDER"
    end
    if IsSessionHostKey(activeSession, resolvedKey) then
      return "MASTER"
    end
    local member = GetSessionMember(activeSession, resolvedKey)
    local memberRole = TrimText(type(member) == "table" and member.role or "")
    if memberRole ~= "" then
      memberRole = string.upper(memberRole)
      if memberRole == "MASTER" or memberRole == "COUNCIL" then
        return memberRole
      end
      return "RAIDER"
    end
    if type(GetLootProfileRole) == "function" then
      local resolvedRole = string.upper(TrimText(GetLootProfileRole(profileName, resolvedKey)))
      if resolvedRole == "MASTER" or resolvedRole == "COUNCIL" then
        return resolvedRole
      end
    end
    return "RAIDER"
  end

  local function CanSessionCharacterVote(activeSession, profileName, characterKey)
    if type(GetLootProfileAccessInfo) == "function" then
      local access = GetLootProfileAccessInfo(profileName, characterKey)
      if type(access) == "table" and access.canVote ~= nil then
        return access.canVote and true or false
      end
    end
    local role = GetSessionCharacterRole(activeSession, profileName, characterKey)
    return role == "MASTER" or role == "COUNCIL"
  end

  local function IsClaimedActorSenderMatch(sender, claimedCharacterKey)
    local senderKey = NormalizeSenderKey(sender)
    local claimedKey = NormalizeCharacterKey(claimedCharacterKey)
    if senderKey == "" or claimedKey == "" then
      return false
    end
    return AreCharacterKeysSame(senderKey, claimedKey)
  end

  local function ResolveEntrySelection(entry, memberKey)
    if type(entry) ~= "table" or type(entry.selections) ~= "table" then
      return nil
    end
    local direct = entry.selections[memberKey]
    if type(direct) == "table" then
      return direct, memberKey
    end
    for selectionKey, selection in pairs(entry.selections) do
      if AreCharacterKeysSame(selectionKey, memberKey) and type(selection) == "table" then
        return selection, selectionKey
      end
    end
    return nil
  end

  local function IsPendingSelection(selection)
    local selectionKey = string.lower(TrimText(type(selection) == "table" and (selection.optionKey or selection.label) or "pending"))
    return selectionKey == "" or selectionKey == "pending"
  end

  local function HasBoardSyncState(sessionId, profileName, sender)
    return type(incomingBoardSyncs[GetBoardSyncToken(sessionId, profileName, sender)]) == "table"
  end

  local function GetIncomingTimestamp(value)
    local timestamp = tonumber(value)
    if not timestamp or timestamp <= 0 then
      return nil
    end
    return timestamp
  end

  local function GetCurrentTimestamp()
    return (type(GetServerTime) == "function" and GetServerTime()) or (time and time() or 0)
  end

  local function ClipManualLedgerText(value, limit)
    local text = TrimText(value)
    local maxLength = tonumber(limit) or 0
    if maxLength > 0 and #text > maxLength then
      text = text:sub(1, maxLength)
    end
    return text
  end

  local function BuildManualLedgerRequestId(prefix)
    local token = tostring(prefix or "ML") .. "-" .. tostring(GetCurrentTimestamp()) .. "-" .. tostring(math.random(1000, 9999))
    return ClipManualLedgerText(token:gsub("[^%w%-_]", ""), MAX_MANUAL_LEDGER_ID_LENGTH)
  end

  local function FindManualLedgerEntry(profileName, memberKey, entryId, sourceRequestId)
    if type(GetLootProfile) ~= "function" then
      return nil
    end
    local profile = select(1, GetLootProfile(profileName))
    local resolvedMemberKey = NormalizeCharacterKey(memberKey)
    local resolvedEntryId = TrimText(entryId)
    local resolvedRequestId = TrimText(sourceRequestId)
    local ledger = type(profile) == "table" and type(profile.lootLedger) == "table" and profile.lootLedger[resolvedMemberKey] or nil
    local items = type(ledger) == "table" and ledger.items or nil
    if type(items) ~= "table" then
      return nil
    end
    for _, entry in ipairs(items) do
      if type(entry) == "table" then
        if resolvedEntryId ~= "" and TrimText(entry.entryId) == resolvedEntryId then
          return entry
        end
        if resolvedRequestId ~= "" and TrimText(entry.sourceRequestId) == resolvedRequestId then
          return entry
        end
      end
    end
    return nil
  end

  local function CanSessionCharacterEditManualPoints(activeSession, profileName, characterKey)
    local resolvedKey = NormalizeCharacterKey(characterKey)
    if resolvedKey == "" or not IsJoinedSessionCharacter(activeSession, resolvedKey) then
      return false
    end
    if type(GetLootProfileAccessInfo) ~= "function" then
      return false
    end
    local access = GetLootProfileAccessInfo(profileName, resolvedKey)
    return type(access) == "table" and access.canEditManualPoints == true
  end

  local function CanSessionCharacterEditMainAlt(activeSession, profileName, characterKey)
    local resolvedKey = NormalizeCharacterKey(characterKey)
    if resolvedKey == "" or not IsJoinedSessionCharacter(activeSession, resolvedKey) then
      return false
    end
    if type(GetLootProfileAccessInfo) ~= "function" then
      return false
    end
    local access = GetLootProfileAccessInfo(profileName, resolvedKey)
    return type(access) == "table" and access.canEditMainAlt == true
  end

  local function CanSessionCharacterEditNotes(activeSession, profileName, characterKey)
    local resolvedKey = NormalizeCharacterKey(characterKey)
    if resolvedKey == "" or not IsJoinedSessionCharacter(activeSession, resolvedKey) then
      return false
    end
    if type(GetLootProfileAccessInfo) ~= "function" then
      return false
    end
    local access = GetLootProfileAccessInfo(profileName, resolvedKey)
    return type(access) == "table" and access.canEditNotes == true
  end

  local function CanSessionCharacterDeleteLootListCharacter(activeSession, profileName, characterKey)
    local resolvedKey = NormalizeCharacterKey(characterKey)
    if resolvedKey == "" or not IsJoinedSessionCharacter(activeSession, resolvedKey) then
      return false
    end
    if type(GetLootProfileAccessInfo) ~= "function" then
      return false
    end
    local access = GetLootProfileAccessInfo(profileName, resolvedKey)
    return type(access) == "table" and access.canDeleteLootListCharacter == true
  end

  local function RefreshManualLedgerViews()
    RefreshBoardAndEditor({
      reason = "ledger",
      editorRefresh = { refreshPages = { Backgrounds = true, Profiles = true, Panels = true } },
    })
  end

  local function ApplyManualLedgerAdd(profileName, memberKey, itemName, points, note, grantedBy, requestId, entryId, awardedAt, sessionId)
    if type(AddLootLedgerEntry) ~= "function" then
      return false, "Loot list ledger API is unavailable."
    end

    local resolvedMemberKey = NormalizeCharacterKey(memberKey)
    local resolvedItemName = ClipManualLedgerText(itemName, MAX_MANUAL_LEDGER_NAME_LENGTH)
    local resolvedRequestId = ClipManualLedgerText(requestId, MAX_MANUAL_LEDGER_ID_LENGTH)
    local resolvedEntryId = ClipManualLedgerText(entryId, MAX_MANUAL_LEDGER_ID_LENGTH)
    if resolvedMemberKey == "" then
      return false, "Character-Realm is required."
    end
    if resolvedItemName == "" then
      return false, "Item name is required."
    end

    local existing = FindManualLedgerEntry(profileName, resolvedMemberKey, resolvedEntryId, resolvedRequestId)
    if type(existing) == "table" then
      return true, existing, "DUPLICATE"
    end

    return AddLootLedgerEntry(
      profileName,
      resolvedMemberKey,
      resolvedItemName,
      nil,
      tonumber(points) or 0,
      ClipManualLedgerText(note, MAX_MANUAL_LEDGER_NOTE_LENGTH),
      nil,
      nil,
      MANUAL_LEDGER_ICON,
      nil,
      {
        entryId = resolvedEntryId,
        sourceRequestId = resolvedRequestId,
        awardedAt = tonumber(awardedAt) or GetCurrentTimestamp(),
        grantedBy = NormalizeCharacterKey(grantedBy),
        sessionId = TrimText(sessionId),
        isManual = true,
      }
    )
  end

  local function ApplyManualLedgerDelete(profileName, memberKey, entryId)
    if type(RemoveLootLedgerEntry) ~= "function" then
      return false, "Loot list ledger API is unavailable."
    end
    local resolvedMemberKey = NormalizeCharacterKey(memberKey)
    local resolvedEntryId = ClipManualLedgerText(entryId, MAX_MANUAL_LEDGER_ID_LENGTH)
    if resolvedMemberKey == "" or resolvedEntryId == "" then
      return false, "Manual ledger entry is missing."
    end
    local existing = FindManualLedgerEntry(profileName, resolvedMemberKey, resolvedEntryId, "")
    if type(existing) ~= "table" then
      return false, "Ledger entry not found."
    end
    if existing.isManual ~= true then
      return false, "Only manual point entries can be removed from this control."
    end
    return RemoveLootLedgerEntry(profileName, resolvedMemberKey, resolvedEntryId)
  end

  local function ResolveLootLedgerRole(value)
    if type(NormalizeLootLedgerRoleLocal) == "function" then
      return NormalizeLootLedgerRoleLocal(value)
    end
    return string.upper(TrimText(value)) == "ALT" and "ALT" or "MAIN"
  end

  local function ApplyLootLedgerMainAlt(profileName, characterKey, role, mainCharacter)
    if type(GetLootProfile) ~= "function" then
      return false, "Loot profile API is unavailable."
    end
    if type(SetLootLedgerMainAltRole) ~= "function" or type(SetLootLedgerMainCharacter) ~= "function" or type(ClearLootLedgerMainCharacter) ~= "function" then
      return false, "Main / Alt update API is unavailable."
    end

    local profile = select(1, GetLootProfile(profileName))
    if type(profile) ~= "table" then
      return false, "Profile not found."
    end

    local resolvedCharacter = ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    if resolvedCharacter == "" then
      return false, "Select a character first."
    end

    local resolvedRole = ResolveLootLedgerRole(role)
    if resolvedRole ~= "ALT" then
      return ClearLootLedgerMainCharacter(profile, resolvedCharacter)
    end

    local ok, result = SetLootLedgerMainAltRole(profile, resolvedCharacter, "ALT")
    if not ok then
      return false, result
    end

    local allCharactersByKey = nil
    if type(BuildLootLedgerNavRows) == "function" then
      local _, byCharacter = BuildLootLedgerNavRows(profile, profileName, "")
      allCharactersByKey = byCharacter
    end
    local resolvedMain = ClipManualLedgerText(NormalizeCharacterKey(mainCharacter), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    return SetLootLedgerMainCharacter(profile, resolvedCharacter, resolvedMain, allCharactersByKey)
  end

  local function ApplyLootLedgerCharacterNote(profileName, characterKey, noteText)
    if type(GetLootProfile) ~= "function" then
      return false, "Loot profile API is unavailable."
    end
    if type(SetLootLedgerCharacterNote) ~= "function" then
      return false, "Loot List note API is unavailable."
    end

    local profile = select(1, GetLootProfile(profileName))
    if type(profile) ~= "table" then
      return false, "Profile not found."
    end

    local resolvedCharacter = ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    if resolvedCharacter == "" then
      return false, "Select a character first."
    end

    return SetLootLedgerCharacterNote(profile, resolvedCharacter, ClipManualLedgerText(noteText, MAX_LOOT_LEDGER_NOTE_LENGTH))
  end

  local function ApplyLootLedgerCharacterDelete(profileName, characterKey)
    if type(GetLootProfile) ~= "function" then
      return false, "Loot profile API is unavailable."
    end
    if type(DeleteLootLedgerCharacter) ~= "function" then
      return false, "Loot List character delete API is unavailable."
    end

    local profile = select(1, GetLootProfile(profileName))
    if type(profile) ~= "table" then
      return false, "Profile not found."
    end

    local resolvedCharacter = ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    if resolvedCharacter == "" then
      return false, "Select a character first."
    end

    return DeleteLootLedgerCharacter(profile, resolvedCharacter)
  end

  local function ResolveOptionalApiFunction(name)
    if type(API) == "table" and type(API[name]) == "function" then
      return API[name]
    end
    local fallback = rawget(_G, name)
    if type(fallback) == "function" then
      return fallback
    end
    return nil
  end

  local function BroadcastProfileLootDelta(profileName, change)
    local broadcastProfileDelta = ResolveOptionalApiFunction("LIDCOUNCIL_BroadcastActiveProfileDeltaFlow")
    if type(broadcastProfileDelta) ~= "function" or type(change) ~= "table" then
      return false, "Profile delta broadcast is unavailable."
    end
    change.domain = "loot"
    return broadcastProfileDelta(profileName, "loot", change)
  end

  local function BroadcastLootChangeWithFallback(profileName, change, legacySender, ...)
    local sent, err = BroadcastProfileLootDelta(profileName, change)
    if sent then
      return true, "delta"
    end
    if type(legacySender) == "function" then
      local legacySent = legacySender(...)
      if legacySent then
        return true, "legacy"
      end
    end
    return false, err or "Could not broadcast live loot change."
  end

  local function BuildManualLedgerAddDeltaChange(activeSession, memberKey, entry, grantedBy)
    if type(entry) ~= "table" then
      return nil
    end
    local resolvedGrantedBy = NormalizeCharacterKey(TrimText(grantedBy) ~= "" and grantedBy or entry.grantedBy)
    local resolvedSessionId = TrimText(TrimText(entry.sessionId) ~= "" and entry.sessionId or (type(activeSession) == "table" and activeSession.id or ""))
    return {
      action = "LEDGER_MANUAL_ADD",
      args = {
        NormalizeCharacterKey(memberKey),
        ClipManualLedgerText(entry.entryId, MAX_MANUAL_LEDGER_ID_LENGTH),
        ClipManualLedgerText(entry.itemName, MAX_MANUAL_LEDGER_NAME_LENGTH),
        tostring(tonumber(entry.points) or 0),
        ClipManualLedgerText(entry.note, MAX_MANUAL_LEDGER_NOTE_LENGTH),
        resolvedGrantedBy,
        tostring(tonumber(entry.awardedAt) or GetCurrentTimestamp()),
        resolvedSessionId,
      },
    }
  end

  local function BuildManualLedgerDeleteDeltaChange(memberKey, entryId)
    return {
      action = "LEDGER_MANUAL_DELETE",
      args = {
        NormalizeCharacterKey(memberKey),
        ClipManualLedgerText(entryId, MAX_MANUAL_LEDGER_ID_LENGTH),
      },
    }
  end

  local function BuildLootLedgerMainAltDeltaChange(characterKey, role, mainCharacter)
    return {
      action = "LEDGER_MAIN_ALT_SET",
      args = {
        ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
        ResolveLootLedgerRole(role),
        ClipManualLedgerText(NormalizeCharacterKey(mainCharacter), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
      },
    }
  end

  local function BuildLootLedgerCharacterNoteDeltaChange(characterKey, noteText)
    return {
      action = "LEDGER_NOTE_SET",
      args = {
        ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
        ClipManualLedgerText(noteText, MAX_LOOT_LEDGER_NOTE_LENGTH),
      },
    }
  end

  local function BuildLootLedgerCharacterDeleteDeltaChange(characterKey)
    return {
      action = "LEDGER_CHARACTER_DELETE",
      args = {
        ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
      },
    }
  end

  local function BroadcastManualLedgerAdd(activeSession, profileName, memberKey, entry, grantedBy)
    local distribution = GetBroadcastDistribution()
    if not distribution or type(SendSessionComm) ~= "function" or type(entry) ~= "table" then
      return false
    end
    return SendSessionComm(
      "LL_ADD",
      distribution,
      nil,
      tostring(activeSession.id or ""),
      GetSessionCommProfileName(activeSession, profileName),
      ClipManualLedgerText(entry.entryId, MAX_MANUAL_LEDGER_ID_LENGTH),
      NormalizeCharacterKey(memberKey),
      ClipManualLedgerText(entry.itemName, MAX_MANUAL_LEDGER_NAME_LENGTH),
      tostring(tonumber(entry.points) or 0),
      ClipManualLedgerText(entry.note, MAX_MANUAL_LEDGER_NOTE_LENGTH),
      tostring(tonumber(entry.awardedAt) or GetCurrentTimestamp()),
      NormalizeCharacterKey(grantedBy)
    )
  end

  local function BroadcastManualLedgerDelete(activeSession, profileName, memberKey, entryId, changedAt)
    local distribution = GetBroadcastDistribution()
    if not distribution or type(SendSessionComm) ~= "function" then
      return false
    end
    return SendSessionComm(
      "LL_DEL",
      distribution,
      nil,
      tostring(activeSession.id or ""),
      GetSessionCommProfileName(activeSession, profileName),
      ClipManualLedgerText(entryId, MAX_MANUAL_LEDGER_ID_LENGTH),
      NormalizeCharacterKey(memberKey),
      tostring(tonumber(changedAt) or GetCurrentTimestamp())
    )
  end

  local function BroadcastLootLedgerMainAlt(activeSession, profileName, characterKey, role, mainCharacter, changedAt, changedBy)
    local distribution = GetBroadcastDistribution()
    if not distribution or type(SendSessionComm) ~= "function" then
      return false
    end
    return SendSessionComm(
      "LL_MA",
      distribution,
      nil,
      tostring(activeSession.id or ""),
      GetSessionCommProfileName(activeSession, profileName),
      ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
      ResolveLootLedgerRole(role),
      ClipManualLedgerText(NormalizeCharacterKey(mainCharacter), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
      tostring(tonumber(changedAt) or GetCurrentTimestamp()),
      NormalizeCharacterKey(changedBy)
    )
  end

  local function BroadcastLootLedgerCharacterNote(activeSession, profileName, characterKey, noteText, changedAt, changedBy)
    local distribution = GetBroadcastDistribution()
    if not distribution or type(SendSessionComm) ~= "function" then
      return false
    end
    return SendSessionComm(
      "LL_NOTE",
      distribution,
      nil,
      tostring(activeSession.id or ""),
      GetSessionCommProfileName(activeSession, profileName),
      ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
      ClipManualLedgerText(noteText, MAX_LOOT_LEDGER_NOTE_LENGTH),
      tostring(tonumber(changedAt) or GetCurrentTimestamp()),
      NormalizeCharacterKey(changedBy)
    )
  end

  local function BroadcastLootLedgerCharacterDelete(activeSession, profileName, characterKey, changedAt, changedBy)
    local distribution = GetBroadcastDistribution()
    if not distribution or type(SendSessionComm) ~= "function" then
      return false
    end
    return SendSessionComm(
      "LL_CHAR_DEL",
      distribution,
      nil,
      tostring(activeSession.id or ""),
      GetSessionCommProfileName(activeSession, profileName),
      ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
      tostring(tonumber(changedAt) or GetCurrentTimestamp()),
      NormalizeCharacterKey(changedBy)
    )
  end

  local function EnsureRuntimeAuthorityMaps()
    runtime.localRollItemKeys = type(runtime.localRollItemKeys) == "table" and runtime.localRollItemKeys or {}
    runtime.hostRollItemKeys = type(runtime.hostRollItemKeys) == "table" and runtime.hostRollItemKeys or {}
    runtime.hostReportItemKeys = type(runtime.hostReportItemKeys) == "table" and runtime.hostReportItemKeys or {}
  end

  local function ClipItemOpenText(value, limit)
    local text = TrimText(value)
    local maxLength = tonumber(limit) or 0
    if maxLength > 0 and #text > maxLength then
      return ""
    end
    return text
  end

  local function NormalizeLootItemName(value)
    local text = TrimText(value)
    text = text:gsub("[%c#\t]+", " ")
    text = text:gsub("%s+", " ")
    return TrimText(text)
  end

  local function BuildLootItemBaseKey(payload)
    local itemID = tonumber(type(payload) == "table" and payload.itemID) or ExtractItemID(type(payload) == "table" and payload.link or nil)
    if itemID then
      return "ITEM-" .. tostring(math.floor(itemID))
    end

    local name = NormalizeLootItemName(type(payload) == "table" and payload.name or "")
    if name ~= "" then
      if #name > 40 then
        name = name:sub(1, 40)
      end
      return "NAME-" .. name
    end
    return "UNKNOWN"
  end

  local function BuildLootItemSignature(payload)
    local itemID = tonumber(type(payload) == "table" and payload.itemID) or ExtractItemID(type(payload) == "table" and payload.link or nil)
    if itemID then
      return "ITEM:" .. tostring(math.floor(itemID))
    end
    local name = NormalizeLootItemName(type(payload) == "table" and payload.name or "")
    if name ~= "" then
      return "NAME:" .. string.lower(name)
    end
    return "UNKNOWN"
  end

  local function GetCurrentInstanceDifficultyInfo()
    if type(GetInstanceInfo) ~= "function" then
      return nil, ""
    end
    local _, _, difficultyID, difficultyName = GetInstanceInfo()
    return tonumber(difficultyID) or nil, TrimText(difficultyName)
  end

  local function ResolveDetailedItemLevel(link)
    local itemLink = TrimText(link)
    if itemLink == "" then
      return nil
    end
    if type(C_Item) == "table" and type(C_Item.GetDetailedItemLevelInfo) == "function" then
      local ok, itemLevel = pcall(C_Item.GetDetailedItemLevelInfo, itemLink)
      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, itemLink)
      if ok and tonumber(itemLevel) and tonumber(itemLevel) > 0 then
        return tonumber(itemLevel)
      end
    end
    return nil
  end

  local function NormalizeLootItemPayload(payload)
    payload = type(payload) == "table" and payload or {}
    local itemID = tonumber(payload.itemID) or ExtractItemID(payload.link)
    local name = NormalizeLootItemName(payload.name)
    if #name > MAX_ITEM_OPEN_NAME_LENGTH then
      name = name:sub(1, MAX_ITEM_OPEN_NAME_LENGTH)
    end
    local icon = ClipItemOpenText(payload.icon, MAX_ITEM_OPEN_ICON_LENGTH)
    local numericIcon = tonumber(icon)
    if numericIcon then
      icon = math.floor(numericIcon)
    end
    local difficultyID = tonumber(payload.difficultyID or payload.lootDifficultyID or payload.difficulty) or nil
    local difficultyName = TrimText(payload.difficultyName)
    if not difficultyID then
      difficultyID, difficultyName = GetCurrentInstanceDifficultyInfo()
    end
    local link = TrimText(payload.link)
    local itemLevel = ResolveDetailedItemLevel(link) or tonumber(payload.itemLevel) or nil
    if link ~= "" and itemLevel and itemLevel < 100 then
      itemLevel = ResolveDetailedItemLevel(link)
    end
    if itemLevel and itemLevel < 100 and itemID and itemID > 100000 then
      itemLevel = nil
    end
    return {
      rollID = tonumber(payload.rollID) or nil,
      itemID = itemID and math.floor(itemID) or nil,
      itemLevel = itemLevel,
      quality = tonumber(payload.quality) or nil,
      icon = icon,
      name = name,
      link = link,
      difficultyID = difficultyID,
      difficultyName = difficultyName,
      createdAt = tonumber(payload.createdAt) or ((type(GetServerTime) == "function" and GetServerTime()) or (time and time() or 0)),
    }
  end

  local function GetReportToken(memberKey, rollID)
    local reporter = NormalizeCharacterKey(memberKey)
    local localRollId = TrimText(rollID)
    if reporter == "" or localRollId == "" then
      return ""
    end
    return reporter .. ":" .. localRollId
  end

  local function FindLatestOpenItemBySignature(signature)
    local resolvedSignature = TrimText(signature)
    if resolvedSignature == "" or resolvedSignature == "UNKNOWN" then
      return nil
    end
    for index = #(runtime.itemOrder or {}), 1, -1 do
      local itemKey = runtime.itemOrder[index]
      local entry = type(runtime.items) == "table" and runtime.items[itemKey] or nil
      if type(entry) == "table" and not entry.awardedAt and TrimText(entry.__lootItemSignature) == resolvedSignature then
        return itemKey, entry
      end
    end
    return nil
  end

  local function QueueLocalChoiceForItem(activeSession, itemKey)
    local selfKey = GetSelfKey()
    if selfKey == "" or not IsJoinedSessionCharacter(activeSession, selfKey) then
      return false
    end
    local entry = type(runtime.items) == "table" and runtime.items[itemKey] or nil
    if type(entry) ~= "table" then
      return false
    end
    local _, localMemberKey = GetSessionMember(activeSession, selfKey)
    local choiceMemberKey = localMemberKey or (IsSessionHostKey(activeSession, selfKey) and TrimText(activeSession.host) or selfKey)
    local selection = ResolveEntrySelection(entry, choiceMemberKey)
    if not IsPendingSelection(selection) then
      return false
    end
    if type(QueueContains) == "function" and QueueContains(itemKey) then
      return true
    end
    runtime.popupQueue = type(runtime.popupQueue) == "table" and runtime.popupQueue or {}
    runtime.popupQueue[#runtime.popupQueue + 1] = itemKey
    return true
  end

  local function BroadcastOfficialLootItem(activeSession, profileName, itemKey, entry, sourceMemberKey, sourceRollID, targetMemberKey)
    local targetKey = NormalizeCharacterKey(targetMemberKey)
    local distribution = targetKey ~= "" and "WHISPER" or GetBroadcastDistribution()
    if not distribution or type(SendSessionComm) ~= "function" then
      return false
    end
    local payload = NormalizeLootItemPayload(entry)
    local function SendWithLink(linkValue)
      return SendSessionComm(
        "ITEM_OPEN",
        distribution,
        targetKey ~= "" and targetKey or nil,
        tostring(activeSession.id or ""),
        profileName,
        itemKey,
        payload.itemID or "",
        payload.itemLevel or "",
        payload.quality or "",
        payload.icon or "",
        payload.name or "",
        ClipItemOpenText(linkValue, MAX_ITEM_OPEN_LINK_LENGTH),
        payload.createdAt or "",
        NormalizeCharacterKey(sourceMemberKey),
        TrimText(sourceRollID)
      )
    end
    local ok = SendWithLink(payload.link or "")
    if ok or TrimText(payload.link) == "" then
      return ok
    end
    return SendWithLink("")
  end

  local function OpenAuthoritativeLootItem(activeSession, profileName, payload, sourceMemberKey, sourceRollID)
    if type(activeSession) ~= "table" or TrimText(profileName) == "" or not IsSelfHost(activeSession) then
      return false, "Only the active session host can open official loot items."
    end
    if not EnsureRuntimeSession(activeSession, profileName) then
      return false, "Could not prepare the active session runtime."
    end

    EnsureRuntimeAuthorityMaps()
    local normalizedPayload = NormalizeLootItemPayload(payload)
    local sourceKey = NormalizeCharacterKey(sourceMemberKey ~= nil and sourceMemberKey or GetSelfKey())
    local localSelfKey = GetSelfKey()
    local rollID = TrimText(sourceRollID ~= nil and sourceRollID or normalizedPayload.rollID)
    local reportToken = GetReportToken(sourceKey, rollID)
    local knownReportToken = reportToken ~= "" and runtime.hostReportItemKeys[reportToken] ~= nil
    local itemKey = reportToken ~= "" and runtime.hostReportItemKeys[reportToken] or nil
    if TrimText(itemKey) == "" and rollID ~= "" then
      itemKey = runtime.hostRollItemKeys[rollID]
    end

    local signature = BuildLootItemSignature(normalizedPayload)
    local entry = nil
    if TrimText(itemKey) ~= "" then
      entry = runtime.items[itemKey]
    elseif not AreCharacterKeysSame(sourceKey, localSelfKey) then
      itemKey, entry = FindLatestOpenItemBySignature(signature)
    end

    local createdNewEntry = type(entry) ~= "table"
    if TrimText(itemKey) == "" or createdNewEntry then
      local baseKey = AUTHORITATIVE_LOOT_ITEM_PREFIX .. BuildLootItemBaseKey(normalizedPayload)
      if type(NextItemKey) == "function" then
        itemKey = NextItemKey(baseKey)
      else
        itemKey = baseKey .. "#" .. tostring(#(runtime.itemOrder or {}) + 1)
      end
      createdNewEntry = true
    end

    entry = EnsureLiveEntry(activeSession, profileName, itemKey, normalizedPayload)
    entry.__authoritativeLoot = true
    entry.__lootItemSignature = signature
    entry.__lastReportSource = sourceKey
    entry.__lastReportRollID = rollID
    entry.createdAt = tonumber(entry.createdAt) or normalizedPayload.createdAt
    if reportToken ~= "" then
      runtime.hostReportItemKeys[reportToken] = itemKey
    end
    if rollID ~= "" then
      runtime.hostRollItemKeys[rollID] = itemKey
    end
    if AreCharacterKeysSame(sourceKey, localSelfKey) and rollID ~= "" then
      runtime.localRollItemKeys[rollID] = itemKey
    end

    QueueLocalChoiceForItem(activeSession, itemKey)
    if createdNewEntry then
      BroadcastOfficialLootItem(activeSession, profileName, itemKey, entry, sourceKey, rollID)
    elseif not AreCharacterKeysSame(sourceKey, localSelfKey) and not knownReportToken then
      BroadcastOfficialLootItem(activeSession, profileName, itemKey, entry, sourceKey, rollID, sourceKey)
    end
    RefreshBoardAndEditor({
      reason = "track",
      itemKey = itemKey,
    })
    if type(RefreshChoicePopup) == "function" then
      RefreshChoicePopup()
    end
    return true, itemKey
  end

  local function ReportLootRollToHost(activeSession, profileName, payload)
    if type(activeSession) ~= "table" or TrimText(profileName) == "" then
      return false, "No active session."
    end
    if IsSelfHost(activeSession) then
      return OpenAuthoritativeLootItem(activeSession, profileName, payload, GetSelfKey(), type(payload) == "table" and payload.rollID or nil)
    end
    if type(SendSessionComm) ~= "function" then
      return false, "Session comms are unavailable."
    end

    EnsureRuntimeAuthorityMaps()
    local normalizedPayload = NormalizeLootItemPayload(payload)
    local selfKey = GetSelfKey()
    local rollID = TrimText(normalizedPayload.rollID)
    local commProfileName = GetSessionCommProfileName(activeSession, profileName)
    if rollID ~= "" then
      runtime.localRollItemKeys[rollID] = "REPORTED"
    end
    local function SendWithLink(linkValue)
      return SendSessionComm(
        "ITEM_REPORT",
        "WHISPER",
        activeSession.host,
        tostring(activeSession.id or ""),
        commProfileName,
        selfKey,
        rollID,
        normalizedPayload.itemID or "",
        normalizedPayload.itemLevel or "",
        normalizedPayload.quality or "",
        normalizedPayload.icon or "",
        normalizedPayload.name or "",
        ClipItemOpenText(linkValue, MAX_ITEM_OPEN_LINK_LENGTH),
        normalizedPayload.createdAt or ""
      )
    end
    local ok = SendWithLink(normalizedPayload.link or "")
    if ok or TrimText(normalizedPayload.link) == "" then
      return ok
    end
    return SendWithLink("")
  end

  local function HasExactFieldCount(fields, opcode)
    local expected = EXPECTED_FIELD_COUNTS[tostring(opcode or "")]
    return expected ~= nil and type(fields) == "table" and #fields == expected
  end

  local function GetSelectionUpdatedAt(entry, memberKey)
    local selection = ResolveEntrySelection(entry, memberKey)
    return tonumber(type(selection) == "table" and selection.selectedAt) or 0
  end

  local function GetSelectionSequence(entry, memberKey)
    local selection = ResolveEntrySelection(entry, memberKey)
    return tonumber(type(selection) == "table" and selection.selectedSeq) or 0
  end

  local function NormalizeVoteUpdatedAt(entry)
    local normalized = {}
    if type(entry) == "table" and type(entry.voteUpdatedAtByVoter) == "table" then
      for voterKey, updatedAt in pairs(entry.voteUpdatedAtByVoter) do
        local normalizedVoterKey = NormalizeCharacterKey(voterKey)
        local normalizedUpdatedAt = tonumber(updatedAt)
        if normalizedVoterKey ~= "" and normalizedUpdatedAt and normalizedUpdatedAt > 0 then
          normalized[normalizedVoterKey] = normalizedUpdatedAt
        end
      end
    end
    if type(entry) == "table" then
      entry.voteUpdatedAtByVoter = normalized
    end
    return normalized
  end

  local function GetVoteUpdatedAt(entry, voterKey)
    local normalizedVoterKey = NormalizeCharacterKey(voterKey)
    if normalizedVoterKey == "" then
      return 0
    end
    local voteUpdatedAtByVoter = NormalizeVoteUpdatedAt(entry)
    return tonumber(voteUpdatedAtByVoter[normalizedVoterKey]) or 0
  end

  local function GetVoteSequence(entry, voterKey)
    local normalizedVoterKey = NormalizeCharacterKey(voterKey)
    if normalizedVoterKey == "" then
      return 0
    end
    local voteSequenceByVoter = type(NormalizeVoteSequence) == "function" and NormalizeVoteSequence(entry) or {}
    return tonumber(voteSequenceByVoter[normalizedVoterKey]) or 0
  end

  local function SetVoteUpdatedAt(entry, voterKey, changedAt)
    if type(entry) ~= "table" then
      return
    end
    local normalizedVoterKey = NormalizeCharacterKey(voterKey)
    local normalizedChangedAt = tonumber(changedAt)
    if normalizedVoterKey == "" or not normalizedChangedAt or normalizedChangedAt <= 0 then
      return
    end
    local voteUpdatedAtByVoter = NormalizeVoteUpdatedAt(entry)
    voteUpdatedAtByVoter[normalizedVoterKey] = normalizedChangedAt
    entry.voteUpdatedAtByVoter = voteUpdatedAtByVoter
  end

  local function SetVoteSequence(entry, voterKey, sequence)
    if type(entry) ~= "table" then
      return
    end
    local normalizedVoterKey = NormalizeCharacterKey(voterKey)
    local normalizedSequence = tonumber(sequence)
    if normalizedVoterKey == "" or not normalizedSequence or normalizedSequence <= 0 then
      return
    end
    local voteSequenceByVoter = type(NormalizeVoteSequence) == "function" and NormalizeVoteSequence(entry) or {}
    voteSequenceByVoter[normalizedVoterKey] = math.floor(normalizedSequence)
    entry.voteSequenceByVoter = voteSequenceByVoter
  end

  local function GetAwardUpdatedAt(entry)
    return tonumber(type(entry) == "table" and (entry.awardUpdatedAt or entry.awardedAt)) or 0
  end

  local function GetTradeUpdatedAt(entry)
    return tonumber(type(entry) == "table" and (entry.tradeUpdatedAt or entry.tradedAt)) or 0
  end

  local function BuildBestRuntimeBoardSyncSnapshot(activeSession, profileName)
    local snapshot = BuildRuntimeBoardHistorySnapshot()
    if type(snapshot) == "table" and type(snapshot.items) == "table" and type(snapshot.itemOrder) == "table" and #snapshot.itemOrder > 0 then
      return snapshot
    end
    if type(activeSession) ~= "table" then
      return nil
    end
    return GetLatestRuntimeBoardSnapshot(profileName, activeSession.id)
  end

  local function RestoreRuntimeBoardFromSyncSnapshot(activeSession, profileName, snapshot)
    if type(activeSession) ~= "table" or TrimText(profileName) == "" or type(snapshot) ~= "table" then
      return false
    end
    runtime.sessionId = tostring(activeSession.id or "")
    runtime.profileName = tostring(profileName or "")
    runtime.host = tostring(activeSession.host or runtime.host or "")
    return RestoreRuntimeBoardSnapshot(activeSession, profileName, snapshot)
  end

  local function CaptureLocalPopupQueue()
    local queue = {}
    for _, itemKey in ipairs(runtime.popupQueue or {}) do
      local resolvedKey = TrimText(itemKey)
      if resolvedKey ~= "" then
        queue[#queue + 1] = resolvedKey
      end
    end
    return queue
  end

  local function RestoreLocalPopupQueue(activeSession, capturedQueue)
    if type(capturedQueue) ~= "table" or #capturedQueue == 0 then
      return
    end

    local selfKey = GetSelfKey()
    if selfKey == "" then
      return
    end

    local _, localMemberKey = GetSessionMember(activeSession, selfKey)
    local choiceMemberKey = localMemberKey or (IsSessionHostKey(activeSession, selfKey) and TrimText(activeSession.host) or selfKey)
    local restoredQueue = {}
    local seen = {}
    for _, itemKey in ipairs(capturedQueue) do
      local entry = type(runtime.items) == "table" and runtime.items[itemKey] or nil
      if type(entry) == "table" and not seen[itemKey] then
        local selection = ResolveEntrySelection(entry, choiceMemberKey)
        if IsPendingSelection(selection) then
          restoredQueue[#restoredQueue + 1] = itemKey
          seen[itemKey] = true
        end
      end
    end
    runtime.popupQueue = restoredQueue
  end

  local function SendBoardSyncStartMessage(targetKey, sessionId, profileName, boardUpdatedAt, boardId, historyProfileName, selectedItemKey)
    local ok = SendSessionComm(
      "BSYNC_START",
      "WHISPER",
      targetKey,
      sessionId,
      profileName,
      boardUpdatedAt,
      boardId,
      historyProfileName,
      selectedItemKey
    )
    if ok then
      return true, false
    end
    ok = SendSessionComm(
      "BSYNC_START",
      "WHISPER",
      targetKey,
      sessionId,
      profileName,
      boardUpdatedAt,
      boardId,
      historyProfileName,
      ""
    )
    return ok, true
  end

  local function SendBoardSyncEndMessage(targetKey, sessionId, profileName, boardId, selectedItemKey)
    local ok = SendSessionComm("BSYNC_END", "WHISPER", targetKey, sessionId, profileName, boardId, selectedItemKey)
    if ok then
      return true, false
    end
    ok = SendSessionComm("BSYNC_END", "WHISPER", targetKey, sessionId, profileName, boardId, "")
    return ok, true
  end

  local function SendBoardSyncItemMessage(targetKey, sessionId, profileName, orderIndex, itemKey, fields)
    return SendSessionComm(
      "BSYNC_ITEM",
      "WHISPER",
      targetKey,
      sessionId,
      profileName,
      tostring(orderIndex),
      TrimText(itemKey),
      TrimText(fields.name),
      fields.link or "",
      fields.icon or "",
      tostring(tonumber(fields.quality) or ""),
      tostring(fields.itemID or ""),
      tostring(tonumber(fields.itemLevel) or ""),
      tostring(tonumber(fields.createdAt) or ""),
      TrimText(fields.awardedTo),
      tostring(tonumber(fields.awardedPoints) or ""),
      TrimText(fields.awardedNote),
      tostring(tonumber(fields.awardedAt) or ""),
      TrimText(fields.ledgerEntryId),
      tostring(tonumber(fields.awardUpdatedAt) or ""),
      TrimText(fields.tradeState),
      tostring(tonumber(fields.tradedAt) or ""),
      NormalizeCharacterKey(fields.tradedBy)
    )
  end

  local function SendBoardSyncItemWithFallback(targetKey, sessionId, profileName, orderIndex, itemKey, entry)
    local attempts = {
      {
        name = ClipBoardSyncText(entry.name, MAX_BOARD_SYNC_ITEM_NAME_LENGTH),
        link = ClipBoardSyncText(entry.link, MAX_BOARD_SYNC_LINK_LENGTH),
        icon = ClipBoardSyncText(entry.icon, MAX_BOARD_SYNC_ICON_LENGTH),
        quality = entry.quality,
        itemID = entry.itemID,
        itemLevel = entry.itemLevel,
        createdAt = entry.createdAt,
        awardedTo = entry.awardedTo,
        awardedPoints = entry.awardedPoints,
        awardedNote = ClipBoardSyncText(entry.awardedNote, MAX_BOARD_SYNC_NOTE_LENGTH),
        awardedAt = entry.awardedAt,
        ledgerEntryId = ClipBoardSyncText(entry.ledgerEntryId, MAX_BOARD_SYNC_LEDGER_ID_LENGTH),
        awardUpdatedAt = entry.awardUpdatedAt,
        tradeState = entry.tradeState,
        tradedAt = entry.tradedAt,
        tradedBy = entry.tradedBy,
      },
      {
        name = ClipBoardSyncText(entry.name, 64),
        link = "",
        icon = ClipBoardSyncText(entry.icon, 48),
        quality = entry.quality,
        itemID = entry.itemID,
        itemLevel = entry.itemLevel,
        createdAt = entry.createdAt,
        awardedTo = entry.awardedTo,
        awardedPoints = entry.awardedPoints,
        awardedNote = ClipBoardSyncText(entry.awardedNote, 32),
        awardedAt = entry.awardedAt,
        ledgerEntryId = "",
        awardUpdatedAt = entry.awardUpdatedAt,
        tradeState = entry.tradeState,
        tradedAt = entry.tradedAt,
        tradedBy = entry.tradedBy,
      },
      {
        name = ClipBoardSyncText(entry.name, 48),
        link = "",
        icon = "",
        quality = entry.quality,
        itemID = entry.itemID,
        itemLevel = entry.itemLevel,
        createdAt = entry.createdAt,
        awardedTo = entry.awardedTo,
        awardedPoints = entry.awardedPoints,
        awardedNote = "",
        awardedAt = entry.awardedAt,
        ledgerEntryId = "",
        awardUpdatedAt = entry.awardUpdatedAt,
        tradeState = entry.tradeState,
        tradedAt = entry.tradedAt,
        tradedBy = entry.tradedBy,
      },
    }

    for attemptIndex, fields in ipairs(attempts) do
      local ok = SendBoardSyncItemMessage(targetKey, sessionId, profileName, orderIndex, itemKey, fields)
      if ok then
        return true, attemptIndex > 1
      end
    end
    return false, false
  end

  local function SendBoardSyncSelectionMessage(targetKey, sessionId, profileName, itemKey, memberKey, fields)
    local color = type(fields.color) == "table" and fields.color or {}
    return SendSessionComm(
      "BSYNC_SEL",
      "WHISPER",
      targetKey,
      sessionId,
      profileName,
      TrimText(itemKey),
      NormalizeCharacterKey(memberKey),
      TrimText(fields.optionKey),
      TrimText(fields.label),
      tostring(tonumber(color[1]) or ""),
      tostring(tonumber(color[2]) or ""),
      tostring(tonumber(color[3]) or ""),
      fields.icon or "",
      NormalizeSelectionNote(fields.note),
      tostring(tonumber(fields.rollValue) or ""),
      TrimText(fields.pointBehavior),
      tostring(tonumber(fields.selectedAt) or ""),
      TrimText(fields.source),
      tostring(tonumber(fields.selectedSeq) or 1)
    )
  end

  local function SendBoardSyncSelectionWithFallback(targetKey, sessionId, profileName, itemKey, memberKey, selection)
    local attempts = {
      {
        optionKey = selection.optionKey,
        label = ClipBoardSyncText(selection.label, MAX_BOARD_SYNC_LABEL_LENGTH),
        color = selection.color,
        icon = ClipBoardSyncText(selection.icon, MAX_BOARD_SYNC_ICON_LENGTH),
        note = ClipBoardSyncText(selection.note, MAX_BOARD_SYNC_NOTE_LENGTH),
        rollValue = selection.rollValue,
        pointBehavior = selection.pointBehavior,
        selectedAt = selection.selectedAt,
        source = ClipBoardSyncText(selection.source, MAX_BOARD_SYNC_SOURCE_LENGTH),
        selectedSeq = selection.selectedSeq,
      },
      {
        optionKey = selection.optionKey,
        label = ClipBoardSyncText(selection.label, 40),
        color = selection.color,
        icon = "",
        note = ClipBoardSyncText(selection.note, 32),
        rollValue = selection.rollValue,
        pointBehavior = selection.pointBehavior,
        selectedAt = selection.selectedAt,
        source = ClipBoardSyncText(selection.source, 16),
        selectedSeq = selection.selectedSeq,
      },
      {
        optionKey = selection.optionKey,
        label = ClipBoardSyncText(selection.label, 32),
        color = selection.color,
        icon = "",
        note = "",
        rollValue = selection.rollValue,
        pointBehavior = selection.pointBehavior,
        selectedAt = selection.selectedAt,
        source = "",
        selectedSeq = selection.selectedSeq,
      },
    }

    for attemptIndex, fields in ipairs(attempts) do
      local ok = SendBoardSyncSelectionMessage(targetKey, sessionId, profileName, itemKey, memberKey, fields)
      if ok then
        return true, attemptIndex > 1
      end
    end
    return false, false
  end

  local function SendBoardSyncSnapshotToTarget(activeSession, profileName, snapshot, targetKey)
    if type(activeSession) ~= "table" or TrimText(profileName) == "" or type(snapshot) ~= "table" then
      return false
    end

    local resolvedTargetKey = NormalizeCharacterKey(targetKey)
    if resolvedTargetKey == "" or type(SendSessionComm) ~= "function" then
      return false
    end

    local sessionId = TrimText(activeSession.id)
    local boardUpdatedAt = tonumber(snapshot.updatedAt) or 0
    local boardId = TrimText(snapshot.boardId)
    local historyProfileName = TrimText(snapshot.historyProfileName ~= "" and snapshot.historyProfileName or profileName)
    local selectedItemKey = TrimText(snapshot.selectedItemKey)

    local startOk = false
    local startTruncated = false
    startOk, startTruncated = SendBoardSyncStartMessage(resolvedTargetKey, sessionId, profileName, boardUpdatedAt, boardId, historyProfileName, selectedItemKey)
    if not startOk then
      return false
    end
    local hadTruncation = startTruncated
    local droppedRows = 0

    for orderIndex, itemKey in ipairs(snapshot.itemOrder or {}) do
      local entry = type(snapshot.items) == "table" and snapshot.items[itemKey] or nil
      if type(entry) == "table" then
        local itemSent, itemTruncated = SendBoardSyncItemWithFallback(resolvedTargetKey, sessionId, profileName, orderIndex, itemKey, entry)
        if itemSent then
          hadTruncation = hadTruncation or itemTruncated
          local selectionKeys = {}
          for memberKey in pairs(entry.selections or {}) do
            selectionKeys[#selectionKeys + 1] = memberKey
          end
          table.sort(selectionKeys, function(left, right)
            return string.lower(tostring(left or "")) < string.lower(tostring(right or ""))
          end)
          for _, memberKey in ipairs(selectionKeys) do
            local selection = entry.selections and entry.selections[memberKey] or nil
            if type(selection) == "table" then
              local selectionSent, selectionTruncated = SendBoardSyncSelectionWithFallback(
                resolvedTargetKey,
                sessionId,
                profileName,
                itemKey,
                memberKey,
                selection
              )
              if selectionSent then
                hadTruncation = hadTruncation or selectionTruncated
              else
                droppedRows = droppedRows + 1
              end
            end
          end

          local voteKeys = {}
          local votesByVoter = NormalizeEntryVotes(entry)
          for voterKey in pairs(votesByVoter or {}) do
            voteKeys[#voteKeys + 1] = voterKey
          end
          table.sort(voteKeys, function(left, right)
            return string.lower(tostring(left or "")) < string.lower(tostring(right or ""))
          end)
          for _, voterKey in ipairs(voteKeys) do
            local targetMemberKey = NormalizeCharacterKey(votesByVoter[voterKey])
            if targetMemberKey ~= "" then
              local voteOk = SendSessionComm(
                "BSYNC_VOTE",
                "WHISPER",
                resolvedTargetKey,
                sessionId,
                profileName,
                TrimText(itemKey),
                NormalizeCharacterKey(voterKey),
                targetMemberKey,
                tostring(tonumber(type(entry.voteUpdatedAtByVoter) == "table" and entry.voteUpdatedAtByVoter[voterKey]) or ""),
                tostring(tonumber(type(entry.voteSequenceByVoter) == "table" and entry.voteSequenceByVoter[voterKey]) or 1)
              )
              if not voteOk then
                droppedRows = droppedRows + 1
              end
            end
          end
        else
          droppedRows = droppedRows + 1
        end
      end
    end

    local endOk, endTruncated = SendBoardSyncEndMessage(resolvedTargetKey, sessionId, profileName, boardId, selectedItemKey)
    hadTruncation = hadTruncation or endTruncated
    if not endOk then
      return false
    end
    return true, {
      hadTruncation = hadTruncation,
      droppedRows = droppedRows,
    }
  end

  local function SendActiveLiveBoardSyncFlow()
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or TrimText(profileName) == "" then
      if type(Print) == "function" then
        Print("No active loot session.")
      end
      return false, "No active session."
    end
    if not IsLiveSession(activeSession) then
      if type(Print) == "function" then
        Print("Start the prepared session before sending a Live Board sync.")
      end
      return false, "Session is not active."
    end

    local selfKey = GetSelfKey()
    if not IsSessionHostKey(activeSession, selfKey) then
      if type(Print) == "function" then
        Print("Only the loot session host can send a Live Board sync.")
      end
      return false, "Only the host can send a Live Board sync."
    end

    if type(InCombatLockdown) == "function" and InCombatLockdown() then
      if type(Print) == "function" then
        Print("Send Board Sync is unavailable during combat.")
      end
      return false, "Send Board Sync is unavailable during combat."
    end

    local snapshot = BuildBestRuntimeBoardSyncSnapshot(activeSession, profileName)
    if type(snapshot) ~= "table" or type(snapshot.itemOrder) ~= "table" or #snapshot.itemOrder == 0 then
      if type(Print) == "function" then
        Print("No Live Board state is available to sync.")
      end
      return false, "No Live Board state is available."
    end

    local capturedPopupQueue = CaptureLocalPopupQueue()
    RestoreRuntimeBoardFromSyncSnapshot(activeSession, profileName, snapshot)
    RestoreLocalPopupQueue(activeSession, capturedPopupQueue)
    PersistRuntimeBoardHistory({
      itemKey = itemKey,
    })
    RefreshBoardAndEditor({
      reason = "sync",
      editorRefresh = { refreshPages = { Panels = true, LiveBoard = true, Backgrounds = true } },
    })

    local sentCount = 0
    local hadTruncation = false
    local droppedRows = 0
    for memberKey, member in pairs(activeSession.members or {}) do
      if not AreCharacterKeysSame(memberKey, selfKey) and tostring(type(member) == "table" and member.status or "JOINED") == "JOINED" then
        local sentOk, syncMeta = SendBoardSyncSnapshotToTarget(activeSession, profileName, snapshot, memberKey)
        if sentOk then
          sentCount = sentCount + 1
          if type(syncMeta) == "table" then
            droppedRows = (droppedRows or 0) + (tonumber(syncMeta.droppedRows) or 0)
            hadTruncation = hadTruncation or syncMeta.hadTruncation
          end
        end
      end
    end

    if type(Print) == "function" then
      if sentCount > 0 then
        local summary = "Sent Live Board sync to " .. tostring(sentCount) .. " joined member" .. (sentCount == 1 and "" or "s") .. "."
        if hadTruncation then
          summary = summary .. " Some long fields were compacted for transport."
        end
        if (tonumber(droppedRows) or 0) > 0 then
          summary = summary .. " " .. tostring(droppedRows) .. " oversized sync row" .. ((tonumber(droppedRows) or 0) == 1 and " was" or "s were") .. " skipped."
        end
        Print(summary)
      else
        Print("No joined session members were available for a Live Board sync.")
      end
    end
    return sentCount > 0, sentCount
  end

  local function RequestManualLootLedgerEntryFlow(profileName, memberKey, itemName, points, note)
    local activeSession, activeProfileName = GetActiveLootSession()
    local resolvedProfileName = TrimText(profileName)
    if resolvedProfileName == "" then
      resolvedProfileName = TrimText(activeProfileName)
    end
    if resolvedProfileName == "" then
      return false, "No profile is active."
    end

    local selfKey = GetSelfKey()
    local access = type(GetLootProfileAccessInfo) == "function" and GetLootProfileAccessInfo(resolvedProfileName, selfKey) or nil
    if not (type(access) == "table" and access.canEditManualPoints) then
      return false, "Your current role cannot add manual points."
    end

    local requestId = BuildManualLedgerRequestId("MLA")
    local liveSession = type(activeSession) == "table"
      and IsLiveSession(activeSession)
      and DoesRuntimeSessionMatch(activeSession, activeProfileName, TrimText(activeSession.id), resolvedProfileName)

    if liveSession then
      if not IsJoinedSessionCharacter(activeSession, selfKey) then
        return false, "You are not joined to the active session."
      end
      if IsSelfHost(activeSession) then
        local ok, entry, ledgerRow = ApplyManualLedgerAdd(resolvedProfileName, memberKey, itemName, points, note, selfKey, requestId, "", GetCurrentTimestamp(), activeSession.id)
        if ok and type(entry) == "table" then
          BroadcastLootChangeWithFallback(
            resolvedProfileName,
            BuildManualLedgerAddDeltaChange(activeSession, memberKey, entry, selfKey),
            BroadcastManualLedgerAdd,
            activeSession,
            resolvedProfileName,
            memberKey,
            entry,
            selfKey
          )
          RefreshManualLedgerViews()
        end
        return ok, entry or ledgerRow, "BROADCAST"
      end

      if type(SendSessionComm) ~= "function" then
        return false, "Session comms are unavailable."
      end
      local sent = SendSessionComm(
        "LL_ADD_REQ",
        "WHISPER",
        activeSession.host,
        tostring(activeSession.id or ""),
        GetSessionCommProfileName(activeSession, resolvedProfileName),
        requestId,
        NormalizeCharacterKey(memberKey),
        ClipManualLedgerText(itemName, MAX_MANUAL_LEDGER_NAME_LENGTH),
        tostring(tonumber(points) or 0),
        ClipManualLedgerText(note, MAX_MANUAL_LEDGER_NOTE_LENGTH),
        tostring(GetCurrentTimestamp())
      )
      if sent then
        return true, "Manual point request sent to the session host.", "REQUEST_SENT"
      end
      return false, "Could not send manual point request to the session host."
    end

    local ok, entry = ApplyManualLedgerAdd(resolvedProfileName, memberKey, itemName, points, note, selfKey, requestId, "", GetCurrentTimestamp(), "")
    if ok then
      RefreshManualLedgerViews()
    end
    return ok, entry, "LOCAL"
  end

  local function RequestManualLootLedgerDeleteFlow(profileName, memberKey, entryId)
    local activeSession, activeProfileName = GetActiveLootSession()
    local resolvedProfileName = TrimText(profileName)
    if resolvedProfileName == "" then
      resolvedProfileName = TrimText(activeProfileName)
    end
    if resolvedProfileName == "" then
      return false, "No profile is active."
    end

    local selfKey = GetSelfKey()
    local access = type(GetLootProfileAccessInfo) == "function" and GetLootProfileAccessInfo(resolvedProfileName, selfKey) or nil
    if not (type(access) == "table" and access.canEditManualPoints) then
      return false, "Your current role cannot delete manual points."
    end

    local requestId = BuildManualLedgerRequestId("MLD")
    local liveSession = type(activeSession) == "table"
      and IsLiveSession(activeSession)
      and DoesRuntimeSessionMatch(activeSession, activeProfileName, TrimText(activeSession.id), resolvedProfileName)

    if liveSession then
      if not IsJoinedSessionCharacter(activeSession, selfKey) then
        return false, "You are not joined to the active session."
      end
      if IsSelfHost(activeSession) then
        local ok, result = ApplyManualLedgerDelete(resolvedProfileName, memberKey, entryId)
        if ok then
          BroadcastLootChangeWithFallback(
            resolvedProfileName,
            BuildManualLedgerDeleteDeltaChange(memberKey, entryId),
            BroadcastManualLedgerDelete,
            activeSession,
            resolvedProfileName,
            memberKey,
            entryId,
            GetCurrentTimestamp()
          )
          RefreshManualLedgerViews()
        end
        return ok, result, "BROADCAST"
      end

      if type(SendSessionComm) ~= "function" then
        return false, "Session comms are unavailable."
      end
      local sent = SendSessionComm(
        "LL_DEL_REQ",
        "WHISPER",
        activeSession.host,
        tostring(activeSession.id or ""),
        GetSessionCommProfileName(activeSession, resolvedProfileName),
        requestId,
        NormalizeCharacterKey(memberKey),
        ClipManualLedgerText(entryId, MAX_MANUAL_LEDGER_ID_LENGTH),
        tostring(GetCurrentTimestamp())
      )
      if sent then
        return true, "Manual point delete request sent to the session host.", "REQUEST_SENT"
      end
      return false, "Could not send manual point delete request to the session host."
    end

    local ok, result = ApplyManualLedgerDelete(resolvedProfileName, memberKey, entryId)
    if ok then
      RefreshManualLedgerViews()
    end
    return ok, result, "LOCAL"
  end

  local function RequestLootLedgerMainAltFlow(profileName, characterKey, role, mainCharacter)
    local activeSession, activeProfileName = GetActiveLootSession()
    local resolvedProfileName = TrimText(profileName)
    if resolvedProfileName == "" then
      resolvedProfileName = TrimText(activeProfileName)
    end
    if resolvedProfileName == "" then
      return false, "No profile is active."
    end

    local selfKey = GetSelfKey()
    local access = type(GetLootProfileAccessInfo) == "function" and GetLootProfileAccessInfo(resolvedProfileName, selfKey) or nil
    if not (type(access) == "table" and access.canEditMainAlt) then
      return false, "Your current role cannot change Main / Alt links."
    end

    local resolvedRole = ResolveLootLedgerRole(role)
    local requestId = BuildManualLedgerRequestId("MAL")
    local changedAt = GetCurrentTimestamp()
    local openSession = type(activeSession) == "table"
      and DoesRuntimeSessionMatch(activeSession, activeProfileName, TrimText(activeSession.id), resolvedProfileName)

    if openSession then
      if not IsJoinedSessionCharacter(activeSession, selfKey) then
        return false, "You are not joined to the active session."
      end
      if IsSelfHost(activeSession) then
        local ok, result = ApplyLootLedgerMainAlt(resolvedProfileName, characterKey, resolvedRole, mainCharacter)
        if ok then
          BroadcastLootChangeWithFallback(
            resolvedProfileName,
            BuildLootLedgerMainAltDeltaChange(characterKey, resolvedRole, mainCharacter),
            BroadcastLootLedgerMainAlt,
            activeSession,
            resolvedProfileName,
            characterKey,
            resolvedRole,
            mainCharacter,
            changedAt,
            selfKey
          )
          RefreshManualLedgerViews()
        end
        return ok, result, "BROADCAST"
      end

      if type(SendSessionComm) ~= "function" then
        return false, "Session comms are unavailable."
      end
      local sent = SendSessionComm(
        "LL_MA_REQ",
        "WHISPER",
        activeSession.host,
        tostring(activeSession.id or ""),
        GetSessionCommProfileName(activeSession, resolvedProfileName),
        requestId,
        ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
        resolvedRole,
        ClipManualLedgerText(NormalizeCharacterKey(mainCharacter), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
        tostring(changedAt)
      )
      if sent then
        return true, "Main / Alt update sent to the session host.", "REQUEST_SENT"
      end
      return false, "Could not send Main / Alt update to the session host."
    end

    local ok, result = ApplyLootLedgerMainAlt(resolvedProfileName, characterKey, resolvedRole, mainCharacter)
    if ok then
      RefreshManualLedgerViews()
    end
    return ok, result, "LOCAL"
  end

  local function RequestLootLedgerCharacterNoteFlow(profileName, characterKey, noteText)
    local activeSession, activeProfileName = GetActiveLootSession()
    local resolvedProfileName = TrimText(profileName)
    if resolvedProfileName == "" then
      resolvedProfileName = TrimText(activeProfileName)
    end
    if resolvedProfileName == "" then
      return false, "No profile is active."
    end

    local selfKey = GetSelfKey()
    local access = type(GetLootProfileAccessInfo) == "function" and GetLootProfileAccessInfo(resolvedProfileName, selfKey) or nil
    if not (type(access) == "table" and access.canEditNotes) then
      return false, "Your current role cannot edit notes."
    end

    local requestId = BuildManualLedgerRequestId("NT")
    local changedAt = GetCurrentTimestamp()
    local openSession = type(activeSession) == "table"
      and DoesRuntimeSessionMatch(activeSession, activeProfileName, TrimText(activeSession.id), resolvedProfileName)

    if openSession then
      if not IsJoinedSessionCharacter(activeSession, selfKey) then
        return false, "You are not joined to the active session."
      end
      if IsSelfHost(activeSession) then
        local ok, result = ApplyLootLedgerCharacterNote(resolvedProfileName, characterKey, noteText)
        if ok then
          BroadcastLootChangeWithFallback(
            resolvedProfileName,
            BuildLootLedgerCharacterNoteDeltaChange(characterKey, noteText),
            BroadcastLootLedgerCharacterNote,
            activeSession,
            resolvedProfileName,
            characterKey,
            noteText,
            changedAt,
            selfKey
          )
          RefreshManualLedgerViews()
        end
        return ok, result, "BROADCAST"
      end

      if type(SendSessionComm) ~= "function" then
        return false, "Session comms are unavailable."
      end
      local sent = SendSessionComm(
        "LL_NOTE_REQ",
        "WHISPER",
        activeSession.host,
        tostring(activeSession.id or ""),
        GetSessionCommProfileName(activeSession, resolvedProfileName),
        requestId,
        ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
        ClipManualLedgerText(noteText, MAX_LOOT_LEDGER_NOTE_LENGTH),
        tostring(changedAt)
      )
      if sent then
        return true, "Character note update sent to the session host.", "REQUEST_SENT"
      end
      return false, "Could not send character note update to the session host."
    end

    local ok, result = ApplyLootLedgerCharacterNote(resolvedProfileName, characterKey, noteText)
    if ok then
      RefreshManualLedgerViews()
    end
    return ok, result, "LOCAL"
  end

  local function RequestLootLedgerCharacterDeleteFlow(profileName, characterKey)
    local activeSession, activeProfileName = GetActiveLootSession()
    local resolvedProfileName = TrimText(profileName)
    if resolvedProfileName == "" then
      resolvedProfileName = TrimText(activeProfileName)
    end
    if resolvedProfileName == "" then
      return false, "No profile is active."
    end

    local selfKey = GetSelfKey()
    local access = type(GetLootProfileAccessInfo) == "function" and GetLootProfileAccessInfo(resolvedProfileName, selfKey) or nil
    if not (type(access) == "table" and access.canDeleteLootListCharacter) then
      return false, "Your current role cannot delete Loot List characters."
    end

    local requestId = BuildManualLedgerRequestId("CD")
    local changedAt = GetCurrentTimestamp()
    local openSession = type(activeSession) == "table"
      and DoesRuntimeSessionMatch(activeSession, activeProfileName, TrimText(activeSession.id), resolvedProfileName)

    if openSession then
      if not IsJoinedSessionCharacter(activeSession, selfKey) then
        return false, "You are not joined to the active session."
      end
      if IsSelfHost(activeSession) then
        local ok, result = ApplyLootLedgerCharacterDelete(resolvedProfileName, characterKey)
        if ok then
          BroadcastLootChangeWithFallback(
            resolvedProfileName,
            BuildLootLedgerCharacterDeleteDeltaChange(characterKey),
            BroadcastLootLedgerCharacterDelete,
            activeSession,
            resolvedProfileName,
            characterKey,
            changedAt,
            selfKey
          )
          RefreshManualLedgerViews()
        end
        return ok, result, "BROADCAST"
      end

      if type(SendSessionComm) ~= "function" then
        return false, "Session comms are unavailable."
      end
      local sent = SendSessionComm(
        "LL_CHAR_DEL_REQ",
        "WHISPER",
        activeSession.host,
        tostring(activeSession.id or ""),
        GetSessionCommProfileName(activeSession, resolvedProfileName),
        requestId,
        ClipManualLedgerText(NormalizeCharacterKey(characterKey), MAX_LOOT_LEDGER_CHARACTER_LENGTH),
        tostring(changedAt)
      )
      if sent then
        return true, "Character delete request sent to the session host.", "REQUEST_SENT"
      end
      return false, "Could not send character delete request to the session host."
    end

    local ok, result = ApplyLootLedgerCharacterDelete(resolvedProfileName, characterKey)
    if ok then
      RefreshManualLedgerViews()
    end
    return ok, result, "LOCAL"
  end

  local function HandleManualLedgerAddRequest(fields, sender)
    if not HasExactFieldCount(fields, "LL_ADD_REQ") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not IsSelfHost(activeSession) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local requestId = ClipManualLedgerText(fields[4], MAX_MANUAL_LEDGER_ID_LENGTH)
    local memberKey = NormalizeCharacterKey(fields[5])
    local itemName = ClipManualLedgerText(fields[6], MAX_MANUAL_LEDGER_NAME_LENGTH)
    local points = tonumber(fields[7]) or 0
    local note = ClipManualLedgerText(fields[8], MAX_MANUAL_LEDGER_NOTE_LENGTH)
    local requestedAt = GetIncomingTimestamp(fields[9]) or GetCurrentTimestamp()
    local senderKey = NormalizeSenderKey(sender)

    if requestId == "" or not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not CanSessionCharacterEditManualPoints(activeSession, profileName, senderKey) then
      return
    end

    local ok, entry = ApplyManualLedgerAdd(profileName, memberKey, itemName, points, note, senderKey, requestId, "", requestedAt, sessionId)
    if ok and type(entry) == "table" then
      BroadcastLootChangeWithFallback(
        profileName,
        BuildManualLedgerAddDeltaChange(activeSession, memberKey, entry, senderKey),
        BroadcastManualLedgerAdd,
        activeSession,
        profileName,
        memberKey,
        entry,
        senderKey
      )
      RefreshManualLedgerViews()
    end
  end

  local function HandleManualLedgerAddBroadcast(fields, sender)
    if not HasExactFieldCount(fields, "LL_ADD") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or IsSelfHost(activeSession) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local entryId = ClipManualLedgerText(fields[4], MAX_MANUAL_LEDGER_ID_LENGTH)
    local memberKey = NormalizeCharacterKey(fields[5])
    local itemName = ClipManualLedgerText(fields[6], MAX_MANUAL_LEDGER_NAME_LENGTH)
    local points = tonumber(fields[7]) or 0
    local note = ClipManualLedgerText(fields[8], MAX_MANUAL_LEDGER_NOTE_LENGTH)
    local awardedAt = GetIncomingTimestamp(fields[9]) or GetCurrentTimestamp()
    local grantedBy = NormalizeCharacterKey(fields[10])

    if entryId == "" or not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end

    local ok = ApplyManualLedgerAdd(profileName, memberKey, itemName, points, note, grantedBy, "", entryId, awardedAt, sessionId)
    if ok then
      RefreshManualLedgerViews()
    end
  end

  local function HandleManualLedgerDeleteRequest(fields, sender)
    if not HasExactFieldCount(fields, "LL_DEL_REQ") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not IsSelfHost(activeSession) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local requestId = ClipManualLedgerText(fields[4], MAX_MANUAL_LEDGER_ID_LENGTH)
    local memberKey = NormalizeCharacterKey(fields[5])
    local entryId = ClipManualLedgerText(fields[6], MAX_MANUAL_LEDGER_ID_LENGTH)
    local senderKey = NormalizeSenderKey(sender)

    if requestId == "" or entryId == "" or not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not CanSessionCharacterEditManualPoints(activeSession, profileName, senderKey) then
      return
    end

    local ok = ApplyManualLedgerDelete(profileName, memberKey, entryId)
    if ok then
      BroadcastLootChangeWithFallback(
        profileName,
        BuildManualLedgerDeleteDeltaChange(memberKey, entryId),
        BroadcastManualLedgerDelete,
        activeSession,
        profileName,
        memberKey,
        entryId,
        GetCurrentTimestamp()
      )
      RefreshManualLedgerViews()
    end
  end

  local function HandleManualLedgerDeleteBroadcast(fields, sender)
    if not HasExactFieldCount(fields, "LL_DEL") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or IsSelfHost(activeSession) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local entryId = ClipManualLedgerText(fields[4], MAX_MANUAL_LEDGER_ID_LENGTH)
    local memberKey = NormalizeCharacterKey(fields[5])
    if entryId == "" or not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end

    local ok = ApplyManualLedgerDelete(profileName, memberKey, entryId)
    if ok then
      RefreshManualLedgerViews()
    end
  end

  local function HandleLootLedgerMainAltRequest(fields, sender)
    if not HasExactFieldCount(fields, "LL_MA_REQ") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not IsSelfHost(activeSession) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local requestId = ClipManualLedgerText(fields[4], MAX_MANUAL_LEDGER_ID_LENGTH)
    local characterKey = ClipManualLedgerText(NormalizeCharacterKey(fields[5]), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    local role = ResolveLootLedgerRole(fields[6])
    local mainCharacter = ClipManualLedgerText(NormalizeCharacterKey(fields[7]), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    local changedAt = GetIncomingTimestamp(fields[8]) or GetCurrentTimestamp()
    local senderKey = NormalizeSenderKey(sender)

    if requestId == "" or characterKey == "" or not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not CanSessionCharacterEditMainAlt(activeSession, profileName, senderKey) then
      return
    end

    local ok = ApplyLootLedgerMainAlt(profileName, characterKey, role, mainCharacter)
    if ok then
      BroadcastLootChangeWithFallback(
        profileName,
        BuildLootLedgerMainAltDeltaChange(characterKey, role, mainCharacter),
        BroadcastLootLedgerMainAlt,
        activeSession,
        profileName,
        characterKey,
        role,
        mainCharacter,
        changedAt,
        senderKey
      )
      RefreshManualLedgerViews()
    end
  end

  local function HandleLootLedgerMainAltBroadcast(fields, sender)
    if not HasExactFieldCount(fields, "LL_MA") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or IsSelfHost(activeSession) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local characterKey = ClipManualLedgerText(NormalizeCharacterKey(fields[4]), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    local role = ResolveLootLedgerRole(fields[5])
    local mainCharacter = ClipManualLedgerText(NormalizeCharacterKey(fields[6]), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    if characterKey == "" or not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end

    local ok = ApplyLootLedgerMainAlt(profileName, characterKey, role, mainCharacter)
    if ok then
      RefreshManualLedgerViews()
    end
  end

  local function HandleLootLedgerCharacterNoteRequest(fields, sender)
    if not HasExactFieldCount(fields, "LL_NOTE_REQ") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not IsSelfHost(activeSession) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local requestId = ClipManualLedgerText(fields[4], MAX_MANUAL_LEDGER_ID_LENGTH)
    local characterKey = ClipManualLedgerText(NormalizeCharacterKey(fields[5]), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    local noteText = ClipManualLedgerText(fields[6], MAX_LOOT_LEDGER_NOTE_LENGTH)
    local changedAt = GetIncomingTimestamp(fields[7]) or GetCurrentTimestamp()
    local senderKey = NormalizeSenderKey(sender)

    if requestId == "" or characterKey == "" or not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not CanSessionCharacterEditNotes(activeSession, profileName, senderKey) then
      return
    end

    local ok = ApplyLootLedgerCharacterNote(profileName, characterKey, noteText)
    if ok then
      BroadcastLootChangeWithFallback(
        profileName,
        BuildLootLedgerCharacterNoteDeltaChange(characterKey, noteText),
        BroadcastLootLedgerCharacterNote,
        activeSession,
        profileName,
        characterKey,
        noteText,
        changedAt,
        senderKey
      )
      RefreshManualLedgerViews()
    end
  end

  local function HandleLootLedgerCharacterNoteBroadcast(fields, sender)
    if not HasExactFieldCount(fields, "LL_NOTE") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or IsSelfHost(activeSession) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local characterKey = ClipManualLedgerText(NormalizeCharacterKey(fields[4]), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    local noteText = ClipManualLedgerText(fields[5], MAX_LOOT_LEDGER_NOTE_LENGTH)
    if characterKey == "" or not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end

    local ok = ApplyLootLedgerCharacterNote(profileName, characterKey, noteText)
    if ok then
      RefreshManualLedgerViews()
    end
  end

  local function HandleLootLedgerCharacterDeleteRequest(fields, sender)
    if not HasExactFieldCount(fields, "LL_CHAR_DEL_REQ") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not IsSelfHost(activeSession) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local requestId = ClipManualLedgerText(fields[4], MAX_MANUAL_LEDGER_ID_LENGTH)
    local characterKey = ClipManualLedgerText(NormalizeCharacterKey(fields[5]), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    local changedAt = GetIncomingTimestamp(fields[6]) or GetCurrentTimestamp()
    local senderKey = NormalizeSenderKey(sender)

    if requestId == "" or characterKey == "" or not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not CanSessionCharacterDeleteLootListCharacter(activeSession, profileName, senderKey) then
      return
    end

    local ok = ApplyLootLedgerCharacterDelete(profileName, characterKey)
    if ok then
      BroadcastLootChangeWithFallback(
        profileName,
        BuildLootLedgerCharacterDeleteDeltaChange(characterKey),
        BroadcastLootLedgerCharacterDelete,
        activeSession,
        profileName,
        characterKey,
        changedAt,
        senderKey
      )
      RefreshManualLedgerViews()
    end
  end

  local function HandleLootLedgerCharacterDeleteBroadcast(fields, sender)
    if not HasExactFieldCount(fields, "LL_CHAR_DEL") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or IsSelfHost(activeSession) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local characterKey = ClipManualLedgerText(NormalizeCharacterKey(fields[4]), MAX_LOOT_LEDGER_CHARACTER_LENGTH)
    if characterKey == "" or not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end

    local ok = ApplyLootLedgerCharacterDelete(profileName, characterKey)
    if ok then
      RefreshManualLedgerViews()
    end
  end

  local function HandleItemReportMessage(fields, sender)
    if not HasExactFieldCount(fields, "ITEM_REPORT") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not IsSelfHost(activeSession) then
      return
    end
    if not EnsureRuntimeSession(activeSession, profileName) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local reporterKey = NormalizeCharacterKey(fields[4] ~= "" and fields[4] or sender)
    local rollID = TrimText(fields[5])
    if not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if reporterKey == "" or not IsClaimedActorSenderMatch(sender, reporterKey) or not IsJoinedSessionCharacter(activeSession, reporterKey) then
      return
    end

    OpenAuthoritativeLootItem(activeSession, profileName, {
      rollID = tonumber(rollID) or nil,
      itemID = tonumber(fields[6]) or nil,
      itemLevel = tonumber(fields[7]) or nil,
      quality = tonumber(fields[8]) or nil,
      icon = fields[9],
      name = fields[10],
      link = fields[11],
      createdAt = tonumber(fields[12]) or nil,
    }, reporterKey, rollID)
  end

  local function HandleItemOpenMessage(fields, sender)
    if not HasExactFieldCount(fields, "ITEM_OPEN") then
      return
    end
    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local itemKey = TrimText(fields[4])
    if sessionId == "" or incomingProfile == "" or itemKey == "" then
      return
    end

    local activeSession, profileName = GetActiveLootSession()
    if not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end
    if IsSelfHost(activeSession) then
      return
    end
    if not EnsureRuntimeSession(activeSession, profileName) then
      return
    end

    EnsureRuntimeAuthorityMaps()
    PrimeSequence(itemKey)
    local payload = NormalizeLootItemPayload({
      itemID = tonumber(fields[5]) or nil,
      itemLevel = tonumber(fields[6]) or nil,
      quality = tonumber(fields[7]) or nil,
      icon = fields[8],
      name = fields[9],
      link = fields[10],
      createdAt = tonumber(fields[11]) or nil,
    })
    local entry = EnsureLiveEntry(activeSession, profileName, itemKey, payload)
    entry.__authoritativeLoot = true
    entry.__lootItemSignature = BuildLootItemSignature(payload)
    local sourceMemberKey = NormalizeCharacterKey(fields[12])
    local sourceRollID = TrimText(fields[13])
    if AreCharacterKeysSame(sourceMemberKey, GetSelfKey()) and sourceRollID ~= "" then
      runtime.localRollItemKeys[sourceRollID] = itemKey
    end

    QueueLocalChoiceForItem(activeSession, itemKey)
    RefreshBoardAndEditor({
      reason = "track",
      itemKey = itemKey,
    })
    if type(RefreshChoicePopup) == "function" then
      RefreshChoicePopup()
    end
  end

  local function HandleChoiceMessage(fields, sender)
    if not HasExactFieldCount(fields, "CHOICE") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not IsSelfHost(activeSession) then
      return
    end
    if not EnsureRuntimeSession(activeSession, profileName) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local itemKey = TrimText(fields[4])
    local memberKey = NormalizeCharacterKey(fields[5] ~= "" and fields[5] or sender)
    local optionKey = TrimText(fields[6])
    local optionLabel = TrimText(fields[7])
    local optionNote = NormalizeSelectionNote(fields[8])
    local optionRollValue = tonumber(fields[9])
    local optionSelectedAt = GetIncomingTimestamp(fields[10])
    local optionSelectedSeq = tonumber(fields[11])
    if not optionSelectedAt or not optionSelectedSeq or optionSelectedSeq <= 0 then
      return
    end
    if not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if itemKey == "" or memberKey == "" then
      return
    end
    if not IsClaimedActorSenderMatch(sender, memberKey) then
      return
    end
    if not IsJoinedSessionCharacter(activeSession, memberKey) then
      return
    end

    PrimeSequence(itemKey)
    local entry = EnsureLiveEntry(activeSession, profileName, itemKey, {
      name = runtime.items[itemKey] and runtime.items[itemKey].name or "Awaiting item info",
    })
    local currentSelectedSeq = GetSelectionSequence(entry, memberKey)
    local currentSelectedAt = GetSelectionUpdatedAt(entry, memberKey)
    if optionSelectedSeq < currentSelectedSeq or (optionSelectedSeq == currentSelectedSeq and optionSelectedAt < currentSelectedAt) then
      return
    end
    local option = ResolveRollOption(activeSession, profileName, optionKey, optionLabel)
    option.note = optionNote
    option.rollValue = optionRollValue
    option.selectedAt = optionSelectedAt
    option.selectedSeq = optionSelectedSeq
    RecordChoice(entry, memberKey, option, "REMOTE")
    local storedSelectedAt = GetSelectionUpdatedAt(entry, memberKey)
    local storedSelectedSeq = GetSelectionSequence(entry, memberKey)
    local distribution = GetBroadcastDistribution()
    if distribution and type(SendSessionComm) == "function" then
      SendSessionComm(
        "RCHOICE",
        distribution,
        nil,
        sessionId,
        GetSessionCommProfileName(activeSession, profileName),
        itemKey,
        memberKey,
        optionKey,
        optionLabel,
        optionNote,
        optionRollValue or "",
        storedSelectedAt or "",
        storedSelectedSeq or ""
      )
    end
    RefreshBoardAndEditor({
      reason = "choice",
      itemKey = itemKey,
    })
  end

  local function HandleMirroredChoiceMessage(fields, sender)
    if not HasExactFieldCount(fields, "RCHOICE") then
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or IsSelfHost(activeSession) then
      return
    end
    if not EnsureRuntimeSession(activeSession, profileName) then
      return
    end

    local sessionId = TrimText(fields[2])
    local incomingProfile = TrimText(fields[3])
    local itemKey = TrimText(fields[4])
    local memberKey = NormalizeCharacterKey(fields[5] ~= "" and fields[5] or sender)
    local optionKey = TrimText(fields[6])
    local optionLabel = TrimText(fields[7])
    local optionNote = NormalizeSelectionNote(fields[8])
    local optionRollValue = tonumber(fields[9])
    local optionSelectedAt = GetIncomingTimestamp(fields[10])
    local optionSelectedSeq = tonumber(fields[11])
    if not optionSelectedAt or not optionSelectedSeq or optionSelectedSeq <= 0 then
      return
    end
    if not DoesRuntimeSessionMatch(activeSession, profileName, sessionId, incomingProfile) then
      return
    end
    if itemKey == "" or memberKey == "" then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end
    if not IsJoinedSessionCharacter(activeSession, memberKey) then
      return
    end

    PrimeSequence(itemKey)
    local entry = EnsureLiveEntry(activeSession, profileName, itemKey, {
      name = runtime.items[itemKey] and runtime.items[itemKey].name or "Awaiting item info",
    })
    local currentSelectedSeq = GetSelectionSequence(entry, memberKey)
    local currentSelectedAt = GetSelectionUpdatedAt(entry, memberKey)
    if optionSelectedSeq < currentSelectedSeq or (optionSelectedSeq == currentSelectedSeq and optionSelectedAt < currentSelectedAt) then
      return
    end
    local option = ResolveRollOption(activeSession, profileName, optionKey, optionLabel)
    option.note = optionNote
    option.rollValue = optionRollValue
    option.selectedAt = optionSelectedAt
    option.selectedSeq = optionSelectedSeq
    RecordChoice(entry, memberKey, option, "MIRROR")
    RefreshBoardAndEditor({
      reason = "choice",
      itemKey = itemKey,
    })
  end

  local function HandleAwardMessage(fields, sender)
    if not HasExactFieldCount(fields, "AWARD") then
      return
    end
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local itemKey = TrimText(fields[4])
    local memberKey = NormalizeCharacterKey(fields[5])
    local itemName = TrimText(fields[6])
    local itemLevel = tonumber(fields[7])
    local points = tonumber(fields[8]) or 0
    local note = TrimText(fields[9])
    local changedAt = GetIncomingTimestamp(fields[10])
    if not changedAt then
      return
    end
    if sessionId == "" or profileName == "" or itemKey == "" or memberKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesRuntimeSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end

    local entry = runtime.items[itemKey]
    if changedAt and changedAt < GetAwardUpdatedAt(entry) then
      return
    end

    local ok = ApplyAwardMessage(itemKey, memberKey, itemName, itemLevel, points, note, activeSession, activeProfileName, changedAt)
    if ok then
      RefreshBoardAndEditor({
        reason = "award",
        itemKey = itemKey,
      })
    end
  end

  local function HandleUnassignMessage(fields, sender)
    if not HasExactFieldCount(fields, "UNASSIGN") then
      return
    end
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local itemKey = TrimText(fields[4])
    local changedAt = GetIncomingTimestamp(fields[5])
    if not changedAt then
      return
    end
    if sessionId == "" or profileName == "" or itemKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesRuntimeSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end

    if not EnsureRuntimeSession(activeSession, activeProfileName) then
      return
    end

    local entry = runtime.items[itemKey]
    if not entry or not entry.awardedAt then
      return
    end
    if changedAt and changedAt < GetAwardUpdatedAt(entry) then
      return
    end

    local ok = RemoveAwardFromEntry(activeProfileName, entry, changedAt)
    if ok then
      RefreshBoardAndEditor({
        reason = "unassign",
        itemKey = itemKey,
      })
    end
  end

  local function HandleTradeMessage(fields, sender)
    if not HasExactFieldCount(fields, "TRADE") then
      return
    end
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local itemKey = TrimText(fields[4])
    local tradeState = string.upper(TrimText(fields[5]))
    local changedAt = GetIncomingTimestamp(fields[6])
    local changedBy = NormalizeCharacterKey(fields[7])
    if not changedAt then
      return
    end
    if sessionId == "" or profileName == "" or itemKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesRuntimeSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end
    if not EnsureRuntimeSession(activeSession, activeProfileName) then
      return
    end

    local entry = runtime.items[itemKey]
    if type(entry) ~= "table" or not entry.awardedAt then
      return
    end
    if changedAt < GetTradeUpdatedAt(entry) then
      return
    end

    if tradeState == "TRADED" then
      entry.tradeState = "TRADED"
      entry.tradedAt = changedAt
      entry.tradedBy = changedBy ~= "" and changedBy or NormalizeSenderKey(sender)
      entry.tradeUpdatedAt = changedAt
    else
      entry.tradeState = nil
      entry.tradedAt = nil
      entry.tradedBy = nil
      entry.tradeUpdatedAt = changedAt
    end
    runtime.boardUpdatedAt = math.max(tonumber(runtime.boardUpdatedAt) or 0, changedAt)
    PersistRuntimeBoardHistory({
      itemKey = itemKey,
      fieldKeys = {
        "awardedTo",
        "awardedPoints",
        "awardedNote",
        "awardedAt",
        "ledgerEntryId",
        "awardUpdatedAt",
        "tradeState",
        "tradedAt",
        "tradedBy",
        "tradeUpdatedAt",
      },
    })
    RefreshBoardAndEditor({
      reason = "trade",
      itemKey = itemKey,
    })
  end

  local function HandleVoteMessage(fields, sender)
    if not HasExactFieldCount(fields, "VOTE") then
      return
    end
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local itemKey = TrimText(fields[4])
    local voterKey = NormalizeCharacterKey(fields[5] ~= "" and fields[5] or sender)
    local targetKey = NormalizeCharacterKey(fields[6])
    local changedAt = GetIncomingTimestamp(fields[7])
    local voteSeq = tonumber(fields[8])
    if not changedAt or not voteSeq or voteSeq <= 0 then
      return
    end
    if sessionId == "" or profileName == "" or itemKey == "" or voterKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesRuntimeSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsClaimedActorSenderMatch(sender, voterKey) then
      return
    end
    if not IsJoinedSessionCharacter(activeSession, voterKey) then
      return
    end
    if not CanSessionCharacterVote(activeSession, activeProfileName, voterKey) then
      return
    end
    if not EnsureRuntimeSession(activeSession, activeProfileName) then
      return
    end

    local entry = runtime.items[itemKey]
    if not entry then
      entry = EnsureLiveEntry(activeSession, activeProfileName, itemKey, {
        name = "Awaiting item info",
      })
    end
    if not entry or entry.awardedAt then
      return
    end
    local currentVoteSeq = GetVoteSequence(entry, voterKey)
    local currentVoteChangedAt = GetVoteUpdatedAt(entry, voterKey)
    if voteSeq < currentVoteSeq or (voteSeq == currentVoteSeq and changedAt < currentVoteChangedAt) then
      return
    end

    SetEntryVoteTarget(entry, voterKey, targetKey ~= "" and targetKey or nil)
    SetVoteUpdatedAt(entry, voterKey, changedAt or ((type(GetServerTime) == "function" and GetServerTime()) or (time and time() or 0)))
    SetVoteSequence(entry, voterKey, voteSeq)
    if type(RecordLootVoteStat) == "function" and type(IsSelfHost) == "function" and IsSelfHost(activeSession) then
      RecordLootVoteStat(activeProfileName, {
        sessionId = sessionId,
        itemKey = itemKey,
        voter = voterKey,
        target = targetKey,
        votedAt = changedAt,
      })
    end
    PersistRuntimeBoardHistory({
      itemKey = itemKey,
      voterKey = voterKey,
    })
    RefreshBoardAndEditor({
      reason = "vote",
      itemKey = itemKey,
    })
  end

  GetBoardSyncToken = function(sessionId, profileName, senderKey)
    return string.lower(TrimText(sessionId) .. "|" .. TrimText(profileName) .. "|" .. NormalizeCharacterKey(senderKey))
  end

  local function HandleBoardSyncStart(fields, sender)
    if not HasExactFieldCount(fields, "BSYNC_START") then
      return
    end
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local boardUpdatedAt = GetIncomingTimestamp(fields[4])
    if not boardUpdatedAt then
      return
    end
    local boardId = TrimText(fields[5])
    local historyProfileName = TrimText(fields[6])
    local selectedItemKey = TrimText(fields[7])
    if sessionId == "" or profileName == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesRuntimeSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) then
      return
    end
    if boardUpdatedAt > 0 and boardUpdatedAt < (tonumber(runtime.boardUpdatedAt) or 0) then
      return
    end
    if not EnsureRuntimeSession(activeSession, activeProfileName) then
      return
    end

    runtime.boardId = boardId ~= "" and boardId or runtime.boardId
    runtime.historyProfileName = historyProfileName ~= "" and historyProfileName or profileName
    runtime.selectedItemKey = nil
    runtime.selectedMemberKey = nil
    runtime.itemCounts = {}
    runtime.itemOrder = {}
    runtime.items = {}
    runtime.popupQueue = {}
    incomingBoardSyncs[GetBoardSyncToken(sessionId, profileName, sender)] = {
      selectedItemKey = selectedItemKey,
      updatedAt = boardUpdatedAt,
    }
  end

  local function HandleBoardSyncItem(fields, sender)
    if not HasExactFieldCount(fields, "BSYNC_ITEM") and not (type(fields) == "table" and #fields == 18) then
      return
    end
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local orderIndex = tonumber(fields[4]) or 0
    local itemKey = TrimText(fields[5])
    if sessionId == "" or profileName == "" or itemKey == "" or orderIndex <= 0 then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesRuntimeSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) or not HasBoardSyncState(sessionId, profileName, sender) then
      return
    end
    if not EnsureRuntimeSession(activeSession, activeProfileName) then
      return
    end

    local entry = {
      key = itemKey,
      name = TrimText(fields[6]),
      link = fields[7] ~= "" and fields[7] or nil,
      icon = fields[8] ~= "" and fields[8] or nil,
      quality = tonumber(fields[9]) or nil,
      itemID = tonumber(fields[10]) or ExtractItemID(fields[10]),
      itemLevel = tonumber(fields[11]) or nil,
      createdAt = tonumber(fields[12]) or nil,
      awardedTo = NormalizeCharacterKey(fields[13]),
      awardedPoints = tonumber(fields[14]) or nil,
      awardedNote = TrimText(fields[15]),
      awardedAt = tonumber(fields[16]) or nil,
      ledgerEntryId = TrimText(fields[17]),
      awardUpdatedAt = tonumber(fields[18]) or nil,
      tradeState = TrimText(fields[19]),
      tradedAt = tonumber(fields[20]) or nil,
      tradedBy = NormalizeCharacterKey(fields[21]),
      selections = {},
      votesByVoter = {},
      voteUpdatedAtByVoter = {},
      voteSequenceByVoter = {},
      sessionId = sessionId,
      profileName = profileName,
    }

    runtime.items[itemKey] = entry
    runtime.itemOrder[orderIndex] = itemKey
  end

  local function HandleBoardSyncSelection(fields, sender)
    if not HasExactFieldCount(fields, "BSYNC_SEL") then
      return
    end
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local itemKey = TrimText(fields[4])
    local memberKey = NormalizeCharacterKey(fields[5])
    if sessionId == "" or profileName == "" or itemKey == "" or memberKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesRuntimeSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) or not HasBoardSyncState(sessionId, profileName, sender) then
      return
    end
    if not EnsureRuntimeSession(activeSession, activeProfileName) then
      return
    end

    local entry = runtime.items[itemKey]
    if type(entry) ~= "table" then
      return
    end

    entry.selections = entry.selections or {}
    local selectedAt = GetIncomingTimestamp(fields[15])
    local selectedSeq = tonumber(fields[17])
    if not selectedAt or not selectedSeq or selectedSeq <= 0 then
      return
    end
    local _, storedMemberKey = ResolveEntrySelection(entry, memberKey)
    entry.selections[storedMemberKey or memberKey] = {
      optionKey = TrimText(fields[6]),
      label = TrimText(fields[7]),
      color = {
        tonumber(fields[8]) or 0.82,
        tonumber(fields[9]) or 0.82,
        tonumber(fields[10]) or 0.86,
      },
      icon = fields[11] ~= "" and fields[11] or nil,
      note = NormalizeSelectionNote(fields[12]),
      rollValue = tonumber(fields[13]) or nil,
      pointBehavior = TrimText(fields[14]),
      selectedAt = selectedAt,
      source = TrimText(fields[16]),
      selectedSeq = math.floor(selectedSeq),
    }
  end

  local function HandleBoardSyncVote(fields, sender)
    if not HasExactFieldCount(fields, "BSYNC_VOTE") then
      return
    end
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local itemKey = TrimText(fields[4])
    local voterKey = NormalizeCharacterKey(fields[5])
    local targetKey = NormalizeCharacterKey(fields[6])
    local changedAt = GetIncomingTimestamp(fields[7])
    local voteSeq = tonumber(fields[8])
    if sessionId == "" or profileName == "" or itemKey == "" or voterKey == "" or targetKey == "" or not changedAt or not voteSeq or voteSeq <= 0 then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesRuntimeSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) or not HasBoardSyncState(sessionId, profileName, sender) then
      return
    end
    if not IsJoinedSessionCharacter(activeSession, voterKey) or not CanSessionCharacterVote(activeSession, activeProfileName, voterKey) then
      return
    end
    if not EnsureRuntimeSession(activeSession, activeProfileName) then
      return
    end

    local entry = runtime.items[itemKey]
    if type(entry) ~= "table" then
      return
    end
    entry.votesByVoter = entry.votesByVoter or {}
    entry.votesByVoter[voterKey] = targetKey
    SetVoteUpdatedAt(entry, voterKey, changedAt or (time and time() or 0))
    SetVoteSequence(entry, voterKey, voteSeq)
  end

  local function HandleBoardSyncEnd(fields, sender)
    if not HasExactFieldCount(fields, "BSYNC_END") then
      return
    end
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local boardId = TrimText(fields[4])
    local selectedItemKey = TrimText(fields[5])
    if sessionId == "" or profileName == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesRuntimeSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsSessionHostKey(activeSession, sender) or not HasBoardSyncState(sessionId, profileName, sender) then
      return
    end
    if not EnsureRuntimeSession(activeSession, activeProfileName) then
      return
    end

    local token = GetBoardSyncToken(sessionId, profileName, sender)
    local syncState = incomingBoardSyncs[token]
    incomingBoardSyncs[token] = nil

    local compactOrder = {}
    for _, itemKey in ipairs(runtime.itemOrder or {}) do
      if TrimText(itemKey) ~= "" and type(runtime.items[itemKey]) == "table" then
        compactOrder[#compactOrder + 1] = itemKey
      end
    end
    runtime.itemOrder = compactOrder
    runtime.boardId = boardId ~= "" and boardId or runtime.boardId
    runtime.selectedItemKey = selectedItemKey ~= "" and selectedItemKey or (type(syncState) == "table" and TrimText(syncState.selectedItemKey)) or runtime.itemOrder[#runtime.itemOrder]
    if runtime.selectedItemKey ~= "" and type(runtime.items[runtime.selectedItemKey]) ~= "table" then
      runtime.selectedItemKey = runtime.itemOrder[#runtime.itemOrder]
    end
    runtime.popupQueue = {}
    for _, itemKey in ipairs(runtime.itemOrder) do
      local entry = runtime.items[itemKey]
      if type(entry) == "table" then
        NormalizeEntryVotes(entry)
        NormalizeVoteUpdatedAt(entry)
        if type(NormalizeVoteSequence) == "function" then
          NormalizeVoteSequence(entry)
        end
        if not tonumber(entry.awardedAt) then
          runtime.popupQueue[#runtime.popupQueue + 1] = itemKey
        end
      end
    end
    runtime.boardUpdatedAt = math.max(tonumber(runtime.boardUpdatedAt) or 0, tonumber(type(syncState) == "table" and syncState.updatedAt) or 0)
    runtime.lastBoardSyncSender = NormalizeSenderKey(sender)
    if type(ClearPreviewState) == "function" then
      ClearPreviewState()
    end
    PersistRuntimeBoardHistory()
    RefreshBoardAndEditor({
      reason = "sync",
      itemKey = runtime.selectedItemKey,
      editorRefresh = { refreshPages = { Panels = true, LiveBoard = true, Backgrounds = true } },
    })
    if type(RefreshChoicePopup) == "function" then
      RefreshChoicePopup()
    end
    if type(Print) == "function" then
      Print("Received a Live Board sync from " .. tostring(sender or "session host") .. ".")
    end
  end

  local function HandleSessionComm(fields, sender)
    local opcode = TrimText(type(fields) == "table" and fields[1] or "")
    if opcode ~= "" then
      runtime.lastReceivedOpcode = opcode
      runtime.lastReceivedSender = NormalizeSenderKey(sender)
    end
    local activeSession = GetActiveLootSession()
    local allowPreparedOpcode = opcode == "LL_MA_REQ"
      or opcode == "LL_MA"
      or opcode == "LL_NOTE_REQ"
      or opcode == "LL_NOTE"
      or opcode == "LL_CHAR_DEL_REQ"
      or opcode == "LL_CHAR_DEL"
    if activeSession and not IsLiveSession(activeSession) and not allowPreparedOpcode then
      return false
    end
    if opcode == "CHOICE" then
      HandleChoiceMessage(fields, sender)
      return true
    elseif opcode == "RCHOICE" then
      HandleMirroredChoiceMessage(fields, sender)
      return true
    elseif opcode == "ITEM_REPORT" then
      HandleItemReportMessage(fields, sender)
      return true
    elseif opcode == "ITEM_OPEN" then
      HandleItemOpenMessage(fields, sender)
      return true
    elseif opcode == "AWARD" then
      HandleAwardMessage(fields, sender)
      return true
    elseif opcode == "UNASSIGN" then
      HandleUnassignMessage(fields, sender)
      return true
    elseif opcode == "TRADE" then
      HandleTradeMessage(fields, sender)
      return true
    elseif opcode == "VOTE" then
      HandleVoteMessage(fields, sender)
      return true
    elseif opcode == "LL_ADD_REQ" then
      HandleManualLedgerAddRequest(fields, sender)
      return true
    elseif opcode == "LL_ADD" then
      HandleManualLedgerAddBroadcast(fields, sender)
      return true
    elseif opcode == "LL_DEL_REQ" then
      HandleManualLedgerDeleteRequest(fields, sender)
      return true
    elseif opcode == "LL_DEL" then
      HandleManualLedgerDeleteBroadcast(fields, sender)
      return true
    elseif opcode == "LL_MA_REQ" then
      HandleLootLedgerMainAltRequest(fields, sender)
      return true
    elseif opcode == "LL_MA" then
      HandleLootLedgerMainAltBroadcast(fields, sender)
      return true
    elseif opcode == "LL_NOTE_REQ" then
      HandleLootLedgerCharacterNoteRequest(fields, sender)
      return true
    elseif opcode == "LL_NOTE" then
      HandleLootLedgerCharacterNoteBroadcast(fields, sender)
      return true
    elseif opcode == "LL_CHAR_DEL_REQ" then
      HandleLootLedgerCharacterDeleteRequest(fields, sender)
      return true
    elseif opcode == "LL_CHAR_DEL" then
      HandleLootLedgerCharacterDeleteBroadcast(fields, sender)
      return true
    elseif opcode == "BSYNC_START" then
      HandleBoardSyncStart(fields, sender)
      return true
    elseif opcode == "BSYNC_ITEM" then
      HandleBoardSyncItem(fields, sender)
      return true
    elseif opcode == "BSYNC_SEL" then
      HandleBoardSyncSelection(fields, sender)
      return true
    elseif opcode == "BSYNC_VOTE" then
      HandleBoardSyncVote(fields, sender)
      return true
    elseif opcode == "BSYNC_END" then
      HandleBoardSyncEnd(fields, sender)
      return true
    end
    return false
  end

  return {
    SendActiveLiveBoardSyncFlow = SendActiveLiveBoardSyncFlow,
    ReportLootRollToHost = ReportLootRollToHost,
    OpenAuthoritativeLootItem = OpenAuthoritativeLootItem,
    RequestManualLootLedgerEntryFlow = RequestManualLootLedgerEntryFlow,
    RequestManualLootLedgerDeleteFlow = RequestManualLootLedgerDeleteFlow,
    RequestLootLedgerMainAltFlow = RequestLootLedgerMainAltFlow,
    RequestLootLedgerCharacterNoteFlow = RequestLootLedgerCharacterNoteFlow,
    RequestLootLedgerCharacterDeleteFlow = RequestLootLedgerCharacterDeleteFlow,
    HandleSessionComm = HandleSessionComm,
  }
end
