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_CreateLootSessionFlowHelpers_Impl = function(deps)
  deps = type(deps) == "table" and deps or {}

  local Print = deps.Print
  local TrimText = deps.TrimText
  local NormalizeCharacterKey = deps.NormalizeCharacterKey
  local NormalizeEnabledFlag = deps.NormalizeEnabledFlag
  local FirstNonEmptyText = deps.FirstNonEmptyText
  local GetCharacterKey = deps.GetCharacterKey
  local AddCharacterToList = deps.AddCharacterToList
  local StartLootSession = deps.StartLootSession
  local ActivateLootSession = deps.ActivateLootSession
  local GetActiveLootSession = deps.GetActiveLootSession
  local GetLootProfile = deps.GetLootProfile
  local StopLootSession = deps.StopLootSession
  local JoinLootSession = deps.JoinLootSession
  local UpsertLootSessionMember = deps.UpsertLootSessionMember
  local RemoveLootSessionMember = deps.RemoveLootSessionMember
  local FinishLootSession = deps.FinishLootSession
  local GetLootProfileRole = deps.GetLootProfileRole
  local GetLootProfileMaster = deps.GetLootProfileMaster
  local SyncLootProfilePermissionState = deps.SyncLootProfilePermissionState
  local EnsureLootProfileMemberRole = deps.EnsureLootProfileMemberRole
  local SetLocalAutoPassEnabled = deps.SetLocalAutoPassEnabled
  local GetLootProfileId = deps.GetLootProfileId
  local FindLootProfileNameById = deps.FindLootProfileNameById
  local GetLootProfileRevisionSummary = deps.GetLootProfileRevisionSummary
  local GetMemberPayloadDetails = deps.GetMemberPayloadDetails
  local NormalizeLootRollOptions = deps.NormalizeLootRollOptions
  local RefreshEditor = deps.RefreshEditor
  local ParseRollOptionFields = deps.ParseRollOptionFields
  local GetGroupDistribution = deps.GetGroupDistribution
  local CollectGroupCharacterKeys = deps.CollectGroupCharacterKeys
  local IsCurrentGroupCharacter = deps.IsCurrentGroupCharacter
  local IsClaimedActorSenderMatch = deps.IsClaimedActorSenderMatch
  local IsActiveSessionHostSender = deps.IsActiveSessionHostSender
  local IsJoinedSessionCharacter = deps.IsJoinedSessionCharacter
  local DoesActiveSessionMatch = deps.DoesActiveSessionMatch
  local SendComm = deps.SendComm
  local SetProfileSyncRuntimeState = deps.SetProfileSyncRuntimeState
  local BuildEmptyRevisionSummary = deps.BuildEmptyRevisionSummary
  local NormalizeRevisionSummary = deps.NormalizeRevisionSummary
  local CompareProfileRevisionSummaries = deps.CompareProfileRevisionSummaries
  local FormatProfileRevisionDomains = deps.FormatProfileRevisionDomains
  local RememberSharedReplicaPlaceholder = deps.RememberSharedReplicaPlaceholder
  local ResolveLocalSharedProfileName = deps.ResolveLocalSharedProfileName
  local PrepareProfileSnapshotTransfer = deps.PrepareProfileSnapshotTransfer
  local BuildPreparedProfileRepairTransfers = deps.BuildPreparedProfileRepairTransfers
  local HasLoadedPatchManifestSubdomains = deps.HasLoadedPatchManifestSubdomains
  local FilterLootProfilePatchCapableSubdomains = deps.FilterLootProfilePatchCapableSubdomains
  local SendProfileSubdomainPatchManifest = deps.SendProfileSubdomainPatchManifest
  local SendPreparedProfileSnapshot = deps.SendPreparedProfileSnapshot
  local SendPreparedProfileSnapshotBatch = deps.SendPreparedProfileSnapshotBatch
  local SendProfileSnapshot = deps.SendProfileSnapshot
  local SendProfileSnapshotBatch = deps.SendProfileSnapshotBatch
  local SendLocalProfileStateToHost = deps.SendLocalProfileStateToHost
  local DelayProfileSnapshotBatchForJoins = deps.DelayProfileSnapshotBatchForJoins
  local GetActiveProfileSyncCandidates = deps.GetActiveProfileSyncCandidates
  local ApplyIncomingLootProfileDelta = deps.ApplyIncomingLootProfileDelta
  local RecordRepairHistory = deps.RecordRepairHistory
  local ResolveOptionalApiFunction = deps.ResolveOptionalApiFunction
  local COMM_PROTOCOL_VERSION = math.max(1, tonumber(deps.COMM_PROTOCOL_VERSION) or 1)
  local BuildCommProtocolMarker = deps.BuildCommProtocolMarker
  local ParseCommProtocolMarker = deps.ParseCommProtocolMarker
  local NormalizeSenderKeyExternal = deps.NormalizeSenderKey

  local pendingInvites = {}
  local pendingJoinRequests = {}
  local appliedProfileDeltaIds = {}
  local profileDeltaLastSequence = {}
  local pendingProfileDeltaAcks = {}
  local pendingProfileCheckpointSyncs = {}
  local pendingProfileCheckpointTimers = {}
  local lastProfileCheckpointSyncAt = {}
  local PROFILE_DELTA_ACK_TIMEOUT_SECONDS = 4
  local PROFILE_DELTA_MAX_RETRIES = 2
  local PROFILE_CHECKPOINT_SYNC_DELAY_SECONDS = 2
  local PROFILE_CHECKPOINT_SYNC_MIN_INTERVAL_SECONDS = 3
  local PROFILE_SYNC_AUTO_SUBCHECK_DEDUPE_SECONDS = 6
  local JOIN_ACK_RETRY_SECONDS = 3
  local JOIN_ACK_MAX_ATTEMPTS = 5
  local PREPARE_JOIN_GRACE_SECONDS = 10
  local INVITE_JOIN_GRACE_SECONDS = 10
  local JOIN_QUIET_GRACE_SECONDS = 5
  local PROFILE_BOOTSTRAP_DOMAINS = { "settings", "permissions" }
  local PROFILE_BACKGROUND_SYNC_DOMAINS = { "loot", "session" }
  local recentAutoSubcheckRequests = {}
  local AreCharacterKeysSame
  local QueueProfileSnapshotForMember
  local SendJoinRequest

  local function GetCommProtocolMarker()
    if type(BuildCommProtocolMarker) == "function" then
      return BuildCommProtocolMarker(COMM_PROTOCOL_VERSION)
    end
    return "P" .. tostring(COMM_PROTOCOL_VERSION)
  end

  local function GetProfileCheckpointSyncTime()
    if type(GetTime) == "function" then
      return tonumber(GetTime()) or 0
    end
    return tonumber(time and time() or 0) or 0
  end

  local function GetInviteProtocolVersion(fieldValue)
    if type(ParseCommProtocolMarker) == "function" then
      return ParseCommProtocolMarker(fieldValue)
    end
    return nil
  end

  local function CloneComparedDomains(domains)
    local cloned = {}
    for _, domain in ipairs(type(domains) == "table" and domains or {}) do
      local value = string.lower(TrimText(domain))
      if value ~= "" then
        cloned[#cloned + 1] = value
      end
    end
    return cloned
  end

  local function MergeComparedDomains(...)
    local merged = {}
    local seen = {}
    for index = 1, select("#", ...) do
      for _, domain in ipairs(type(select(index, ...)) == "table" and select(index, ...) or {}) do
        local value = string.lower(TrimText(domain))
        if value ~= "" and not seen[value] then
          seen[value] = true
          merged[#merged + 1] = value
        end
      end
    end
    return merged
  end

  local function EncodeCheckpointSubdomainToken(value)
    local text = TrimText(value)
    if text == "" then
      return ""
    end
    return (text:gsub("([^%w%-%_])", function(character)
      return string.format("%%%02x", string.byte(character))
    end))
  end

  local function BuildDynamicCheckpointSubdomainKey(prefix, identity)
    local resolvedPrefix = string.lower(TrimText(prefix))
    local token = EncodeCheckpointSubdomainToken(identity)
    if resolvedPrefix == "" or token == "" then
      return ""
    end
    return resolvedPrefix .. ":" .. token
  end

  local function BuildSessionRecordCheckpointSubdomain(sessionId)
    local resolvedSessionId = TrimText(sessionId)
    if resolvedSessionId == "" then
      return ""
    end
    return BuildDynamicCheckpointSubdomainKey("ssr", "id:" .. resolvedSessionId)
  end

  local function CloneCheckpointDomainList(domains)
    local clone = {}
    local seen = {}
    for _, domain in ipairs(type(domains) == "table" and domains or {}) do
      local key = string.lower(TrimText(domain))
      if key ~= "" and not seen[key] then
        seen[key] = true
        clone[#clone + 1] = key
      end
    end
    return clone
  end

  local function CloneCheckpointSubdomainList(subdomains)
    local clone = {}
    local seen = {}
    for _, subdomain in ipairs(type(subdomains) == "table" and subdomains or {}) do
      local value = TrimText(subdomain)
      local seenKey = string.lower(value)
      if value ~= "" and not seen[seenKey] then
        seen[seenKey] = true
        clone[#clone + 1] = value
      end
    end
    return clone
  end

  local function MergeCheckpointSubdomainLists(...)
    local merged = {}
    local seen = {}
    for index = 1, select("#", ...) do
      for _, subdomain in ipairs(type(select(index, ...)) == "table" and select(index, ...) or {}) do
        local value = TrimText(subdomain)
        local seenKey = string.lower(value)
        if value ~= "" and not seen[seenKey] then
          seen[seenKey] = true
          merged[#merged + 1] = value
        end
      end
    end
    return merged
  end

  local function BuildProfileCheckpointStateKey(sessionId, profileName)
    return string.lower(TrimText(sessionId)) .. "|" .. string.lower(TrimText(profileName))
  end

  local function CollectLiveSyncTargets(activeSession, selfKey, targetMemberKey)
    local targets = {}
    local seenTargets = {}
    local function AddLiveSyncTarget(characterKey)
      local resolvedKey = NormalizeCharacterKey(characterKey)
      local targetIndexKey = string.lower(resolvedKey)
      if resolvedKey ~= "" and not seenTargets[targetIndexKey] and not AreCharacterKeysSame(resolvedKey, selfKey) and IsJoinedSessionCharacter(activeSession, resolvedKey) then
        targets[#targets + 1] = resolvedKey
        seenTargets[targetIndexKey] = true
      end
    end

    local requestedTarget = NormalizeCharacterKey(targetMemberKey)
    if requestedTarget ~= "" then
      AddLiveSyncTarget(requestedTarget)
    else
      AddLiveSyncTarget(activeSession.host)
      for memberKey, member in pairs(activeSession.members or {}) do
        if type(member) == "table" and tostring(member.status or "JOINED") == "JOINED" then
          AddLiveSyncTarget(memberKey)
        end
      end
      table.sort(targets)
    end
    return targets
  end

  local function SendActiveProfileCheckpointNow(profileName, pendingState)
    pendingState = type(pendingState) == "table" and pendingState or {}
    local activeSession, activeProfileName = GetActiveLootSession()
    if not activeSession or not activeProfileName then
      return false, "No active session."
    end

    local requestedProfileName = TrimText(profileName)
    if requestedProfileName ~= "" and not DoesActiveSessionMatch(activeSession, activeProfileName, activeSession.id, requestedProfileName) then
      return false, "No matching active session profile."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if selfKey == "" or not AreCharacterKeysSame(activeSession.host or "", selfKey) or not IsJoinedSessionCharacter(activeSession, selfKey) then
      return false, "Only the joined session host can send live profile checkpoints."
    end

    local domains = CloneCheckpointDomainList(pendingState.domains)
    local subdomains = CloneCheckpointSubdomainList(pendingState.subdomains)
    if #domains == 0 and #subdomains == 0 then
      return false, "No checkpoint scope requested."
    end

    local rowPatchSubdomains = {}
    local remainingSubdomains = CloneCheckpointSubdomainList(subdomains)
    local prebuiltRowsBySubdomain = type(pendingState.prebuiltRowsBySubdomain) == "table" and pendingState.prebuiltRowsBySubdomain or nil
    local targets = CollectLiveSyncTargets(activeSession, selfKey, nil)
    if #targets == 0 then
      return false, "No joined session members."
    end

    local checkpointReason = TrimText(pendingState.reason) ~= "" and TrimText(pendingState.reason) or "checkpoint"
    local sentCount = 0
    local rowPatchTransferCount = 0
    if type(prebuiltRowsBySubdomain) == "table" and #remainingSubdomains > 0 and type(PrepareProfileSnapshotTransfer) == "function" then
      local subdomainLookup = {}
      for _, subdomain in ipairs(remainingSubdomains) do
        subdomainLookup[string.lower(TrimText(subdomain))] = true
      end
      for subdomain, rows in pairs(prebuiltRowsBySubdomain) do
        if subdomainLookup[string.lower(TrimText(subdomain))] and type(rows) == "table" and #rows > 0 then
          rowPatchSubdomains[#rowPatchSubdomains + 1] = TrimText(subdomain)
        end
      end
      table.sort(rowPatchSubdomains)
      if #rowPatchSubdomains > 0 then
        local preparedRowPatch = PrepareProfileSnapshotTransfer(activeProfileName, {
          domains = #domains > 0 and domains or nil,
          subdomains = rowPatchSubdomains,
          prebuiltRowsBySubdomain = prebuiltRowsBySubdomain,
        })
        if type(preparedRowPatch) == "table" and TrimText(preparedRowPatch.transferKind) == "ROWPATCHES" then
          local ok, queuedCount = SendPreparedProfileSnapshotBatch(preparedRowPatch, activeSession.id, targets, {
            mode = "LIVE",
            reason = checkpointReason,
          })
          if ok then
            local queuedMembers = tonumber(queuedCount) or #targets
            rowPatchTransferCount = queuedMembers
            sentCount = sentCount + queuedMembers
            local handled = {}
            local unresolved = {}
            for _, subdomain in ipairs(rowPatchSubdomains) do
              handled[string.lower(TrimText(subdomain))] = true
            end
            for _, subdomain in ipairs(remainingSubdomains) do
              if not handled[string.lower(TrimText(subdomain))] then
                unresolved[#unresolved + 1] = subdomain
              end
            end
            remainingSubdomains = unresolved
            if #subdomains > 0 and #remainingSubdomains == 0 then
              domains = {}
            end
          end
        end
      end
    end
    local patchCapableSubdomains = {}
    if #remainingSubdomains > 0 and type(HasLoadedPatchManifestSubdomains) == "function" then
      if type(FilterLootProfilePatchCapableSubdomains) == "function" then
        patchCapableSubdomains = FilterLootProfilePatchCapableSubdomains(remainingSubdomains)
      end
    end
    local patchTransferCount = 0
    local snapshotTransferCount = 0
    local snapshotTargets = targets

    if #patchCapableSubdomains > 0 then
      local directPatchTargets = {}
      snapshotTargets = {}
      for _, memberKey in ipairs(targets) do
        if HasLoadedPatchManifestSubdomains(activeSession.id, memberKey, patchCapableSubdomains) then
          directPatchTargets[#directPatchTargets + 1] = memberKey
        else
          snapshotTargets[#snapshotTargets + 1] = memberKey
        end
      end

      for _, memberKey in ipairs(directPatchTargets) do
        local transfers = BuildPreparedProfileRepairTransfers(activeProfileName, activeSession.id, memberKey, {
          domains = #domains > 0 and domains or nil,
          subdomains = #remainingSubdomains > 0 and remainingSubdomains or nil,
        })
        local memberSent = false
        if type(transfers) == "table" then
          for _, preparedTransfer in ipairs(transfers) do
            local ok = SendPreparedProfileSnapshot(preparedTransfer, activeSession.id, memberKey, {
              mode = "LIVE",
              reason = checkpointReason,
            })
            if ok then
              memberSent = true
              if TrimText(type(preparedTransfer) == "table" and preparedTransfer.transferKind or "") == "PATCHES" then
                patchTransferCount = patchTransferCount + 1
              else
                snapshotTransferCount = snapshotTransferCount + 1
              end
            end
          end
        elseif type(PrepareProfileSnapshotTransfer) == "function" then
          local fallbackSnapshot = PrepareProfileSnapshotTransfer(activeProfileName, {
            domains = #domains > 0 and domains or nil,
            subdomains = #remainingSubdomains > 0 and remainingSubdomains or nil,
          })
          if type(fallbackSnapshot) == "table" then
            local ok = SendPreparedProfileSnapshot(fallbackSnapshot, activeSession.id, memberKey, {
              mode = "LIVE",
              reason = checkpointReason,
            })
            if ok then
              memberSent = true
              snapshotTransferCount = snapshotTransferCount + 1
            end
          end
        end
        if memberSent then
          sentCount = sentCount + 1
        end
      end
    end

    if #snapshotTargets > 0 and (#domains > 0 or #remainingSubdomains > 0) then
      local preparedSnapshot, snapshotErr = PrepareProfileSnapshotTransfer(activeProfileName, {
        domains = #domains > 0 and domains or nil,
        subdomains = #remainingSubdomains > 0 and remainingSubdomains or nil,
      })
      if not preparedSnapshot then
        return sentCount > 0, sentCount > 0 and sentCount or (snapshotErr or "Profile checkpoint export failed.")
      end

      if type(SendPreparedProfileSnapshotBatch) == "function" then
        local ok, queuedCount = SendPreparedProfileSnapshotBatch(preparedSnapshot, activeSession.id, snapshotTargets, {
          mode = "LIVE",
          reason = checkpointReason,
        })
        if ok then
          local queuedMembers = tonumber(queuedCount) or #snapshotTargets
          sentCount = sentCount + queuedMembers
          snapshotTransferCount = snapshotTransferCount + queuedMembers
        end
      else
        for _, memberKey in ipairs(snapshotTargets) do
          local ok = SendPreparedProfileSnapshot(preparedSnapshot, activeSession.id, memberKey, {
            mode = "LIVE",
            reason = checkpointReason,
          })
          if ok then
            sentCount = sentCount + 1
            snapshotTransferCount = snapshotTransferCount + 1
          end
        end
      end
    end

    if sentCount > 0 then
      local scopeCount = (#subdomains > 0 and #subdomains or #domains)
      local scopeLabel = #subdomains > 0 and "scope" or "domain"
      SetProfileSyncRuntimeState(activeSession.id, activeProfileName, "live_checkpoint", "info",
        "Queued a live " .. scopeLabel .. " checkpoint for " .. tostring(sentCount) .. " joined member"
          .. (sentCount == 1 and "" or "s") .. " across " .. tostring(scopeCount) .. " " .. scopeLabel
          .. (scopeCount == 1 and "" or "s") .. "."
          .. (patchTransferCount > 0 and (" " .. tostring(patchTransferCount) .. " patch transfer"
            .. (patchTransferCount == 1 and "" or "s") .. " prepared.") or "")
          .. (rowPatchTransferCount > 0 and (" " .. tostring(rowPatchTransferCount) .. " row patch transfer"
            .. (rowPatchTransferCount == 1 and "" or "s") .. " prepared.") or ""), {
          sender = selfKey,
          refreshEditor = false,
        })
    end
    return sentCount > 0, sentCount
  end

  local function FlushQueuedProfileCheckpointSync(stateKey)
    local resolvedKey = TrimText(stateKey)
    if resolvedKey == "" then
      return
    end
    local pending = pendingProfileCheckpointSyncs[resolvedKey]
    pendingProfileCheckpointSyncs[resolvedKey] = nil
    pendingProfileCheckpointTimers[resolvedKey] = nil
    if type(pending) ~= "table" then
      return
    end
    lastProfileCheckpointSyncAt[resolvedKey] = GetProfileCheckpointSyncTime()
    SendActiveProfileCheckpointNow(pending.profileName, pending)
  end

  local function QueueActiveProfileCheckpointFlow(profileName, opts)
    opts = type(opts) == "table" and opts or {}
    local activeSession, activeProfileName = GetActiveLootSession()
    if not activeSession or not activeProfileName then
      return false, "No active session."
    end

    local requestedProfileName = TrimText(profileName)
    if requestedProfileName ~= "" and not DoesActiveSessionMatch(activeSession, activeProfileName, activeSession.id, requestedProfileName) then
      return false, "No matching active session profile."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if selfKey == "" or not AreCharacterKeysSame(activeSession.host or "", selfKey) or not IsJoinedSessionCharacter(activeSession, selfKey) then
      return false, "Only the joined session host can queue live checkpoints."
    end

    local domains = CloneCheckpointDomainList(opts.domains)
    local subdomains = CloneCheckpointSubdomainList(opts.subdomains)
    if #domains == 0 and #subdomains == 0 then
      return false, "No checkpoint scope requested."
    end

    local stateKey = BuildProfileCheckpointStateKey(activeSession.id, activeProfileName)
    local pending = type(pendingProfileCheckpointSyncs[stateKey]) == "table" and pendingProfileCheckpointSyncs[stateKey] or {
      sessionId = TrimText(activeSession.id),
      profileName = TrimText(activeProfileName),
      reason = TrimText(opts.reason),
      domains = {},
      subdomains = {},
      prebuiltRowsBySubdomain = {},
    }
    pending.sessionId = TrimText(activeSession.id)
    pending.profileName = TrimText(activeProfileName)
    if TrimText(opts.reason) ~= "" then
      pending.reason = TrimText(opts.reason)
    end
    pending.domains = CloneCheckpointDomainList(MergeComparedDomains(pending.domains, domains))
    pending.subdomains = CloneCheckpointSubdomainList(MergeCheckpointSubdomainLists(pending.subdomains, subdomains))
    if type(opts.prebuiltRowsBySubdomain) == "table" then
      pending.prebuiltRowsBySubdomain = type(pending.prebuiltRowsBySubdomain) == "table" and pending.prebuiltRowsBySubdomain or {}
      for subdomain, rows in pairs(opts.prebuiltRowsBySubdomain) do
        local resolvedSubdomain = TrimText(subdomain)
        if resolvedSubdomain ~= "" and type(rows) == "table" and #rows > 0 then
          local mergedById = {}
          for _, row in ipairs(type(pending.prebuiltRowsBySubdomain[resolvedSubdomain]) == "table" and pending.prebuiltRowsBySubdomain[resolvedSubdomain] or {}) do
            local rowId = tostring(type(row) == "table" and row.id or "")
            if rowId ~= "" then
              mergedById[rowId] = row
            end
          end
          for _, row in ipairs(rows) do
            local rowId = tostring(type(row) == "table" and row.id or "")
            if rowId ~= "" then
              mergedById[rowId] = row
            end
          end
          local mergedRows = {}
          for _, row in pairs(mergedById) do
            mergedRows[#mergedRows + 1] = row
          end
          table.sort(mergedRows, function(left, right)
            return tostring(type(left) == "table" and left.id or "") < tostring(type(right) == "table" and right.id or "")
          end)
          pending.prebuiltRowsBySubdomain[resolvedSubdomain] = mergedRows
        end
      end
    end
    pendingProfileCheckpointSyncs[stateKey] = pending

    if opts.immediate == true then
      pendingProfileCheckpointTimers[stateKey] = nil
      pendingProfileCheckpointSyncs[stateKey] = nil
      lastProfileCheckpointSyncAt[stateKey] = GetProfileCheckpointSyncTime()
      return SendActiveProfileCheckpointNow(activeProfileName, pending)
    end

    if pendingProfileCheckpointTimers[stateKey] then
      return true, "queued"
    end

    local now = GetProfileCheckpointSyncTime()
    local lastSent = tonumber(lastProfileCheckpointSyncAt[stateKey]) or 0
    local delay = PROFILE_CHECKPOINT_SYNC_DELAY_SECONDS
    if lastSent > 0 and (now - lastSent) < PROFILE_CHECKPOINT_SYNC_MIN_INTERVAL_SECONDS then
      delay = math.max(delay, PROFILE_CHECKPOINT_SYNC_MIN_INTERVAL_SECONDS - math.max(0, now - lastSent))
    end

    if type(C_Timer) ~= "table" or type(C_Timer.After) ~= "function" then
      pendingProfileCheckpointSyncs[stateKey] = nil
      lastProfileCheckpointSyncAt[stateKey] = now
      return SendActiveProfileCheckpointNow(activeProfileName, pending)
    end

    pendingProfileCheckpointTimers[stateKey] = true
    C_Timer.After(delay, function()
      FlushQueuedProfileCheckpointSync(stateKey)
    end)
    return true, "queued"
  end

  local function QueueSessionRecordCheckpoint(profileName, sessionId, reason, memberKey)
    local subdomain = BuildSessionRecordCheckpointSubdomain(sessionId)
    if subdomain == "" then
      return false, "Session checkpoint scope is unavailable."
    end
    local prebuiltRowsBySubdomain = nil
    local resolvedMemberKey = NormalizeCharacterKey(memberKey)
    if resolvedMemberKey ~= "" then
      local activeSession = GetActiveLootSession()
      activeSession = type(activeSession) == "table" and activeSession or nil
      local member = type(activeSession) == "table" and type(activeSession.members) == "table" and activeSession.members[resolvedMemberKey] or nil
      local remotePayload = {
        session = {
          members = {},
        },
      }
      if type(member) == "table" then
        remotePayload.session.members[resolvedMemberKey] = member
      end
      prebuiltRowsBySubdomain = {
        [subdomain] = {
          {
            id = "session:member:" .. resolvedMemberKey,
            subdomain = subdomain,
            applySpec = {
              kind = "keyed_entry",
              tableField = "session.members",
              key = resolvedMemberKey,
            },
            remotePayload = remotePayload,
          },
        },
      }
    end
    return QueueActiveProfileCheckpointFlow(profileName, {
      reason = TrimText(reason) ~= "" and TrimText(reason) or "session_checkpoint",
      domains = { "session" },
      subdomains = { subdomain },
      prebuiltRowsBySubdomain = prebuiltRowsBySubdomain,
    })
  end

  local function HasComparedDomain(domains, domain)
    local needle = string.lower(TrimText(domain))
    if needle == "" then
      return false
    end
    for _, value in ipairs(type(domains) == "table" and domains or {}) do
      if string.lower(TrimText(value)) == needle then
        return true
      end
    end
    return false
  end

  local function FindActiveSyncCandidate(memberKey)
    local resolvedMemberKey = NormalizeCharacterKey(memberKey)
    if resolvedMemberKey == "" or type(GetActiveProfileSyncCandidates) ~= "function" then
      return nil
    end
    for _, candidate in ipairs(GetActiveProfileSyncCandidates() or {}) do
      if NormalizeCharacterKey(type(candidate) == "table" and candidate.memberKey or "") == resolvedMemberKey then
        return candidate
      end
    end
    return nil
  end

  local function BuildHostRepairDomainsForMember(memberKey)
    local candidate = FindActiveSyncCandidate(memberKey)
    if type(candidate) ~= "table" then
      return nil, nil, false, "full"
    end
    local comparison = string.lower(TrimText(candidate.comparison))
    if comparison == "same" then
      return {}, {}, false, "same"
    end
    if comparison == "different_lineage" or comparison == "unknown" or TrimText(candidate.profileId) == "" then
      return nil, nil, true, "full"
    end
    local domains = {}
    for _, domain in ipairs(type(candidate.localNewerDomains) == "table" and candidate.localNewerDomains or {}) do
      if not HasComparedDomain(candidate.remoteNewerDomains, domain) then
        domains[#domains + 1] = string.lower(TrimText(domain))
      end
    end
    if #domains == 0 then
      return {}, {}, false, comparison == "remote_newer" and "member_newer" or "same"
    end
    local subdomains = {}
    if candidate.precisePushReady then
      for _, domain in ipairs(domains) do
        for _, subdomain in ipairs(type(candidate.preciseDifferentSubdomainsByDomain) == "table" and (candidate.preciseDifferentSubdomainsByDomain[domain] or {}) or {}) do
          subdomains[#subdomains + 1] = subdomain
        end
      end
    end
    return domains, subdomains, false, #subdomains > 0 and "precise" or "targeted"
  end

  local function BuildMemberRepairRequestDomains(memberKey, previewOnly)
    local candidate = FindActiveSyncCandidate(memberKey)
    if type(candidate) ~= "table" then
      return nil, nil, "none"
    end
    local comparison = string.lower(TrimText(candidate.comparison))
    if comparison == "different_lineage" or comparison == "unknown" or TrimText(candidate.profileId) == "" then
      return nil, nil, "full"
    end
    if previewOnly then
      local domains = MergeComparedDomains(candidate.remoteNewerDomains, candidate.localNewerDomains)
      local subdomains = {}
      if candidate.precisePreviewReady then
        for _, subdomain in ipairs(type(candidate.precisePreviewSubdomains) == "table" and candidate.precisePreviewSubdomains or {}) do
          subdomains[#subdomains + 1] = subdomain
        end
      end
      return #domains > 0 and domains or nil, #subdomains > 0 and subdomains or nil, #subdomains > 0 and "precise" or "targeted"
    end
    local domains = {}
    for _, domain in ipairs(type(candidate.remoteNewerDomains) == "table" and candidate.remoteNewerDomains or {}) do
      if not HasComparedDomain(candidate.localNewerDomains, domain) then
        domains[#domains + 1] = string.lower(TrimText(domain))
      end
    end
    local subdomains = {}
    if candidate.precisePullReady then
      for _, domain in ipairs(domains) do
        for _, subdomain in ipairs(type(candidate.preciseDifferentSubdomainsByDomain) == "table" and (candidate.preciseDifferentSubdomainsByDomain[domain] or {}) or {}) do
          subdomains[#subdomains + 1] = subdomain
        end
      end
    end
    return #domains > 0 and domains or nil, #subdomains > 0 and subdomains or nil, #subdomains > 0 and "precise" or "targeted"
  end

  local function BuildDetailedComparisonRequestDomains(memberKey)
    local candidate = FindActiveSyncCandidate(memberKey)
    if type(candidate) ~= "table" then
      return nil
    end
    local comparison = string.lower(TrimText(candidate.comparison))
    if comparison == "same" or comparison == "different_lineage" or comparison == "unknown" or TrimText(candidate.profileId) == "" then
      return nil
    end
    local domains = MergeComparedDomains(candidate.remoteNewerDomains, candidate.localNewerDomains)
    return #domains > 0 and domains or nil
  end

  local function HasLoadedDetailedComparisonDomains(candidate, domains)
    candidate = type(candidate) == "table" and candidate or {}
    if candidate.preciseDetailLoaded ~= true then
      return false
    end
    for _, domain in ipairs(type(domains) == "table" and domains or {}) do
      if not HasComparedDomain(candidate.preciseScopeDomains, domain) then
        return false
      end
    end
    return true
  end

  local function BuildDetailedComparisonRequestStamp(sessionId, memberKey, domains)
    return string.lower(TrimText(sessionId)) .. "|"
      .. string.lower(NormalizeCharacterKey(memberKey)) .. "|"
      .. table.concat(MergeComparedDomains(domains), ",")
  end

  local function SendDetailedComparisonRequests(targets, options)
    options = type(options) == "table" and options or {}
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not profileName then
      return 0, 0, 0
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      return 0, 0, 0
    end

    local requestedCount = 0
    local skippedAligned = 0
    local skippedLoaded = 0
    local now = tonumber(time and time() or 0) or 0
    for _, memberKey in ipairs(type(targets) == "table" and targets or {}) do
      local candidate = FindActiveSyncCandidate(memberKey)
      local requestDomains = BuildDetailedComparisonRequestDomains(memberKey)
      if type(requestDomains) ~= "table" or #requestDomains == 0 then
        skippedAligned = skippedAligned + 1
      elseif HasLoadedDetailedComparisonDomains(candidate, requestDomains) then
        skippedLoaded = skippedLoaded + 1
      else
        local requestStamp = BuildDetailedComparisonRequestStamp(activeSession.id, memberKey, requestDomains)
        local lastRequestedAt = tonumber(recentAutoSubcheckRequests[requestStamp]) or 0
        local allowRetry = options.force == true or (now - lastRequestedAt) >= PROFILE_SYNC_AUTO_SUBCHECK_DEDUPE_SECONDS
        if allowRetry then
          local sent = SendComm(
            "PSUB_REQ",
            "WHISPER",
            memberKey,
            activeSession.id,
            profileName,
            TrimText(select(1, GetLootProfileId(profileName)) or ""),
            table.concat(requestDomains, ",")
          )
          if sent then
            recentAutoSubcheckRequests[requestStamp] = now
            requestedCount = requestedCount + 1
          end
        else
          skippedLoaded = skippedLoaded + 1
        end
      end
    end
    return requestedCount, skippedAligned, skippedLoaded
  end

  local function QueueAutoDetailedComparison(memberKey, reason)
    local resolvedMemberKey = NormalizeCharacterKey(memberKey)
    if resolvedMemberKey == "" then
      return
    end
    local function RunAutoRequest()
      SendDetailedComparisonRequests({ resolvedMemberKey }, {
        auto = true,
      })
    end
    if type(C_Timer) == "table" and type(C_Timer.After) == "function" then
      C_Timer.After(0.35, RunAutoRequest)
    else
      RunAutoRequest()
    end
  end

  local function IsCombatLocked()
    return type(InCombatLockdown) == "function" and InCombatLockdown() and true or false
  end

  local function RejectCombatLockedAction(actionLabel)
    if not IsCombatLocked() then
      return false
    end
    local message = tostring(actionLabel or "This action") .. " is unavailable during combat."
    if type(Print) == "function" then
      Print(message)
    end
    return true, message
  end

  local function BuildProfileDeltaId()
    return string.format("PD-%d-%d", tonumber(time and time() or 0) or 0, math.random(1000, 9999))
  end

  local function MarkProfileDeltaSeen(changeId)
    local resolvedId = TrimText(changeId)
    if resolvedId ~= "" then
      appliedProfileDeltaIds[resolvedId] = true
    end
  end

  local function HasProfileDeltaSeen(changeId)
    local resolvedId = TrimText(changeId)
    return resolvedId ~= "" and appliedProfileDeltaIds[resolvedId] == true
  end

  local function GetProfileDeltaRuntimeKey(sessionId, profileId, profileName)
    local resolvedSessionId = TrimText(sessionId)
    local resolvedProfileId = TrimText(profileId)
    local resolvedProfileName = TrimText(profileName)
    return resolvedSessionId .. ":" .. (resolvedProfileId ~= "" and resolvedProfileId or resolvedProfileName)
  end

  local function NextHostProfileDeltaSequence(activeSession)
    if type(activeSession) ~= "table" then
      return 0
    end
    activeSession.profileDeltaSequence = math.max(0, tonumber(activeSession.profileDeltaSequence) or 0) + 1
    return activeSession.profileDeltaSequence
  end

  local function RememberProfileDeltaSequence(delta)
    if type(delta) ~= "table" or tonumber(delta.sequence) == nil or tonumber(delta.sequence) <= 0 then
      return
    end
    local runtimeKey = GetProfileDeltaRuntimeKey(delta.sessionId, delta.profileId, delta.profileName)
    profileDeltaLastSequence[runtimeKey] = math.max(tonumber(profileDeltaLastSequence[runtimeKey]) or 0, tonumber(delta.sequence) or 0)
  end

  local function IsProfileDeltaSequenceGap(delta)
    if type(delta) ~= "table" or tonumber(delta.sequence) == nil or tonumber(delta.sequence) <= 0 then
      return false
    end
    local runtimeKey = GetProfileDeltaRuntimeKey(delta.sessionId, delta.profileId, delta.profileName)
    local lastSequence = tonumber(profileDeltaLastSequence[runtimeKey]) or 0
    return lastSequence > 0 and tonumber(delta.sequence) > (lastSequence + 1)
  end

  local function IsProfileDeltaSequenceStale(delta)
    if type(delta) ~= "table" or tonumber(delta.sequence) == nil or tonumber(delta.sequence) <= 0 then
      return false
    end
    local runtimeKey = GetProfileDeltaRuntimeKey(delta.sessionId, delta.profileId, delta.profileName)
    local lastSequence = tonumber(profileDeltaLastSequence[runtimeKey]) or 0
    return lastSequence > 0 and tonumber(delta.sequence) <= lastSequence
  end

  local function ReadProfileDeltaFields(fields)
    fields = type(fields) == "table" and fields or {}
    local sequence = tonumber(fields[13])
    local hasExtendedHeader = sequence ~= nil
    local argStartIndex = hasExtendedHeader and 17 or 13
    local args = {}
    for index = argStartIndex, #fields do
      args[#args + 1] = fields[index]
    end
    return {
      sessionId = TrimText(fields[2]),
      profileName = TrimText(fields[3]),
      profileId = TrimText(fields[4]),
      changeId = TrimText(fields[5]),
      actor = NormalizeCharacterKey(fields[6]),
      domain = TrimText(fields[7]),
      action = TrimText(fields[8]),
      settingsRevision = tonumber(fields[9]) or 0,
      permissionsRevision = tonumber(fields[10]) or 0,
      operationalRevision = tonumber(fields[11]) or 0,
      profileUpdatedAt = tonumber(fields[12]) or 0,
      sequence = hasExtendedHeader and math.max(0, tonumber(fields[13]) or 0) or 0,
      settingsChecksum = hasExtendedHeader and TrimText(fields[14]) or "",
      permissionsChecksum = hasExtendedHeader and TrimText(fields[15]) or "",
      operationalChecksum = hasExtendedHeader and TrimText(fields[16]) or "",
      args = args,
    }
  end

  local function SendProfileDelta(kind, distribution, target, activeSession, profileName, delta, revisionSummary)
    if type(SendComm) ~= "function" or type(activeSession) ~= "table" or type(delta) ~= "table" then
      return false
    end
    revisionSummary = type(revisionSummary) == "table" and revisionSummary or GetLootProfileRevisionSummary(profileName)
    if TrimText(kind) == "PDELTA" and (tonumber(delta.sequence) or 0) <= 0 then
      delta.sequence = NextHostProfileDeltaSequence(activeSession)
    end
    local args = type(delta.args) == "table" and delta.args or {}
    return SendComm(
      kind,
      distribution,
      target,
      TrimText(activeSession.id),
      TrimText(profileName),
      TrimText(delta.profileId),
      TrimText(delta.changeId),
      NormalizeCharacterKey(delta.actor),
      TrimText(delta.domain),
      TrimText(delta.action),
      tostring(tonumber(revisionSummary.settings) or 0),
      tostring(tonumber(revisionSummary.permissions) or 0),
      tostring(tonumber(revisionSummary.operational) or 0),
      tostring(tonumber(revisionSummary.updatedAt) or 0),
      tostring(tonumber(delta.sequence) or 0),
      TrimText(revisionSummary.settingsChecksum),
      TrimText(revisionSummary.permissionsChecksum),
      TrimText(revisionSummary.operationalChecksum),
      unpack(args)
    )
  end

  local function SendProfileDeltaAck(activeSession, profileName, delta, revisionSummary)
    if type(activeSession) ~= "table" or type(delta) ~= "table" or type(SendComm) ~= "function" then
      return false
    end
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    local hostKey = NormalizeCharacterKey(activeSession.host or "")
    if selfKey == "" or hostKey == "" or AreCharacterKeysSame(selfKey, hostKey) then
      return false
    end
    revisionSummary = type(revisionSummary) == "table" and revisionSummary or GetLootProfileRevisionSummary(profileName)
    return SendComm(
      "PDELTA_ACK",
      "WHISPER",
      hostKey,
      TrimText(activeSession.id),
      TrimText(profileName),
      TrimText(delta.changeId),
      selfKey,
      tostring(tonumber(delta.sequence) or 0),
      tostring(tonumber(revisionSummary.settings) or 0),
      tostring(tonumber(revisionSummary.permissions) or 0),
      tostring(tonumber(revisionSummary.operational) or 0),
      tostring(tonumber(revisionSummary.updatedAt) or 0),
      TrimText(revisionSummary.settingsChecksum),
      TrimText(revisionSummary.permissionsChecksum),
      TrimText(revisionSummary.operationalChecksum),
      tostring(tonumber(revisionSummary.loot) or tonumber(revisionSummary.operational) or 0),
      tostring(tonumber(revisionSummary.session) or tonumber(revisionSummary.operational) or 0),
      TrimText(revisionSummary.lootChecksum),
      TrimText(revisionSummary.sessionChecksum)
    )
  end

  local function RequestProfileDeltaRecovery(activeSession, profileName, delta, reason)
    if type(activeSession) ~= "table" or type(delta) ~= "table" or type(SendComm) ~= "function" then
      return false
    end
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    local hostKey = NormalizeCharacterKey(activeSession.host or "")
    if selfKey == "" or hostKey == "" or AreCharacterKeysSame(selfKey, hostKey) then
      return false
    end
    return SendComm(
      "PDELTA_NACK",
      "WHISPER",
      hostKey,
      TrimText(activeSession.id),
      TrimText(profileName),
      TrimText(delta.changeId),
      selfKey,
      tostring(tonumber(delta.sequence) or 0),
      TrimText(reason)
    )
  end

  local function TrackProfileDeltaAcks(activeSession, profileName, delta, revisionSummary)
    if type(activeSession) ~= "table" or type(delta) ~= "table" or TrimText(delta.changeId) == "" then
      return
    end
    local distribution = GetGroupDistribution()
    if not distribution or type(C_Timer) ~= "table" or type(C_Timer.After) ~= "function" then
      return
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    local missing = {}
    for memberKey, member in pairs(activeSession.members or {}) do
      local resolvedKey = NormalizeCharacterKey(memberKey)
      if resolvedKey ~= "" and not AreCharacterKeysSame(resolvedKey, selfKey)
          and type(member) == "table" and string.upper(TrimText(member.status or "JOINED")) == "JOINED" then
        missing[resolvedKey] = true
      end
    end
    if not next(missing) then
      return
    end

    pendingProfileDeltaAcks[delta.changeId] = {
      sessionId = TrimText(activeSession.id),
      profileName = TrimText(profileName),
      profileId = TrimText(delta.profileId),
      delta = delta,
      revisionSummary = revisionSummary,
      missing = missing,
      attempts = 0,
    }

    local function CheckPendingAcks()
      local pending = pendingProfileDeltaAcks[delta.changeId]
      if type(pending) ~= "table" then
        return
      end
      if not next(pending.missing or {}) then
        pendingProfileDeltaAcks[delta.changeId] = nil
        return
      end

      pending.attempts = math.max(0, tonumber(pending.attempts) or 0) + 1
      local currentSession, currentProfileName = GetActiveLootSession()
      if not DoesActiveSessionMatch(currentSession, currentProfileName, pending.sessionId, pending.profileName) then
        pendingProfileDeltaAcks[delta.changeId] = nil
        return
      end

      if pending.attempts <= PROFILE_DELTA_MAX_RETRIES then
        for memberKey in pairs(pending.missing) do
          SendProfileDelta("PDELTA", "WHISPER", memberKey, currentSession, pending.profileName, pending.delta, pending.revisionSummary)
        end
        C_Timer.After(PROFILE_DELTA_ACK_TIMEOUT_SECONDS, CheckPendingAcks)
        return
      end

      if type(SendProfileSnapshot) == "function" then
        for memberKey in pairs(pending.missing) do
          QueueProfileSnapshotForMember(pending.profileName, pending.sessionId, memberKey, { mode = "LIVE" })
        end
      end
      pendingProfileDeltaAcks[delta.changeId] = nil
    end

    C_Timer.After(PROFILE_DELTA_ACK_TIMEOUT_SECONDS, CheckPendingAcks)
  end

  local function BuildProfileDeltaRevisionSummary(delta)
    delta = type(delta) == "table" and delta or {}
    return NormalizeRevisionSummary({
      profileName = delta.profileName,
      profileId = delta.profileId,
      settings = delta.settingsRevision,
      permissions = delta.permissionsRevision,
      operational = delta.operationalRevision,
      loot = delta.lootRevision,
      session = delta.sessionRevision,
      settingsChecksum = delta.settingsChecksum,
      permissionsChecksum = delta.permissionsChecksum,
      operationalChecksum = delta.operationalChecksum,
      lootChecksum = delta.lootChecksum,
      sessionChecksum = delta.sessionChecksum,
      updatedAt = delta.profileUpdatedAt,
    }, delta.profileName, delta.profileId)
  end

  local function NormalizeProfileDeltaDomain(domain)
    local resolved = string.lower(TrimText(domain))
    if resolved == "settings" then
      return "settings"
    elseif resolved == "permissions" then
      return "permissions"
    elseif resolved == "loot" then
      return "loot"
    elseif resolved == "session" then
      return "session"
    end
    return "operational"
  end

  local function IsLocalProfileAlignedWithDelta(profileName, delta)
    local localSummary = NormalizeRevisionSummary(
      GetLootProfileRevisionSummary(profileName),
      profileName,
      TrimText(type(delta) == "table" and delta.profileId or "")
    )
    local remoteSummary = BuildProfileDeltaRevisionSummary(delta)
    local domain = NormalizeProfileDeltaDomain(type(delta) == "table" and delta.domain or "")
    local checksumKey = domain .. "Checksum"
    local localRevision = math.max(0, tonumber(localSummary[domain]) or 0)
    local remoteRevision = math.max(0, tonumber(remoteSummary[domain]) or 0)
    if localRevision ~= remoteRevision then
      return false, { domain }, { domain }
    end
    local localChecksum = TrimText(localSummary[checksumKey])
    local remoteChecksum = TrimText(remoteSummary[checksumKey])
    if localChecksum ~= "" and remoteChecksum ~= "" and localChecksum ~= remoteChecksum then
      return false, { domain }, { domain }
    end
    return true, {}, {}
  end

  local function RefreshActiveSessionProfileCache(activeSession, profileName)
    if type(activeSession) ~= "table" or TrimText(profileName) == "" then
      return
    end
    local sourceProfile = type(GetLootProfile) == "function" and select(1, GetLootProfile(profileName)) or nil
    if type(sourceProfile) == "table" and type(NormalizeLootRollOptions) == "function" then
      activeSession.rollOptions = NormalizeLootRollOptions(sourceProfile.settings and sourceProfile.settings.rollOptions)
    end
    if type(activeSession.members) == "table" then
      for memberKey, member in pairs(activeSession.members) do
        if type(member) == "table" then
          member.profileMaster = GetLootProfileMaster(profileName)
          member.role = GetLootProfileRole(profileName, memberKey)
        end
      end
    end
  end

  AreCharacterKeysSame = function(left, right)
    local leftKey = NormalizeCharacterKey(left)
    local rightKey = NormalizeCharacterKey(right)
    if leftKey == "" or rightKey == "" then
      return false
    end
    if string.lower(leftKey) == string.lower(rightKey) then
      return true
    end

    local leftName, leftRealm = leftKey:match("^([^%-]+)%-(.+)$")
    local rightName, rightRealm = rightKey:match("^([^%-]+)%-(.+)$")
    leftName = string.lower(TrimText(leftName or leftKey))
    rightName = string.lower(TrimText(rightName or rightKey))
    leftRealm = string.lower(TrimText(leftRealm or ""))
    rightRealm = string.lower(TrimText(rightRealm or ""))
    if leftName == "" or rightName == "" or leftName ~= rightName then
      return false
    end
    return leftRealm == "" or rightRealm == "" or leftRealm == rightRealm
  end

  local function NormalizeSenderKey(sender)
    if type(NormalizeSenderKeyExternal) == "function" then
      return NormalizeSenderKeyExternal(sender)
    end
    return NormalizeCharacterKey(sender)
  end

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

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

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

  local function BuildPendingJoinRequest(invite)
    invite = type(invite) == "table" and invite or {}
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "Unknown")
    local inviteProfileId = TrimText(invite.profileId)
    local existingSharedProfileName = TrimText(inviteProfileId ~= "" and FindLootProfileNameById(inviteProfileId) or "")
    local localRevisionSummary = existingSharedProfileName ~= ""
      and NormalizeRevisionSummary(GetLootProfileRevisionSummary(existingSharedProfileName), existingSharedProfileName, inviteProfileId)
      or BuildEmptyRevisionSummary(invite.profileName, inviteProfileId)
    return {
      invite = invite,
      selfKey = selfKey,
      joinedAt = time and time() or 0,
      payloadDetails = GetMemberPayloadDetails(nil, true),
      localRevisionSummary = localRevisionSummary,
      existingSharedProfileName = existingSharedProfileName,
      attempts = 0,
      confirmed = false,
    }
  end

  SendJoinRequest = function(sessionId, isRetry)
    local request = pendingJoinRequests[TrimText(sessionId)]
    if type(request) ~= "table" or request.confirmed then
      return false, "No pending join request."
    end
    local invite = type(request.invite) == "table" and request.invite or {}
    if TrimText(invite.sessionId) == "" or TrimText(invite.profileName) == "" or NormalizeCharacterKey(invite.host) == "" then
      return false, "Pending invite is incomplete."
    end

    request.attempts = math.max(0, tonumber(request.attempts) or 0) + 1
    local payloadDetails = type(request.payloadDetails) == "table" and request.payloadDetails or GetMemberPayloadDetails(nil, true)
    request.payloadDetails = payloadDetails
    local localRevisionSummary = type(request.localRevisionSummary) == "table" and request.localRevisionSummary or BuildEmptyRevisionSummary(invite.profileName, invite.profileId)
    local function TrySendJoin(args)
      return SendComm("JOIN", "WHISPER", invite.host, unpack(args))
    end
    local joinSent, joinError = TrySendJoin({
      invite.sessionId,
      invite.profileName,
      request.selfKey,
      request.joinedAt,
      payloadDetails.addonVersion,
      payloadDetails.clientVersion,
      payloadDetails.className,
      payloadDetails.classFile,
      payloadDetails.specName,
      payloadDetails.specIcon,
      payloadDetails.localAutoPassEnabled and "1" or "0",
      invite.profileId,
      tostring(localRevisionSummary.settings or 0),
      tostring(localRevisionSummary.permissions or 0),
      tostring(localRevisionSummary.operational or 0),
      tostring(localRevisionSummary.updatedAt or 0),
      request.existingSharedProfileName ~= "" and "1" or "0",
      GetCommProtocolMarker(),
      TrimText(localRevisionSummary.settingsChecksum),
      TrimText(localRevisionSummary.permissionsChecksum),
      TrimText(localRevisionSummary.operationalChecksum),
      tostring(localRevisionSummary.loot or localRevisionSummary.operational or 0),
      tostring(localRevisionSummary.session or localRevisionSummary.operational or 0),
      TrimText(localRevisionSummary.lootChecksum),
      TrimText(localRevisionSummary.sessionChecksum)
    })
    if not joinSent and string.find(tostring(joinError or ""), "Payload exceeds safe addon message length", 1, true) then
      joinSent, joinError = TrySendJoin({
        invite.sessionId,
        invite.profileName,
        request.selfKey,
        request.joinedAt,
        payloadDetails.addonVersion,
        payloadDetails.clientVersion,
        payloadDetails.className,
        payloadDetails.classFile,
        payloadDetails.specName,
        payloadDetails.specIcon,
        payloadDetails.localAutoPassEnabled and "1" or "0",
        invite.profileId,
        tostring(localRevisionSummary.settings or 0),
        tostring(localRevisionSummary.permissions or 0),
        tostring(localRevisionSummary.operational or 0),
        tostring(localRevisionSummary.updatedAt or 0),
        request.existingSharedProfileName ~= "" and "1" or "0",
        GetCommProtocolMarker()
      })
    end

    if joinSent then
      if isRetry then
        Print("Still waiting for host confirmation for \"" .. tostring(invite.profileName) .. "\". Retried join request " .. tostring(request.attempts) .. "/" .. tostring(JOIN_ACK_MAX_ATTEMPTS) .. ".")
      else
        Print("Join request sent for \"" .. tostring(invite.profileName) .. "\". Waiting for host confirmation before creating the local session.")
      end
    else
      Print("Could not send join request to the session host: " .. tostring(joinError or "JOIN send failed."))
    end

    if request.attempts < JOIN_ACK_MAX_ATTEMPTS and type(C_Timer) == "table" and type(C_Timer.After) == "function" then
      C_Timer.After(JOIN_ACK_RETRY_SECONDS, function()
        local pending = pendingJoinRequests[TrimText(sessionId)]
        if type(pending) == "table" and not pending.confirmed then
          SendJoinRequest(sessionId, true)
        end
      end)
    elseif request.attempts >= JOIN_ACK_MAX_ATTEMPTS and type(C_Timer) == "table" and type(C_Timer.After) == "function" then
      C_Timer.After(JOIN_ACK_RETRY_SECONDS, function()
        local pending = pendingJoinRequests[TrimText(sessionId)]
        if type(pending) == "table" and not pending.confirmed then
          Print("The session host did not confirm your join request for \"" .. tostring(invite.profileName) .. "\". Ask the host to send the invite again.")
          pendingJoinRequests[TrimText(sessionId)] = nil
          pendingInvites[TrimText(sessionId)] = nil
          RefreshEditor()
        end
      end)
    end

    RefreshEditor()
    return joinSent, joinError
  end

  local function EnsureSessionPopup()
    if type(StaticPopupDialogs) ~= "table" or StaticPopupDialogs.LIDCOUNCIL_SESSION_INVITE then
      return
    end

    StaticPopupDialogs.LIDCOUNCIL_SESSION_INVITE = {
      text = "%s prepared a new Loot Session with the profile \"%s\".\n\nBy joining, your local Auto Pass starts as ON by default. You can change that later in Session -> Auto Pass Setting.\n\nDo you want to join the preparation lobby?",
      button1 = YES,
      button2 = NO,
      timeout = 0,
      whileDead = 1,
      hideOnEscape = 1,
      preferredIndex = 3,
      OnAccept = function(self, data)
        local invite = data or self.data
        if not invite then
          return
        end
        local inviteProtocolVersion = math.max(1, tonumber(invite.protocolVersion) or 1)
        if inviteProtocolVersion ~= COMM_PROTOCOL_VERSION then
          local selfKey = NormalizeCharacterKey(GetCharacterKey() or "Unknown")
          SendComm("DECLINE", "WHISPER", invite.host, invite.sessionId, invite.profileName, selfKey)
          Print("Could not join \"" .. tostring(invite.profileName) .. "\" because the session host is using an incompatible LidCouncil build. Update both clients to the same build and try again.")
          pendingInvites[invite.sessionId] = nil
          return
        end
        SetLocalAutoPassEnabled(true)
        pendingJoinRequests[invite.sessionId] = BuildPendingJoinRequest(invite)
        SendJoinRequest(invite.sessionId, false)
        RefreshEditor()
      end,
      OnCancel = function(self, data)
        local invite = data or self.data
        if not invite then
          return
        end
        local selfKey = NormalizeCharacterKey(GetCharacterKey() or "Unknown")
        SendComm("DECLINE", "WHISPER", invite.host, invite.sessionId, invite.profileName, selfKey)
        pendingInvites[invite.sessionId] = nil
        pendingJoinRequests[invite.sessionId] = nil
      end,
    }
  end

  local function ShowSessionInvite(invite)
    EnsureSessionPopup()
    if type(StaticPopup_Show) ~= "function" then
      return
    end
    local dialog = StaticPopup_Show("LIDCOUNCIL_SESSION_INVITE", tostring(invite.host), tostring(invite.profileName), invite)
    if dialog then
      dialog.data = invite
      if dialog.text and dialog.text.SetText then
        local inviteStatus = string.upper(TrimText(invite.status))
        local actionText = inviteStatus == "ACTIVE" and "started an active Loot Session" or "prepared a new Loot Session"
        local questionText = inviteStatus == "ACTIVE" and "Do you want to join the active session?" or "Do you want to join the preparation lobby?"
        dialog.text:SetText(string.format(
          "%s %s with the profile \"%s\".\n\nBy joining, your local Auto Pass starts as ON by default. You can change that later in Session -> Auto Pass Setting.\n\n%s",
          tostring(invite.host),
          actionText,
          tostring(invite.profileName),
          questionText
        ))
      end
    end
  end

  local function BroadcastMember(profileName, sessionId, memberKey, memberData, channel, target)
    local details = type(memberData) == "table" and memberData or {}
    local payloadDetails = GetMemberPayloadDetails(details, false)
    local profileMaster = FirstNonEmptyText(details.profileMaster, GetLootProfileMaster(profileName))
    local memberRole = FirstNonEmptyText(details.role, GetLootProfileRole(profileName, memberKey))
    local profileId = FirstNonEmptyText(details.sharedProfileId, details.profileId, select(1, GetLootProfileId(profileName)))
    local revisionSummary = type(details.revisionSummary) == "table" and details.revisionSummary or GetLootProfileRevisionSummary(profileName)
    local settingsRevision = tonumber(details.settingsRevision) or tonumber(revisionSummary and revisionSummary.settings) or 0
    local permissionsRevision = tonumber(details.permissionsRevision) or tonumber(revisionSummary and revisionSummary.permissions) or 0
    local operationalRevision = tonumber(details.operationalRevision) or tonumber(revisionSummary and revisionSummary.operational) or 0
    local lootRevision = tonumber(details.lootRevision) or tonumber(revisionSummary and revisionSummary.loot) or operationalRevision
    local sessionRevision = tonumber(details.sessionRevision) or tonumber(revisionSummary and revisionSummary.session) or operationalRevision
    local profileUpdatedAt = tonumber(details.profileUpdatedAt) or tonumber(revisionSummary and revisionSummary.updatedAt) or 0
    local settingsChecksum = FirstNonEmptyText(details.settingsChecksum, revisionSummary and revisionSummary.settingsChecksum)
    local permissionsChecksum = FirstNonEmptyText(details.permissionsChecksum, revisionSummary and revisionSummary.permissionsChecksum)
    local operationalChecksum = FirstNonEmptyText(details.operationalChecksum, revisionSummary and revisionSummary.operationalChecksum)
    local lootChecksum = FirstNonEmptyText(details.lootChecksum, revisionSummary and revisionSummary.lootChecksum, operationalChecksum)
    local sessionChecksum = FirstNonEmptyText(details.sessionChecksum, revisionSummary and revisionSummary.sessionChecksum, operationalChecksum)
    local distribution = channel or GetGroupDistribution()
    if not distribution then
      return false
    end
    local sent = SendComm(
      "MEMBER",
      distribution,
      target,
      sessionId,
      profileName,
      memberKey,
      details.status or "JOINED",
      details.joinedAt or (time and time() or 0),
      payloadDetails.addonVersion,
      payloadDetails.clientVersion,
      payloadDetails.className,
      payloadDetails.classFile,
      payloadDetails.specName,
      payloadDetails.specIcon,
      payloadDetails.localAutoPassEnabled and "1" or "0",
      profileMaster,
      memberRole,
      profileId,
      tostring(settingsRevision),
      tostring(permissionsRevision),
      tostring(operationalRevision),
      tostring(profileUpdatedAt),
      settingsChecksum,
      permissionsChecksum,
      operationalChecksum,
      tostring(tonumber(details.leftAt) or ""),
      tostring(lootRevision),
      tostring(sessionRevision),
      lootChecksum,
      sessionChecksum
    )
    if sent then
      local activeSession, activeProfileName = GetActiveLootSession()
      local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
      if type(activeSession) == "table"
          and TrimText(activeSession.id) == TrimText(sessionId)
          and DoesActiveSessionMatch(activeSession, activeProfileName, sessionId, profileName)
          and AreCharacterKeysSame(activeSession.host or "", selfKey) then
        QueueSessionRecordCheckpoint(profileName, sessionId, "session_member_checkpoint", memberKey)
      end
    end
    return sent
  end

  local function SendMemberSnapshot(activeSession, profileName, target)
    if type(activeSession) ~= "table" or type(activeSession.members) ~= "table" then
      return
    end
    for memberKey, member in pairs(activeSession.members) do
      BroadcastMember(profileName, activeSession.id, memberKey, member, "WHISPER", target)
    end
  end

  local function SendJoinAck(activeSession, profileName, memberKey)
    if type(activeSession) ~= "table" then
      return false, "No active session."
    end
    local resolvedMemberKey = NormalizeCharacterKey(memberKey)
    if resolvedMemberKey == "" then
      return false, "Join ACK target is missing."
    end
    return SendComm(
      "JACK",
      "WHISPER",
      resolvedMemberKey,
      activeSession.id,
      profileName,
      TrimText(select(1, GetLootProfileId(profileName)) or ""),
      activeSession.host,
      GetLootProfileMaster(profileName),
      tostring(activeSession.startedAt or (time and time() or 0)),
      activeSession.status or "PREPARING",
      tostring(activeSession.activatedAt or ""),
      GetCommProtocolMarker(),
      resolvedMemberKey
    )
  end

  QueueProfileSnapshotForMember = function(profileName, sessionId, memberKey, opts)
    local resolvedMemberKey = NormalizeCharacterKey(memberKey)
    if resolvedMemberKey == "" then
      return false, "Profile snapshot target is missing."
    end
    opts = type(opts) == "table" and opts or {}
    if type(opts.preparedSnapshot) == "table" then
      if type(SendPreparedProfileSnapshotBatch) == "function" then
        return SendPreparedProfileSnapshotBatch(opts.preparedSnapshot, sessionId, { resolvedMemberKey }, opts)
      end
      if type(SendPreparedProfileSnapshot) == "function" then
        return SendPreparedProfileSnapshot(opts.preparedSnapshot, sessionId, resolvedMemberKey, opts)
      end
    end
    if type(SendProfileSnapshotBatch) == "function" then
      return SendProfileSnapshotBatch(profileName, sessionId, { resolvedMemberKey }, opts)
    end
    return SendProfileSnapshot(profileName, sessionId, resolvedMemberKey, opts)
  end

  local function QueueMissingMemberBootstrapSync(profileName, sessionId, memberKey)
    local preparedBootstrap, bootstrapError = PrepareProfileSnapshotTransfer(profileName, {
      domains = PROFILE_BOOTSTRAP_DOMAINS,
    })
    if not preparedBootstrap then
      return false, false, bootstrapError
    end

    local queuedBootstrap, queueBootstrapError = QueueProfileSnapshotForMember(profileName, sessionId, memberKey, {
      mode = "LIVE",
      reason = "missing_member_bootstrap",
      domains = PROFILE_BOOTSTRAP_DOMAINS,
      preparedSnapshot = preparedBootstrap,
    })
    if not queuedBootstrap then
      return false, false, queueBootstrapError
    end

    local preparedBackground, backgroundError = PrepareProfileSnapshotTransfer(profileName, {
      domains = PROFILE_BACKGROUND_SYNC_DOMAINS,
    })
    if not preparedBackground then
      return true, false, backgroundError
    end

    local queuedBackground, queueBackgroundError = QueueProfileSnapshotForMember(profileName, sessionId, memberKey, {
      mode = "LIVE",
      reason = "missing_member_background_sync",
      domains = PROFILE_BACKGROUND_SYNC_DOMAINS,
      preparedSnapshot = preparedBackground,
    })
    if not queuedBackground then
      return true, false, queueBackgroundError
    end

    return true, true, nil
  end

  local function BuildStartSessionSyncWarning(candidates)
    local summary = {
      joined = 0,
      aligned = 0,
      rollReady = 0,
      bootstrapPending = 0,
      bootstrapReview = 0,
      lineageMismatch = 0,
      notAligned = 0,
    }

    for _, candidate in ipairs(type(candidates) == "table" and candidates or {}) do
      summary.joined = summary.joined + 1
      local comparison = string.lower(TrimText(candidate.comparison))
      local bootstrapState = string.lower(TrimText(candidate.bootstrapState))
      if comparison == "same" then
        summary.aligned = summary.aligned + 1
      else
        summary.notAligned = summary.notAligned + 1
      end
      if bootstrapState == "ready" then
        summary.rollReady = summary.rollReady + 1
      elseif bootstrapState == "review" then
        summary.bootstrapReview = summary.bootstrapReview + 1
      elseif bootstrapState == "lineage" then
        summary.bootstrapReview = summary.bootstrapReview + 1
        summary.lineageMismatch = summary.lineageMismatch + 1
      else
        summary.bootstrapPending = summary.bootstrapPending + 1
      end
    end

    local lines = {}
    if summary.joined > 0 then
      lines[#lines + 1] = "Roll-ready joined members: "
        .. tostring(summary.rollReady) .. " / " .. tostring(summary.joined) .. "."
      if summary.bootstrapPending > 0 then
        lines[#lines + 1] = tostring(summary.bootstrapPending)
          .. " joined member bootstrap cop" .. (summary.bootstrapPending == 1 and "y is" or "ies are")
          .. " still pending. Those players may not receive the roll popup yet."
      end
      if summary.bootstrapReview > 0 then
        lines[#lines + 1] = tostring(summary.bootstrapReview)
          .. " joined member bootstrap cop" .. (summary.bootstrapReview == 1 and "y needs" or "ies need")
          .. " review before trusting roll choices."
      end
      if summary.notAligned > 0 then
        lines[#lines + 1] = tostring(summary.notAligned)
          .. " joined member profile cop" .. (summary.notAligned == 1 and "y is" or "ies are")
          .. " still not fully aligned. Loot and session history can keep syncing in the background."
      end
    end

    return summary, lines
  end

  local function ExtendProfileSnapshotJoinGrace(sessionId, profileName, seconds, reason)
    if type(DelayProfileSnapshotBatchForJoins) ~= "function" then
      return false
    end
    return DelayProfileSnapshotBatchForJoins(sessionId, seconds, reason, profileName)
  end

  local function HasJoinedActiveLootSession()
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not profileName then
      return false, nil, nil
    end
    if not IsLiveSession(activeSession) then
      return false, nil, nil
    end
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if selfKey == "" then
      return false, nil, nil
    end
    if not IsJoinedSessionCharacter(activeSession, selfKey) then
      return false, nil, nil
    end
    return true, activeSession, profileName
  end

  local function StartLootSessionFlow(profileName)
    local blocked, blockedMessage = RejectCombatLockedAction("Prepare Session")
    if blocked then
      RefreshEditor()
      return false, blockedMessage
    end

    local session, err = StartLootSession(profileName)
    if not session then
      if err then
        Print(tostring(err))
      end
      RefreshEditor()
      return false, err
    end

    SetLocalAutoPassEnabled(false)
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if selfKey ~= "" then
      UpsertLootSessionMember(session.profileName, session.id, selfKey, {
        localAutoPassEnabled = false,
      })
    end
    ExtendProfileSnapshotJoinGrace(session.id, session.profileName, PREPARE_JOIN_GRACE_SECONDS, "prepare_session")

    local clearRuntime = ResolveOptionalApiFunction("LIDCOUNCIL_ClearLiveLootRuntime")
    if type(clearRuntime) == "function" then
      clearRuntime()
    end
    local distribution = GetGroupDistribution()
    if distribution then
      SendComm(
        "START",
        distribution,
        nil,
        session.id,
        session.profileName,
        TrimText(select(1, GetLootProfileId(session.profileName)) or ""),
        session.host,
        session.startedAt,
        GetLootProfileMaster(session.profileName),
        GetCommProtocolMarker(),
        session.status or "PREPARING"
      )
      Print("Prepared loot session \"" .. tostring(session.profileName) .. "\".")
    else
      Print("Prepared local loot session \"" .. tostring(session.profileName) .. "\". No raid or party channel is available yet.")
    end
    SetProfileSyncRuntimeState(session.id, session.profileName, "session_prepared", "info",
      "Preparation lobby is open. Joined member profile revisions can be compared before the session is started.", {
        sender = selfKey,
        refreshEditor = false,
      })
    Print("As session host, your personal Auto Pass starts OFF by default. Joined members start with personal Auto Pass ON and can change it any time in Session -> Auto Pass Setting.")
    RefreshEditor()
    return true, session
  end

  local function SendActiveSessionInviteFlow()
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not profileName then
      Print("No active loot session.")
      return false, "No active session."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      Print("Only the loot session host can send session invites.")
      return false, "Only the host can send session invites."
    end

    local blocked, blockedMessage = RejectCombatLockedAction("Send Session Invite")
    if blocked then
      return false, blockedMessage
    end

    local distribution = GetGroupDistribution()
    if not distribution then
      Print("No raid or party channel is available yet.")
      return false, "No raid or party channel is available yet."
    end

    local inviteTargets = {}
    for _, memberKey in ipairs(CollectGroupCharacterKeys()) do
      local existingMember = FindSessionMember(activeSession, memberKey)
      local existingStatus = string.upper(TrimText(type(existingMember) == "table" and existingMember.status or ""))
      if memberKey ~= "" and not AreCharacterKeysSame(memberKey, selfKey) and (not existingMember or existingStatus ~= "JOINED") then
        inviteTargets[#inviteTargets + 1] = memberKey
      end
    end

    if #inviteTargets == 0 then
      Print("No new raid members were found for this active session.")
      return true, 0
    end

    ExtendProfileSnapshotJoinGrace(activeSession.id, activeSession.profileName or profileName, INVITE_JOIN_GRACE_SECONDS, "manual_invite")
    local sentCount = 0
    for _, memberKey in ipairs(inviteTargets) do
      local sent = SendComm(
        "START",
        "WHISPER",
        memberKey,
        activeSession.id,
        activeSession.profileName,
        TrimText(select(1, GetLootProfileId(activeSession.profileName)) or ""),
        activeSession.host,
        activeSession.startedAt,
        GetLootProfileMaster(activeSession.profileName),
        GetCommProtocolMarker(),
        activeSession.status or "PREPARING"
      )
      if sent then
        sentCount = sentCount + 1
      end
    end

    if sentCount > 0 then
      Print("Sent session invite to " .. tostring(sentCount) .. " late joiner" .. (sentCount == 1 and "" or "s") .. ".")
    else
      Print("No session invites could be sent.")
    end
    RefreshEditor()
    return sentCount > 0, sentCount
  end

  local function RequestActiveProfileSubchecksumFlow(targetMemberKey)
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not profileName then
      Print("No active loot session.")
      return false, "No active session."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      Print("Only the loot session host can request detailed shared-profile comparisons.")
      return false, "Only the host can request detailed shared-profile comparisons."
    end

    local blocked, blockedMessage = RejectCombatLockedAction("Check Differences")
    if blocked then
      return false, blockedMessage
    end

    local requestedTarget = NormalizeCharacterKey(targetMemberKey)
    local targets = {}
    if requestedTarget ~= "" then
      targets[1] = requestedTarget
    else
      for _, candidate in ipairs(type(GetActiveProfileSyncCandidates) == "function" and GetActiveProfileSyncCandidates() or {}) do
        local memberKey = NormalizeCharacterKey(type(candidate) == "table" and candidate.memberKey or "")
        if memberKey ~= "" then
          targets[#targets + 1] = memberKey
        end
      end
    end

    local requestedCount, skippedAligned, skippedLoaded = SendDetailedComparisonRequests(targets, {
      force = true,
    })

    if requestedCount > 0 then
      local message = "Requested detailed checksum scopes from " .. tostring(requestedCount) .. " joined member"
        .. (requestedCount == 1 and "" or "s") .. "."
      if skippedAligned > 0 then
        message = message .. " Already aligned or full-fallback members skipped: " .. tostring(skippedAligned) .. "."
      end
      if skippedLoaded > 0 then
        message = message .. " Already loaded: " .. tostring(skippedLoaded) .. "."
      end
      SetProfileSyncRuntimeState(activeSession.id, profileName, "subchecks_requested", "info", message, {
        sender = selfKey,
        refreshEditor = false,
      })
      Print(message)
    elseif skippedAligned > 0 or skippedLoaded > 0 then
      Print("No additional detailed checksum request was needed for the selected members.")
    else
      Print("No joined member comparison targets are available.")
    end
    RefreshEditor()
    return requestedCount > 0, requestedCount
  end

  local function PushActiveProfileSnapshotFlow(targetMemberKey, options)
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not profileName then
      Print("No active loot session.")
      return false, "No active session."
    end
    options = type(options) == "table" and options or {}

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      Print("Only the loot session host can push a shared profile update.")
      return false, "Only the host can push a shared profile update."
    end

    local blocked, blockedMessage = RejectCombatLockedAction("Push Host Repair")
    if blocked then
      return false, blockedMessage
    end

    local explicitDomains = type(options.domains) == "table" and options.domains or nil
    local explicitSubdomains = type(options.subdomains) == "table" and options.subdomains or nil
    local explicitScopeSelected = (type(explicitDomains) == "table" and #explicitDomains > 0)
      or (type(explicitSubdomains) == "table" and #explicitSubdomains > 0)

    local targets = {}
    local requestedTarget = NormalizeCharacterKey(targetMemberKey)
    if explicitScopeSelected and requestedTarget == "" then
      Print("Select one joined member when pushing only selected leaf scopes.")
      return false, "Leaf scope push requires a selected member."
    end
    if requestedTarget ~= "" then
      if AreCharacterKeysSame(requestedTarget, selfKey) then
        Print("The host does not need to push the shared profile to themselves.")
        return false, "Target must be another joined member."
      end
      if not IsJoinedSessionCharacter(activeSession, requestedTarget) then
        Print("That character is not currently joined to the active loot session.")
        return false, "Target is not joined."
      end
      targets[1] = requestedTarget
    else
      for memberKey, member in pairs(activeSession.members or {}) do
        local resolvedKey = NormalizeCharacterKey(memberKey)
        if resolvedKey ~= "" and not AreCharacterKeysSame(resolvedKey, selfKey) and type(member) == "table" and tostring(member.status or "JOINED") == "JOINED" then
          targets[#targets + 1] = resolvedKey
        end
      end
      table.sort(targets)
    end

    if #targets == 0 then
      Print("No joined session members are available to receive a shared profile update.")
      return false, "No joined session members."
    end

    local sentCount = 0
    local memberSentCount = 0
    local targetedCount = 0
    local preciseCount = 0
    local patchTransferCount = 0
    local patchScopeCount = 0
    local fullFallbackCount = 0
    local skippedAlignedCount = 0
    local skippedMemberNewerCount = 0
    local lastSendError = nil
    for _, memberKey in ipairs(targets) do
      local repairDomains, repairSubdomains, forceFullSnapshot, repairMode
      if explicitScopeSelected then
        repairDomains = explicitDomains
        repairSubdomains = explicitSubdomains
        forceFullSnapshot = false
        repairMode = (#(repairSubdomains or {}) > 0) and "precise" or "targeted"
      else
        repairDomains, repairSubdomains, forceFullSnapshot, repairMode = BuildHostRepairDomainsForMember(memberKey)
      end
      if repairMode == "same" then
        skippedAlignedCount = skippedAlignedCount + 1
      elseif repairMode == "member_newer" then
        skippedMemberNewerCount = skippedMemberNewerCount + 1
      else
        local preparedTransfers = nil
        local prepareError = nil
        local prepareDetail = {
          patchTransfers = 0,
          patchSubdomains = 0,
        }
        if not forceFullSnapshot
          and type(BuildPreparedProfileRepairTransfers) == "function"
          and type(repairSubdomains) == "table"
          and #repairSubdomains > 0
        then
          preparedTransfers, prepareError, prepareDetail = BuildPreparedProfileRepairTransfers(profileName, activeSession.id, memberKey, {
            domains = repairDomains,
            subdomains = repairSubdomains,
          })
        else
          local preparedSnapshot
          preparedSnapshot, prepareError = PrepareProfileSnapshotTransfer(profileName, {
            domains = not forceFullSnapshot and repairDomains or nil,
            subdomains = not forceFullSnapshot and repairSubdomains or nil,
          })
          if preparedSnapshot then
            preparedTransfers = { preparedSnapshot }
          end
        end

        if type(preparedTransfers) ~= "table" or #preparedTransfers == 0 then
          lastSendError = prepareError
        else
          local memberQueued = false
          for _, preparedSnapshot in ipairs(preparedTransfers) do
            local ok, queuedCount = QueueProfileSnapshotForMember(profileName, activeSession.id, memberKey, {
              mode = "LIVE",
              reason = forceFullSnapshot and "host_push_full" or "host_push_repair",
              domains = not forceFullSnapshot and repairDomains or nil,
              subdomains = not forceFullSnapshot and repairSubdomains or nil,
              preparedSnapshot = preparedSnapshot,
            })
            if ok then
              sentCount = sentCount + (tonumber(queuedCount) or 1)
              memberQueued = true
            else
              lastSendError = queuedCount
            end
          end
          if memberQueued then
            memberSentCount = memberSentCount + 1
            if forceFullSnapshot then
              fullFallbackCount = fullFallbackCount + 1
            else
              targetedCount = targetedCount + 1
              if type(repairSubdomains) == "table" and #repairSubdomains > 0 then
                preciseCount = preciseCount + 1
              end
              patchTransferCount = patchTransferCount + math.max(0, tonumber(prepareDetail.patchTransfers) or 0)
              patchScopeCount = patchScopeCount + math.max(0, tonumber(prepareDetail.patchSubdomains) or 0)
            end
          end
        end
      end
    end

    if sentCount > 0 then
      local message = "Queued shared-profile repairs for " .. tostring(memberSentCount) .. " joined member" .. (memberSentCount == 1 and "" or "s") .. "."
      message = message
        .. " Transfers: " .. tostring(sentCount)
        .. " Targeted: " .. tostring(targetedCount)
        .. " | Precise: " .. tostring(preciseCount)
        .. " | Patch transfers: " .. tostring(patchTransferCount)
        .. " | Patch scopes: " .. tostring(patchScopeCount)
        .. " | Full fallback: " .. tostring(fullFallbackCount)
      if skippedAlignedCount > 0 then
        message = message .. " | Already aligned: " .. tostring(skippedAlignedCount)
      end
      if skippedMemberNewerCount > 0 then
        message = message .. " | Member newer/conflict skipped: " .. tostring(skippedMemberNewerCount)
      end
      SetProfileSyncRuntimeState(activeSession.id, profileName, "host_pushed", "success",
        message, {
          sender = selfKey,
          refreshEditor = false,
        })
      if type(RecordRepairHistory) == "function" then
        RecordRepairHistory({
          profileName = profileName,
          sessionId = TrimText(activeSession.id),
          memberKey = TrimText(targetMemberKey),
          kind = "host_push",
          summary = message,
          createdAt = tonumber(time and time() or 0) or 0,
        })
      end
      Print(message)
    elseif skippedAlignedCount > 0 or skippedMemberNewerCount > 0 then
      local message = "No host repair was queued."
      if skippedAlignedCount > 0 then
        message = message .. " Already aligned: " .. tostring(skippedAlignedCount) .. "."
      end
      if skippedMemberNewerCount > 0 then
        message = message .. " Member newer or mixed-difference copies should be reviewed first: " .. tostring(skippedMemberNewerCount) .. "."
      end
      Print(message)
    else
      Print("No shared profile updates could be sent." .. (lastSendError and (" " .. tostring(lastSendError)) or ""))
    end
    RefreshEditor()
    return sentCount > 0, sentCount
  end

  local function BroadcastActiveProfileSnapshotFlow(profileName, reason, targetMemberKey)
    local activeSession, activeProfileName = GetActiveLootSession()
    if not activeSession or not activeProfileName then
      return false, "No active session."
    end

    local requestedProfileName = TrimText(profileName)
    if requestedProfileName ~= "" and not DoesActiveSessionMatch(activeSession, activeProfileName, activeSession.id, requestedProfileName) then
      return false, "No matching active session profile."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if selfKey == "" or not IsJoinedSessionCharacter(activeSession, selfKey) then
      return false, "You are not joined to the active session."
    end

    local targets = CollectLiveSyncTargets(activeSession, selfKey, targetMemberKey)
    if #targets == 0 then
      return false, "No joined session members."
    end

    local preparedSnapshot, snapshotErr = PrepareProfileSnapshotTransfer(activeProfileName)
    if not preparedSnapshot then
      return false, snapshotErr or "Profile snapshot export failed."
    end

    local sourceProfile = type(GetLootProfile) == "function" and select(1, GetLootProfile(activeProfileName)) or nil
    if type(sourceProfile) == "table" and type(NormalizeLootRollOptions) == "function" then
      activeSession.rollOptions = NormalizeLootRollOptions(sourceProfile.settings and sourceProfile.settings.rollOptions)
    end
    if type(activeSession.members) == "table" then
      for memberKey, member in pairs(activeSession.members) do
        if type(member) == "table" then
          member.profileMaster = GetLootProfileMaster(activeProfileName)
          member.role = GetLootProfileRole(activeProfileName, memberKey)
        end
      end
    end

    local sentCount = 0
    if type(SendPreparedProfileSnapshotBatch) == "function" then
      local ok, queuedCount = SendPreparedProfileSnapshotBatch(preparedSnapshot, activeSession.id, targets, {
        mode = "LIVE",
        reason = TrimText(reason),
      })
      if ok then
        sentCount = tonumber(queuedCount) or #targets
      end
    else
      for _, memberKey in ipairs(targets) do
        local ok = SendPreparedProfileSnapshot(preparedSnapshot, activeSession.id, memberKey, {
          mode = "LIVE",
          reason = TrimText(reason),
        })
        if ok then
          sentCount = sentCount + 1
        end
      end
    end

    if sentCount > 0 then
      SetProfileSyncRuntimeState(activeSession.id, activeProfileName, "live_broadcast", "success",
        "Queued a live shared profile update for " .. tostring(sentCount) .. " joined member" .. (sentCount == 1 and "" or "s") .. ".", {
          sender = selfKey,
          refreshEditor = false,
        })
    end
    return sentCount > 0, sentCount
  end

  local function BroadcastActiveProfileDeltaFlow(profileName, reason, change)
    local activeSession, activeProfileName = GetActiveLootSession()
    if not activeSession or not activeProfileName then
      return false, "No active session."
    end

    local requestedProfileName = TrimText(profileName)
    if requestedProfileName ~= "" and not DoesActiveSessionMatch(activeSession, activeProfileName, activeSession.id, requestedProfileName) then
      return false, "No matching active session profile."
    end
    if type(change) ~= "table" or TrimText(change.action) == "" then
      return false, "Profile delta is missing."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if selfKey == "" or not IsJoinedSessionCharacter(activeSession, selfKey) then
      return false, "You are not joined to the active session."
    end

    local profileId = TrimText(select(1, GetLootProfileId(activeProfileName)) or "")
    local delta = {
      profileId = profileId,
      changeId = BuildProfileDeltaId(),
      actor = selfKey,
      domain = TrimText(change.domain) ~= "" and TrimText(change.domain) or TrimText(reason),
      action = TrimText(change.action),
      args = type(change.args) == "table" and change.args or {},
    }
    MarkProfileDeltaSeen(delta.changeId)

    local revisionSummary = GetLootProfileRevisionSummary(activeProfileName)
    RefreshActiveSessionProfileCache(activeSession, activeProfileName)
    if AreCharacterKeysSame(activeSession.host or "", selfKey) then
      local distribution = GetGroupDistribution()
      if not distribution then
        return false, "No group channel."
      end
      local sent, err = SendProfileDelta("PDELTA", distribution, nil, activeSession, activeProfileName, delta, revisionSummary)
      if sent then
        TrackProfileDeltaAcks(activeSession, activeProfileName, delta, revisionSummary)
      end
      return sent, err
    end

    local hostKey = NormalizeCharacterKey(activeSession.host)
    if hostKey == "" then
      return false, "No session host."
    end
    return SendProfileDelta("PDELTA_REQ", "WHISPER", hostKey, activeSession, activeProfileName, delta, revisionSummary)
  end

  local function HandleProfileDeltaRequest(fields, sender)
    local delta = ReadProfileDeltaFields(fields)
    if delta.sessionId == "" or delta.profileName == "" or delta.changeId == "" or delta.action == "" then
      return
    end
    if HasProfileDeltaSeen(delta.changeId) then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not DoesActiveSessionMatch(activeSession, activeProfileName, delta.sessionId, delta.profileName) then
      return
    end
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      return
    end
    if not IsClaimedActorSenderMatch(sender, delta.actor) then
      return
    end
    if not IsJoinedSessionCharacter(activeSession, delta.actor) then
      return
    end

    local localProfileName = TrimText(activeProfileName) ~= "" and activeProfileName or delta.profileName
    if delta.profileId ~= "" and TrimText(select(1, GetLootProfileId(localProfileName)) or "") ~= delta.profileId then
      return
    end

    if type(ApplyIncomingLootProfileDelta) ~= "function" then
      return
    end
    local ok = ApplyIncomingLootProfileDelta(localProfileName, delta.domain, delta.action, delta.args, {
      actor = delta.actor,
      source = "request",
    })
    if not ok then
      return
    end
    MarkProfileDeltaSeen(delta.changeId)
    RefreshActiveSessionProfileCache(activeSession, localProfileName)

    local revisionSummary = GetLootProfileRevisionSummary(localProfileName)
    local member = activeSession.members and activeSession.members[delta.actor]
    if type(member) == "table" then
      member.sharedProfileId = TrimText(select(1, GetLootProfileId(localProfileName)) or "")
      member.settingsRevision = tonumber(revisionSummary.settings) or 0
      member.permissionsRevision = tonumber(revisionSummary.permissions) or 0
      member.operationalRevision = tonumber(revisionSummary.operational) or 0
      member.lootRevision = tonumber(revisionSummary.loot) or tonumber(revisionSummary.operational) or 0
      member.sessionRevision = tonumber(revisionSummary.session) or tonumber(revisionSummary.operational) or 0
      member.settingsChecksum = TrimText(revisionSummary.settingsChecksum)
      member.permissionsChecksum = TrimText(revisionSummary.permissionsChecksum)
      member.operationalChecksum = TrimText(revisionSummary.operationalChecksum)
      member.lootChecksum = TrimText(revisionSummary.lootChecksum)
      member.sessionChecksum = TrimText(revisionSummary.sessionChecksum)
      member.profileUpdatedAt = tonumber(revisionSummary.updatedAt) or 0
      BroadcastMember(localProfileName, activeSession.id, delta.actor, member)
    end

    local distribution = GetGroupDistribution()
    if distribution then
      local sent = SendProfileDelta("PDELTA", distribution, nil, activeSession, localProfileName, delta, revisionSummary)
      if not sent then
        BroadcastActiveProfileSnapshotFlow(localProfileName, "delta_fallback")
      else
        TrackProfileDeltaAcks(activeSession, localProfileName, delta, revisionSummary)
      end
    end
    RefreshEditor()
  end

  local function HandleProfileDelta(fields, sender)
    local delta = ReadProfileDeltaFields(fields)
    if delta.sessionId == "" or delta.profileName == "" or delta.changeId == "" or delta.action == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesActiveSessionMatch(activeSession, activeProfileName, delta.sessionId, delta.profileName) then
      return
    end
    if not IsActiveSessionHostSender(activeSession, sender) then
      return
    end
    if not IsJoinedSessionCharacter(activeSession, delta.actor) then
      return
    end

    local localProfileName = TrimText(activeProfileName) ~= "" and activeProfileName or delta.profileName
    if delta.profileId ~= "" and TrimText(select(1, GetLootProfileId(localProfileName)) or "") ~= delta.profileId then
      return
    end
    if type(ApplyIncomingLootProfileDelta) ~= "function" then
      return
    end

    if HasProfileDeltaSeen(delta.changeId) then
      RememberProfileDeltaSequence(delta)
      local aligned = IsLocalProfileAlignedWithDelta(localProfileName, delta)
      if not aligned then
        RequestProfileDeltaRecovery(activeSession, localProfileName, delta, "checksum_mismatch")
        return
      end
      SendProfileDeltaAck(activeSession, localProfileName, delta, GetLootProfileRevisionSummary(localProfileName))
      return
    end
    if IsProfileDeltaSequenceStale(delta) then
      RequestProfileDeltaRecovery(activeSession, localProfileName, delta, "stale_sequence")
      SetProfileSyncRuntimeState(delta.sessionId, localProfileName, "delta_stale_recovery", "warn",
        "An older profile update arrived after a newer one. Requested a full host profile refresh.", {
          sender = NormalizeSenderKey(sender),
          refreshEditor = false,
        })
      RefreshEditor()
      return
    end
    if IsProfileDeltaSequenceGap(delta) then
      RequestProfileDeltaRecovery(activeSession, localProfileName, delta, "sequence_gap")
      SetProfileSyncRuntimeState(delta.sessionId, localProfileName, "delta_gap_recovery", "warn",
        "A profile update was missed. Requested a full host profile refresh.", {
          sender = NormalizeSenderKey(sender),
          refreshEditor = false,
        })
      RefreshEditor()
      return
    end

    local ok = ApplyIncomingLootProfileDelta(localProfileName, delta.domain, delta.action, delta.args, {
      actor = delta.actor,
      source = "host",
      skipAccessCheck = true,
    })
    if not ok then
      RequestProfileDeltaRecovery(activeSession, localProfileName, delta, "apply_failed")
      return
    end
    local aligned = IsLocalProfileAlignedWithDelta(localProfileName, delta)
    if not aligned then
      RequestProfileDeltaRecovery(activeSession, localProfileName, delta, "checksum_mismatch")
      SetProfileSyncRuntimeState(delta.sessionId, localProfileName, "delta_checksum_recovery", "warn",
        "A profile update did not match the host checksum. Requested a full host profile refresh.", {
          sender = NormalizeSenderKey(sender),
          refreshEditor = false,
        })
      RefreshEditor()
      return
    end
    MarkProfileDeltaSeen(delta.changeId)
    RememberProfileDeltaSequence(delta)
    SendProfileDeltaAck(activeSession, localProfileName, delta, GetLootProfileRevisionSummary(localProfileName))
    RefreshActiveSessionProfileCache(activeSession, localProfileName)
    RefreshEditor()
  end

  local function HandleProfileDeltaAck(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local changeId = TrimText(fields[4])
    local memberKey = NormalizeCharacterKey(fields[5] ~= "" and fields[5] or sender)
    local sequence = tonumber(fields[6]) or 0
    local settingsRevision = tonumber(fields[7]) or 0
    local permissionsRevision = tonumber(fields[8]) or 0
    local operationalRevision = tonumber(fields[9]) or 0
    local profileUpdatedAt = tonumber(fields[10]) or 0
    local settingsChecksum = TrimText(fields[11])
    local permissionsChecksum = TrimText(fields[12])
    local operationalChecksum = TrimText(fields[13])
    local lootRevision = math.max(0, tonumber(fields[14]) or operationalRevision)
    local sessionRevision = math.max(0, tonumber(fields[15]) or operationalRevision)
    local lootChecksum = TrimText(fields[16])
    if lootChecksum == "" then
      lootChecksum = operationalChecksum
    end
    local sessionChecksum = TrimText(fields[17])
    if sessionChecksum == "" then
      sessionChecksum = operationalChecksum
    end
    if sessionId == "" or profileName == "" or changeId == "" or memberKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not DoesActiveSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      return
    end
    if not IsClaimedActorSenderMatch(sender, memberKey) then
      return
    end

    local pending = pendingProfileDeltaAcks[changeId]
    if type(pending) == "table" and type(pending.missing) == "table" then
      pending.missing[memberKey] = nil
      if not next(pending.missing) then
        pendingProfileDeltaAcks[changeId] = nil
      end
    end

    local ok, member = UpsertLootSessionMember(profileName, sessionId, memberKey, {
      settingsRevision = settingsRevision,
      permissionsRevision = permissionsRevision,
      operationalRevision = operationalRevision,
      lootRevision = lootRevision,
      sessionRevision = sessionRevision,
      settingsChecksum = settingsChecksum,
      permissionsChecksum = permissionsChecksum,
      operationalChecksum = operationalChecksum,
      lootChecksum = lootChecksum,
      sessionChecksum = sessionChecksum,
      profileUpdatedAt = profileUpdatedAt,
      lastSyncAt = time and time() or 0,
      suppressProfileTouch = true,
    })
    if ok and type(member) == "table" then
      member.lastProfileDeltaAck = math.max(tonumber(member.lastProfileDeltaAck) or 0, sequence)
      BroadcastMember(profileName, sessionId, memberKey, member)
    end
    RefreshEditor()
  end

  local function HandleProfileDeltaNack(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local changeId = TrimText(fields[4])
    local memberKey = NormalizeCharacterKey(fields[5] ~= "" and fields[5] or sender)
    local sequence = tonumber(fields[6]) or 0
    local reason = TrimText(fields[7])
    if sessionId == "" or profileName == "" or memberKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not DoesActiveSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      return
    end
    if not IsClaimedActorSenderMatch(sender, memberKey) then
      return
    end

    local pending = pendingProfileDeltaAcks[changeId]
    if type(pending) == "table" and type(pending.missing) == "table" then
      pending.missing[memberKey] = nil
      if not next(pending.missing) then
        pendingProfileDeltaAcks[changeId] = nil
      end
    end
    if type(SendProfileSnapshot) == "function" then
      QueueProfileSnapshotForMember(profileName, sessionId, memberKey, { mode = "LIVE", reason = reason ~= "" and reason or "delta_recovery" })
    end
    local ok, member = UpsertLootSessionMember(profileName, sessionId, memberKey, {
      lastSyncAt = time and time() or 0,
      suppressProfileTouch = true,
    })
    if ok and type(member) == "table" then
      member.lastProfileDeltaRecovery = math.max(tonumber(member.lastProfileDeltaRecovery) or 0, sequence)
    end
    RefreshEditor()
  end

  local function ActivatePreparedLootSessionFlow(opts)
    opts = type(opts) == "table" and opts or {}
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not profileName then
      Print("Prepare a loot session before starting it.")
      return false, "No prepared session."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      Print("Only the preparation host can start this session.")
      return false, "Only the host can start the session."
    end

    local blocked, blockedMessage = RejectCombatLockedAction("Start Session")
    if blocked then
      return false, blockedMessage
    end

    if IsLiveSession(activeSession) then
      Print("Loot session \"" .. tostring(profileName) .. "\" is already active.")
      return true, activeSession
    end
    if not IsPreparedSession(activeSession) then
      Print("Only a prepared loot session can be started.")
      return false, "Session is not prepared."
    end

    if opts.force ~= true then
      local warnings = {}
      local getQueueStatus = type(ResolveOptionalApiFunction) == "function" and ResolveOptionalApiFunction("LIDCOUNCIL_GetSessionCommQueueStatus") or nil
      local queueStatus = type(getQueueStatus) == "function" and getQueueStatus() or nil
      if type(queueStatus) == "table" and math.max(0, tonumber(queueStatus.pending) or 0) > 0 then
        warnings[#warnings + 1] = "The sync queue still has " .. tostring(math.max(0, tonumber(queueStatus.pending) or 0)) .. " pending addon message(s)."
      end
      local candidates = type(GetActiveProfileSyncCandidates) == "function" and GetActiveProfileSyncCandidates() or {}
      local _, syncWarningLines = BuildStartSessionSyncWarning(candidates)
      for _, line in ipairs(syncWarningLines) do
        warnings[#warnings + 1] = line
      end
      if #warnings > 0 then
        if type(StaticPopupDialogs) == "table" and not StaticPopupDialogs.LIDCOUNCIL_START_SESSION_WARNING then
          StaticPopupDialogs.LIDCOUNCIL_START_SESSION_WARNING = {
            text = "%s\n\nCancel and wait, or force start with the host profile as authoritative. Joined members that are already roll-ready can continue while the remaining shared history syncs in the background. Members still waiting on bootstrap may not receive the roll popup yet. Force Start does not queue another full profile push.",
            button1 = "Force Start",
            button2 = CANCEL,
            timeout = 0,
            whileDead = 1,
            hideOnEscape = 1,
            preferredIndex = 3,
            OnAccept = function()
              ActivatePreparedLootSessionFlow({ force = true })
            end,
          }
        end
        local warningText = table.concat(warnings, "\n")
        if type(StaticPopup_Show) == "function" then
          StaticPopup_Show("LIDCOUNCIL_START_SESSION_WARNING", warningText)
        else
          Print(warningText .. " Use Start Session again after more members are roll-ready, or force start only if you accept that some players may still miss the roll popup.")
        end
        return false, "START_CONFIRM_REQUIRED", warningText
      end
    end

    SetLocalAutoPassEnabled(false)
    UpsertLootSessionMember(profileName, activeSession.id, selfKey, {
      localAutoPassEnabled = false,
    })

    local session, err = ActivateLootSession(profileName, activeSession.id)
    if not session then
      Print(tostring(err or "Could not start the prepared loot session."))
      RefreshEditor()
      return false, err
    end

    local distribution = GetGroupDistribution()
    if distribution then
      SendComm(
        "BEGIN",
        distribution,
        nil,
        session.id,
        session.profileName,
        TrimText(select(1, GetLootProfileId(session.profileName)) or ""),
        session.host,
        session.activatedAt or (time and time() or 0),
        GetLootProfileMaster(session.profileName),
        GetCommProtocolMarker()
      )
    end

    SetProfileSyncRuntimeState(session.id, session.profileName, "session_started", "success",
      "Session started. The host profile is authoritative for this active session. No extra full profile push was queued automatically.", {
        sender = selfKey,
        refreshEditor = false,
      })
    Print("Started loot session \"" .. tostring(session.profileName) .. "\". The host profile is now authoritative.")
    RefreshEditor()
    return true, session
  end

  local function RequestActiveProfileSnapshotFlow(targetMemberKey, options)
    options = type(options) == "table" and options or {}
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not profileName then
      Print("No active loot session.")
      return false, "No active session."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      Print("Only the loot session host can pull or preview a shared profile.")
      return false, "Only the host can pull or preview a shared profile."
    end

    local previewOnly = string.upper(TrimText(options.mode)) == "PREVIEW" or options.previewOnly == true
    local actionLabel = previewOnly and "Preview Member Repair" or "Pull Member Repair"
    local blocked, blockedMessage = RejectCombatLockedAction(actionLabel)
    if blocked then
      return false, blockedMessage
    end

    local resolvedTarget = NormalizeCharacterKey(targetMemberKey)
    if resolvedTarget == "" then
      Print("Select a joined session member first.")
      return false, "No target selected."
    end
    if AreCharacterKeysSame(resolvedTarget, selfKey) then
      Print("The host already has the local shared profile copy.")
      return false, "Target must be another joined member."
    end
    if not IsJoinedSessionCharacter(activeSession, resolvedTarget) then
      Print("That character is not currently joined to the active loot session.")
      return false, "Target is not joined."
    end

    local requestedDomains, requestedSubdomains, requestMode
    if type(options.domains) == "table" or type(options.subdomains) == "table" then
      requestedDomains = type(options.domains) == "table" and options.domains or nil
      requestedSubdomains = type(options.subdomains) == "table" and options.subdomains or nil
      requestMode = type(requestedSubdomains) == "table" and #requestedSubdomains > 0 and "precise" or "targeted"
    else
      requestedDomains, requestedSubdomains, requestMode = BuildMemberRepairRequestDomains(resolvedTarget, previewOnly)
    end
    if not previewOnly and type(requestedDomains) == "table" and #requestedDomains == 0 then
      Print("The selected member does not currently have newer shared-profile data to pull.")
      return false, "No member-newer scope."
    end
    local requestedDomainCsv = type(requestedDomains) == "table" and table.concat(requestedDomains, ",") or ""
    local requestedSubdomainCsv = type(requestedSubdomains) == "table" and #requestedSubdomains > 0
      and table.concat(requestedSubdomains, ",")
      or ""
    if #requestedSubdomainCsv > 80 then
      requestedSubdomainCsv = ""
      if requestMode == "precise" then
        requestMode = "targeted"
      end
    end

    local patchManifestAttempted = false
    local patchManifestSent, patchManifestTransfers, patchManifestToken = false, 0, ""
    if requestMode == "precise"
      and type(requestedSubdomains) == "table"
      and #requestedSubdomains > 0
      and type(SendProfileSubdomainPatchManifest) == "function"
    then
      patchManifestAttempted = true
      patchManifestSent, patchManifestTransfers, patchManifestToken = SendProfileSubdomainPatchManifest(profileName, activeSession.id, resolvedTarget, requestedSubdomains)
      patchManifestTransfers = math.max(0, tonumber(patchManifestTransfers) or 0)
    end
    local requestedPatchManifestToken = patchManifestSent and TrimText(patchManifestToken) or ""
    if patchManifestAttempted and requestedPatchManifestToken == "" then
      requestedPatchManifestToken = "MISS"
    end

    local sent = SendComm(
      "PSYNC_REQ",
      "WHISPER",
      resolvedTarget,
      activeSession.id,
      profileName,
      TrimText(select(1, GetLootProfileId(profileName)) or ""),
      previewOnly and "PREVIEW" or "PULL",
      requestedDomainCsv,
      requestedSubdomainCsv,
      requestedPatchManifestToken
    )
    if sent then
      SetProfileSyncRuntimeState(activeSession.id, profileName, previewOnly and "preview_request_sent" or "request_sent", "warn",
        (previewOnly and "Requested a member shared profile change preview from " or "Requested a member shared profile pull from ")
          .. tostring(resolvedTarget)
          .. (requestMode == "precise" and " using the loaded precise checksum scope." or ".")
          .. (patchManifestSent and (" Nested host patch manifests were shared first (" .. tostring(patchManifestTransfers) .. " transfer" .. (patchManifestTransfers == 1 and "" or "s") .. ").") or ""), {
          sender = resolvedTarget,
          refreshEditor = false,
        })
      Print((previewOnly and "Requested a shared profile change preview from " or "Requested to pull shared profile data from ")
        .. tostring(resolvedTarget)
        .. (requestMode == "precise" and " using the loaded precise checksum scope." or ".")
        .. (patchManifestSent and " Host patch manifests were sent ahead of the request." or ""))
    else
      Print((previewOnly and "Could not request a shared profile change preview from " or "Could not request shared profile pull from ") .. tostring(resolvedTarget) .. ".")
    end
    RefreshEditor()
    return sent, resolvedTarget
  end

  local function RemoveActiveSessionMemberFlow(targetMemberKey)
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not profileName then
      Print("No active loot session.")
      return false, "No active session."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      Print("Only the loot session host can remove joined members.")
      return false, "Only the host can remove joined members."
    end

    local blocked, blockedMessage = RejectCombatLockedAction("Remove Joined Member")
    if blocked then
      return false, blockedMessage
    end

    local resolvedTarget = NormalizeCharacterKey(targetMemberKey)
    if resolvedTarget == "" then
      Print("Select a joined session member first.")
      return false, "No target selected."
    end
    if AreCharacterKeysSame(resolvedTarget, selfKey) then
      Print("The session host cannot remove themselves.")
      return false, "Cannot remove host."
    end

    local member = FindSessionMember(activeSession, resolvedTarget)
    if type(member) ~= "table" then
      Print("That character is not currently in the joined member list.")
      return false, "Session member not found."
    end

    local removedMember = {}
    for key, value in pairs(member) do
      removedMember[key] = value
    end
    removedMember.status = "REMOVED"
    removedMember.leftAt = time and time() or 0

    local ok, result = RemoveLootSessionMember(profileName, activeSession.id, resolvedTarget)
    if not ok then
      Print(tostring(result or "Could not remove joined member."))
      return false, result
    end

    BroadcastMember(profileName, activeSession.id, resolvedTarget, type(result) == "table" and result or removedMember)
    SendComm("STOP", "WHISPER", resolvedTarget, activeSession.id, profileName, activeSession.host, time and time() or 0)
    SetProfileSyncRuntimeState(activeSession.id, profileName, "member_removed", "info",
      tostring(resolvedTarget) .. " was removed from the joined member list.", {
        sender = selfKey,
        refreshEditor = false,
      })
    Print("Removed " .. tostring(resolvedTarget) .. " from the joined member list.")
    RefreshEditor()
    return true
  end

  local function StopLootSessionFlow()
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession then
      Print("No active loot session.")
      return false, "No active session."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      Print("Only the loot session host can stop the current session.")
      return false, "Only the host can stop the active session."
    end

    local ok, result = StopLootSession()
    if not ok then
      if result then
        Print(tostring(result))
      end
      RefreshEditor()
      return false, result
    end

    local cancelQueuedProfileSync = ResolveOptionalApiFunction("LIDCOUNCIL_CancelQueuedProfileSyncForSession")
    if type(cancelQueuedProfileSync) == "function" then
      cancelQueuedProfileSync(result.id)
    end
    local cancelProfileSyncBatch = ResolveOptionalApiFunction("LIDCOUNCIL_CancelProfileSnapshotBatchForSession")
    if type(cancelProfileSyncBatch) == "function" then
      cancelProfileSyncBatch(result.id)
    end

    local distribution = GetGroupDistribution()
    if distribution then
      SendComm("STOP", distribution, nil, result.id, profileName or result.profileName, result.host, result.endedAt or (time and time() or 0))
    end
    local clearRuntime = ResolveOptionalApiFunction("LIDCOUNCIL_ClearLiveLootRuntime")
    if type(clearRuntime) == "function" then
      clearRuntime()
    end
    SetProfileSyncRuntimeState(result.id, profileName or result.profileName or "", "session_stopped", "info",
      "Shared profile sync is idle because the active session ended.", {
        sender = selfKey,
        refreshEditor = false,
      })
    Print("Stopped loot session \"" .. tostring(profileName or result.profileName or "Unknown") .. "\".")
    RefreshEditor()
    return true, result
  end

  local function HandleGroupRosterChanged()
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or not profileName then
      return false, "No active session."
    end

    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if AreCharacterKeysSame(activeSession.host or "", selfKey) then
      local leftCount = 0
      local leftAt = time and time() or 0
      for memberKey, member in pairs(type(activeSession.members) == "table" and activeSession.members or {}) do
        local resolvedMemberKey = NormalizeCharacterKey(memberKey)
        local memberStatus = string.upper(TrimText(type(member) == "table" and member.status or "JOINED"))
        if resolvedMemberKey ~= "" and not AreCharacterKeysSame(resolvedMemberKey, selfKey) and memberStatus == "JOINED" and not IsCurrentGroupCharacter(resolvedMemberKey) then
          local ok, updatedMember = UpsertLootSessionMember(profileName, activeSession.id, resolvedMemberKey, {
            status = "LEFT",
            leftAt = leftAt,
            joinedAt = type(member) == "table" and member.joinedAt or nil,
          })
          if ok then
            BroadcastMember(profileName, activeSession.id, resolvedMemberKey, updatedMember or member)
            leftCount = leftCount + 1
          end
        end
      end
      if leftCount > 0 then
        RefreshEditor()
        return true, tostring(leftCount) .. " member(s) marked as left."
      end
      return false, "Local host session stays active."
    end

    local hostKey = NormalizeCharacterKey(activeSession.host or "")
    local shouldLeaveSession = GetGroupDistribution() == nil
    if not shouldLeaveSession and hostKey ~= "" then
      shouldLeaveSession = not IsCurrentGroupCharacter(hostKey)
    end
    if not shouldLeaveSession then
      return false, "Session host is still in the current group."
    end

    local endedAt = time and time() or 0
    local ok = FinishLootSession(profileName, activeSession.id, endedAt, "FINISHED")
    if ok then
      local clearRuntime = ResolveOptionalApiFunction("LIDCOUNCIL_ClearLiveLootRuntime")
      if type(clearRuntime) == "function" then
        clearRuntime()
      end
      SetProfileSyncRuntimeState(activeSession.id, profileName, "left_group", "info",
        "Local loot session ended because you left the host group.", {
          sender = hostKey,
          refreshEditor = false,
        })
      Print("Left the group. Local loot session \"" .. tostring(profileName) .. "\" was ended.")
      RefreshEditor()
      return true, activeSession
    end

    return false, "Could not end local session."
  end

  local function BroadcastAutoPassNotice(sessionId, profileName, memberKey, enabled, channel, target)
    local distribution = channel or GetGroupDistribution()
    if not distribution then
      return false
    end
    return SendComm(
      "APNOTICE",
      distribution,
      target,
      sessionId,
      profileName,
      memberKey,
      enabled and "1" or "0"
    )
  end

  local function NotifyLocalAutoPassChanged(enabled, suppressLocalPrint)
    local resolvedEnabled = enabled and true or false
    local activeSession, profileName = GetActiveLootSession()
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")

    if not suppressLocalPrint then
      if activeSession and profileName then
        Print("Local Auto Pass " .. (resolvedEnabled and "enabled" or "disabled") .. " for session \"" .. tostring(profileName) .. "\".")
      else
        Print("Local Auto Pass " .. (resolvedEnabled and "enabled" or "disabled") .. ".")
      end
    end

    if not activeSession or not profileName or selfKey == "" then
      RefreshEditor()
      return true, resolvedEnabled
    end

    local isHost = AreCharacterKeysSame(activeSession.host or "", selfKey)
    local isJoined = IsJoinedSessionCharacter(activeSession, selfKey)
    if isHost then
      local ok, member = UpsertLootSessionMember(profileName, activeSession.id, selfKey, {
        localAutoPassEnabled = resolvedEnabled,
        suppressProfileTouch = true,
      })
      if ok then
        local broadcastData = member or (type(activeSession.members) == "table" and activeSession.members[selfKey]) or {
          name = selfKey,
          status = "JOINED",
          joinedAt = time and time() or 0,
          localAutoPassEnabled = resolvedEnabled,
        }
        BroadcastMember(profileName, activeSession.id, selfKey, broadcastData)
        BroadcastAutoPassNotice(activeSession.id, profileName, selfKey, resolvedEnabled)
      end
    elseif isJoined then
      UpsertLootSessionMember(profileName, activeSession.id, selfKey, {
        localAutoPassEnabled = resolvedEnabled,
        suppressProfileTouch = true,
      })
      local commProfileName = TrimText(activeSession.remoteProfileName) ~= "" and activeSession.remoteProfileName or profileName
      SendComm(
        "LOCALAP",
        "WHISPER",
        activeSession.host,
        activeSession.id,
        commProfileName,
        selfKey,
        resolvedEnabled and "1" or "0"
      )
    end

    RefreshEditor()
    return true, resolvedEnabled
  end

  local function HandleStartInvite(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local profileId = TrimText(fields[4])
    local claimedHost = NormalizeCharacterKey(fields[5])
    local host = NormalizeSenderKey(sender)
    local startedAt = tonumber(fields[6]) or (time and time() or 0)
    local profileMaster = TrimText(fields[7])
    local protocolVersion = 1
    local rollFieldsStartIndex = 8
    local parsedProtocolVersion = GetInviteProtocolVersion(fields[8])
    if parsedProtocolVersion then
      protocolVersion = parsedProtocolVersion
      rollFieldsStartIndex = 9
    end
    local inviteStatus = string.upper(TrimText(fields[rollFieldsStartIndex]))
    if inviteStatus == "ACTIVE" or inviteStatus == "PREPARING" then
      rollFieldsStartIndex = rollFieldsStartIndex + 1
    else
      inviteStatus = "PREPARING"
    end
    if profileMaster == "" then
      profileMaster = host
    end
    local rollOptions = ParseRollOptionFields(fields, rollFieldsStartIndex)
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if sessionId == "" or profileName == "" or host == "" or AreCharacterKeysSame(host, selfKey) then
      return
    end
    if claimedHost ~= "" and not AreCharacterKeysSame(claimedHost, host) then
      return
    end
    if not IsCurrentGroupCharacter(host) then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if DoesActiveSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if activeSession then
      Print("Ignored session invite from " .. tostring(host) .. " because a different LidCouncil session is already open.")
      return
    end

    local invite = {
      sessionId = sessionId,
      profileName = profileName,
      profileId = profileId,
      host = host,
      profileMaster = profileMaster,
      startedAt = startedAt,
      rollOptions = rollOptions,
      protocolVersion = protocolVersion,
      status = inviteStatus,
    }
    if type(pendingJoinRequests[sessionId]) == "table" then
      pendingInvites[sessionId] = invite
      pendingJoinRequests[sessionId].invite = invite
      SendJoinRequest(sessionId, true)
      return
    end
    pendingInvites[sessionId] = invite
    ShowSessionInvite(invite)
  end

  local function HandleJoinAck(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local profileId = TrimText(fields[4])
    local claimedHost = NormalizeCharacterKey(fields[5])
    local host = NormalizeSenderKey(sender)
    local profileMaster = TrimText(fields[6])
    local startedAt = tonumber(fields[7]) or (time and time() or 0)
    local ackStatus = string.upper(TrimText(fields[8]))
    local activatedAt = tonumber(fields[9])
    local protocolVersion = GetInviteProtocolVersion(fields[10]) or 1
    local ackMemberKey = NormalizeCharacterKey(fields[11])
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if sessionId == "" or profileName == "" or host == "" or selfKey == "" then
      return
    end
    if claimedHost ~= "" and not AreCharacterKeysSame(claimedHost, host) then
      return
    end
    if ackMemberKey ~= "" and not AreCharacterKeysSame(ackMemberKey, selfKey) then
      return
    end
    if protocolVersion ~= COMM_PROTOCOL_VERSION then
      Print("Ignored join confirmation for \"" .. tostring(profileName) .. "\" because the host is using an incompatible LidCouncil build.")
      return
    end
    if profileMaster == "" then
      profileMaster = host
    end

    local pendingJoin = pendingJoinRequests[sessionId]
    local invite = type(pendingJoin) == "table" and type(pendingJoin.invite) == "table" and pendingJoin.invite or pendingInvites[sessionId]
    if type(invite) ~= "table" then
      return
    end
    if not AreCharacterKeysSame(invite.host, host) or TrimText(invite.profileName) ~= profileName then
      return
    end

    pendingJoinRequests[sessionId] = nil
    pendingInvites[sessionId] = nil
    SetLocalAutoPassEnabled(true)

    local localProfileName = ResolveLocalSharedProfileName(profileName, profileId, profileMaster)
    local existingSharedProfileName = TrimText(profileId ~= "" and FindLootProfileNameById(profileId) or "")
    if ackStatus ~= "ACTIVE" then
      ackStatus = "PREPARING"
    end
    local session, joinedProfileName = JoinLootSession(localProfileName, {
      id = sessionId,
      profileName = localProfileName,
      remoteProfileName = profileName,
      profileId = profileId,
      host = host,
      profileMaster = profileMaster,
      status = ackStatus,
      startedAt = startedAt,
      activatedAt = activatedAt,
      rollOptions = invite.rollOptions,
      sharedProfileReady = existingSharedProfileName ~= "" or TrimText(profileId) == "",
    }, "JACK")
    if not session then
      Print(tostring(joinedProfileName or "Could not join the confirmed incoming loot session."))
      return
    end
    if type(RememberSharedReplicaPlaceholder) == "function" then
      RememberSharedReplicaPlaceholder(joinedProfileName, profileName, profileId, profileMaster)
    end

    local payloadDetails = type(pendingJoin) == "table" and type(pendingJoin.payloadDetails) == "table" and pendingJoin.payloadDetails or GetMemberPayloadDetails(nil, true)
    SyncLootProfilePermissionState(joinedProfileName, profileMaster, selfKey, "RAIDER")
    UpsertLootSessionMember(joinedProfileName, sessionId, selfKey, {
      status = "JOINED",
      joinedAt = type(pendingJoin) == "table" and pendingJoin.joinedAt or (time and time() or 0),
      profileMaster = profileMaster,
      role = "RAIDER",
      addonVersion = payloadDetails.addonVersion,
      clientVersion = payloadDetails.clientVersion,
      className = payloadDetails.className,
      classFile = payloadDetails.classFile,
      specName = payloadDetails.specName,
      specIcon = payloadDetails.specIcon,
      localAutoPassEnabled = payloadDetails.localAutoPassEnabled,
      suppressProfileTouch = true,
    })
    AddCharacterToList(selfKey)
    if session.sharedProfileReady ~= false and type(SendLocalProfileStateToHost) == "function" then
      SendLocalProfileStateToHost(sessionId, profileName, joinedProfileName)
    end

    if session.sharedProfileReady == false then
      session.__sharedProfilePendingNoticeShown = nil
      Print(
        "Host confirmed your join for \"" .. tostring(profileName)
        .. "\". Waiting for the host bootstrap copy before LidCouncil roll choices become available."
        .. " Remaining shared history can keep syncing in the background."
      )
    else
      Print("Host confirmed your join for \"" .. tostring(profileName) .. "\".")
    end
    RefreshEditor()
  end

  local function HandleBegin(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local profileId = TrimText(fields[4])
    local claimedHost = NormalizeCharacterKey(fields[5])
    local host = NormalizeSenderKey(sender)
    local activatedAt = tonumber(fields[6]) or (time and time() or 0)
    local profileMaster = TrimText(fields[7])
    local protocolVersion = GetInviteProtocolVersion(fields[8]) or 1
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if sessionId == "" or profileName == "" or host == "" or AreCharacterKeysSame(host, selfKey) then
      return
    end
    if claimedHost ~= "" and not AreCharacterKeysSame(claimedHost, host) then
      return
    end
    if not IsCurrentGroupCharacter(host) then
      return
    end
    if protocolVersion ~= COMM_PROTOCOL_VERSION then
      return
    end
    if profileMaster == "" then
      profileMaster = host
    end

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

    if IsLiveSession(activeSession) then
      RefreshEditor()
      return
    end

    local localProfileName = TrimText(activeProfileName)
    if localProfileName == "" then
      localProfileName = ResolveLocalSharedProfileName(profileName, profileId, profileMaster)
    end

    local session, err = JoinLootSession(localProfileName, {
      id = sessionId,
      profileName = localProfileName,
      remoteProfileName = profileName,
      profileId = profileId,
      host = host,
      profileMaster = profileMaster,
      status = "ACTIVE",
      startedAt = activeSession.startedAt,
      activatedAt = activatedAt,
      rollOptions = activeSession.rollOptions,
      sharedProfileReady = activeSession.sharedProfileReady ~= false,
    }, "BEGIN")
    if not session then
      Print(tostring(err or "Could not start the incoming prepared loot session."))
      return
    end

    SetProfileSyncRuntimeState(sessionId, localProfileName, "session_started", "success",
      "Session started. The host profile is authoritative for this active session.", {
        sender = host,
        refreshEditor = false,
      })
    Print("Loot session \"" .. tostring(profileName) .. "\" was started by " .. tostring(host) .. ".")
    RefreshEditor()
  end

  local function HandleJoin(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local memberKey = NormalizeCharacterKey(fields[4] ~= "" and fields[4] or sender)
    local joinedAt = tonumber(fields[5]) or (time and time() or 0)
    local addonVersion = TrimText(fields[6])
    local clientVersion = TrimText(fields[7])
    local className = TrimText(fields[8])
    local classFile = TrimText(fields[9])
    local specName = TrimText(fields[10])
    local specIcon = TrimText(fields[11])
    local localAutoPassEnabled = NormalizeEnabledFlag(fields[12], true)
    local claimedProfileId = TrimText(fields[13])
    local remoteSettingsRevision = math.max(0, tonumber(fields[14]) or 0)
    local remotePermissionsRevision = math.max(0, tonumber(fields[15]) or 0)
    local remoteOperationalRevision = math.max(0, tonumber(fields[16]) or 0)
    local memberProtocolVersion = GetInviteProtocolVersion(fields[19])
    local remoteProfileUpdatedAt
    local hadLocalSharedProfile
    if memberProtocolVersion then
      remoteProfileUpdatedAt = math.max(0, tonumber(fields[17]) or 0)
      hadLocalSharedProfile = NormalizeEnabledFlag(fields[18], false) and true or false
    else
      remoteProfileUpdatedAt = 0
      hadLocalSharedProfile = NormalizeEnabledFlag(fields[17], false) and true or false
      memberProtocolVersion = GetInviteProtocolVersion(fields[18]) or 1
    end
    local remoteSettingsChecksum = memberProtocolVersion >= 2 and TrimText(fields[20]) or ""
    local remotePermissionsChecksum = memberProtocolVersion >= 2 and TrimText(fields[21]) or ""
    local remoteOperationalChecksum = memberProtocolVersion >= 2 and TrimText(fields[22]) or ""
    local remoteLootRevision = memberProtocolVersion >= 2 and math.max(0, tonumber(fields[23]) or remoteOperationalRevision) or remoteOperationalRevision
    local remoteSessionRevision = memberProtocolVersion >= 2 and math.max(0, tonumber(fields[24]) or remoteOperationalRevision) or remoteOperationalRevision
    local remoteLootChecksum = memberProtocolVersion >= 2 and TrimText(fields[25]) or ""
    if remoteLootChecksum == "" then
      remoteLootChecksum = remoteOperationalChecksum
    end
    local remoteSessionChecksum = memberProtocolVersion >= 2 and TrimText(fields[26]) or ""
    if remoteSessionChecksum == "" then
      remoteSessionChecksum = remoteOperationalChecksum
    end
    if sessionId == "" or profileName == "" or memberKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not DoesActiveSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      Print("Ignored JOIN from " .. tostring(memberKey) .. ": session mismatch.")
      return
    end
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      return
    end
    if not IsClaimedActorSenderMatch(sender, memberKey) then
      Print("Ignored JOIN from " .. tostring(sender) .. ": sender does not match claimed member " .. tostring(memberKey) .. ".")
      return
    end
    if not IsCurrentGroupCharacter(memberKey) then
      Print("Ignored JOIN from " .. tostring(memberKey) .. ": character is not in the current group.")
      return
    end
    if AreCharacterKeysSame(memberKey, selfKey) then
      return
    end
    if memberProtocolVersion ~= COMM_PROTOCOL_VERSION then
      Print(memberKey .. " could not join \"" .. tostring(profileName) .. "\" because their LidCouncil build is incompatible with the active session. Update both clients to the same build and try again.")
      SendComm("STOP", "WHISPER", memberKey, sessionId, profileName, activeSession.host, time and time() or 0)
      return
    end
    ExtendProfileSnapshotJoinGrace(sessionId, profileName, JOIN_QUIET_GRACE_SECONDS, "join:" .. tostring(memberKey))
    if IsJoinedSessionCharacter(activeSession, memberKey) then
      local existingMember = FindSessionMember(activeSession, memberKey)
      SendJoinAck(activeSession, profileName, memberKey)
      BroadcastMember(profileName, sessionId, memberKey, existingMember or {
        name = memberKey,
        status = "JOINED",
        joinedAt = joinedAt,
      })
      SendMemberSnapshot(activeSession, profileName, memberKey)
      QueueProfileSnapshotForMember(profileName, sessionId, memberKey, {
        mode = "LIVE",
        reason = "duplicate_join_recovery",
      })
      Print("Recovered duplicate JOIN from " .. tostring(memberKey) .. ": resent member table and queued profile sync.")
      return
    end

    UpsertLootSessionMember(profileName, sessionId, memberKey, {
      status = "JOINED",
      joinedAt = joinedAt,
      addonVersion = addonVersion,
      clientVersion = clientVersion,
      className = className,
      classFile = classFile,
      specName = specName,
      specIcon = specIcon,
      localAutoPassEnabled = localAutoPassEnabled,
      sharedProfileId = claimedProfileId,
      settingsRevision = remoteSettingsRevision,
      permissionsRevision = remotePermissionsRevision,
      operationalRevision = remoteOperationalRevision,
      lootRevision = remoteLootRevision,
      sessionRevision = remoteSessionRevision,
      settingsChecksum = remoteSettingsChecksum,
      permissionsChecksum = remotePermissionsChecksum,
      operationalChecksum = remoteOperationalChecksum,
      lootChecksum = remoteLootChecksum,
      sessionChecksum = remoteSessionChecksum,
      profileUpdatedAt = remoteProfileUpdatedAt,
    })
    AddCharacterToList(memberKey)
    local _, assignedRole = EnsureLootProfileMemberRole(profileName, memberKey, "RAIDER")

    local localProfileId = TrimText(select(1, GetLootProfileId(profileName)) or "")
    local localRevisionSummary = NormalizeRevisionSummary(
      GetLootProfileRevisionSummary(profileName),
      profileName,
      localProfileId
    )
    local remoteRevisionSummary = NormalizeRevisionSummary({
      profileName = profileName,
      profileId = claimedProfileId,
      settings = remoteSettingsRevision,
      permissions = remotePermissionsRevision,
      operational = remoteOperationalRevision,
      loot = remoteLootRevision,
      session = remoteSessionRevision,
      settingsChecksum = remoteSettingsChecksum,
      permissionsChecksum = remotePermissionsChecksum,
      operationalChecksum = remoteOperationalChecksum,
      lootChecksum = remoteLootChecksum,
      sessionChecksum = remoteSessionChecksum,
      updatedAt = remoteProfileUpdatedAt,
    }, profileName, claimedProfileId)
    local remoteNewerDomains = {}
    local localNewerDomains = {}
    local shouldSendSnapshot = true
    local snapshotDomains = nil

    if localProfileId ~= "" and claimedProfileId ~= "" and string.lower(localProfileId) == string.lower(claimedProfileId) then
      remoteNewerDomains, localNewerDomains = CompareProfileRevisionSummaries(localRevisionSummary, remoteRevisionSummary)
      if hadLocalSharedProfile then
        snapshotDomains = #localNewerDomains > 0 and CloneComparedDomains(localNewerDomains) or nil
        shouldSendSnapshot = #localNewerDomains > 0 and #remoteNewerDomains == 0
      else
        shouldSendSnapshot = true
      end

      if #remoteNewerDomains > 0 and #localNewerDomains > 0 then
        SetProfileSyncRuntimeState(sessionId, profileName, "diverged_remote_member", "warn",
          tostring(memberKey) .. " joined with diverged shared profile data.", {
            sender = memberKey,
            remoteDomains = remoteNewerDomains,
            localDomains = localNewerDomains,
            refreshEditor = false,
          })
        Print(
          "Divergent shared profile data detected for \"" .. tostring(profileName) .. "\" from " .. tostring(memberKey)
          .. ". Remote newer: " .. FormatProfileRevisionDomains(remoteNewerDomains)
          .. ". Local newer: " .. FormatProfileRevisionDomains(localNewerDomains)
          .. ". Automatic sync was skipped."
        )
      elseif #remoteNewerDomains > 0 then
        SetProfileSyncRuntimeState(sessionId, profileName, "member_newer", "warn",
          tostring(memberKey) .. " joined with newer shared profile data.", {
            sender = memberKey,
            remoteDomains = remoteNewerDomains,
            refreshEditor = false,
          })
        Print(
          "Newer shared profile data was found from " .. tostring(memberKey)
          .. " for \"" .. tostring(profileName) .. "\" (" .. tostring(assignedRole or "RAIDER") .. "). Newer domains: "
          .. FormatProfileRevisionDomains(remoteNewerDomains)
          .. ". Your current host copy was kept for now."
        )
      end
    end

    local member = activeSession.members and activeSession.members[memberKey] or {
      name = memberKey,
      status = "JOINED",
      joinedAt = joinedAt,
    }
    member.profileMaster = GetLootProfileMaster(profileName)
    member.role = assignedRole
    SendJoinAck(activeSession, profileName, memberKey)
    BroadcastMember(profileName, sessionId, memberKey, member)
    SendMemberSnapshot(activeSession, profileName, memberKey)
    if IsLiveSession(activeSession) then
      SendComm(
        "BEGIN",
        "WHISPER",
        memberKey,
        sessionId,
        profileName,
        localProfileId,
        activeSession.host,
        activeSession.activatedAt or (time and time() or 0),
        GetLootProfileMaster(profileName),
        GetCommProtocolMarker()
      )
    end
    if shouldSendSnapshot then
      if hadLocalSharedProfile then
        local preparedSnapshot, prepareError = PrepareProfileSnapshotTransfer(profileName, {
          domains = snapshotDomains,
        })
        if preparedSnapshot then
          QueueProfileSnapshotForMember(profileName, sessionId, memberKey, {
            mode = "LIVE",
            reason = "join_repair",
            domains = snapshotDomains,
            preparedSnapshot = preparedSnapshot,
          })
          SetProfileSyncRuntimeState(sessionId, profileName, "host_snapshot_sent", "success",
            tostring(memberKey) .. " joined with an older shared copy. Host repair sent.", {
              sender = memberKey,
              localDomains = localNewerDomains,
              refreshEditor = false,
            })
          Print(
            "Queued the host shared profile repair for " .. tostring(memberKey)
            .. " because their copy was older in: " .. FormatProfileRevisionDomains(localNewerDomains) .. "."
          )
        elseif prepareError then
          Print(tostring(prepareError))
        end
      else
        local bootstrapQueued, backgroundQueued, queueError = QueueMissingMemberBootstrapSync(profileName, sessionId, memberKey)
        if bootstrapQueued then
          SetProfileSyncRuntimeState(sessionId, profileName, "missing_member_copy", "success",
            tostring(memberKey) .. " joined without a local shared copy. Sent the smaller roll-ready bootstrap first.", {
              sender = memberKey,
              refreshEditor = false,
          })
          if backgroundQueued then
            Print(
              "Queued the initial shared-profile bootstrap for " .. tostring(memberKey)
              .. " so roll choices can unlock sooner. Loot and session history continue syncing in the background."
            )
          else
            Print(
              "Queued the initial shared-profile bootstrap for " .. tostring(memberKey)
              .. ". Roll choices can unlock sooner once that bootstrap arrives."
            )
            if queueError then
              Print("Background loot/session follow-up for " .. tostring(memberKey) .. " could not be queued: " .. tostring(queueError))
            end
          end
        elseif queueError then
          Print(tostring(queueError))
        end
      end
    end
    if hadLocalSharedProfile and (#remoteNewerDomains > 0 or #localNewerDomains > 0) then
      QueueAutoDetailedComparison(memberKey, "join_mismatch")
    end
    Print(memberKey .. " joined loot session \"" .. profileName .. "\".")
    RefreshEditor()
  end

  local function HandleMember(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local memberKey = NormalizeCharacterKey(fields[4])
    local status = TrimText(fields[5])
    local joinedAt = tonumber(fields[6]) or (time and time() or 0)
    local addonVersion = TrimText(fields[7])
    local clientVersion = TrimText(fields[8])
    local className = TrimText(fields[9])
    local classFile = TrimText(fields[10])
    local specName = TrimText(fields[11])
    local specIcon = TrimText(fields[12])
    local localAutoPassEnabled = NormalizeEnabledFlag(fields[13], true)
    local profileMaster = TrimText(fields[14])
    local role = TrimText(fields[15])
    local sharedProfileId = TrimText(fields[16])
    local settingsRevision = tonumber(fields[17]) or 0
    local permissionsRevision = tonumber(fields[18]) or 0
    local operationalRevision = tonumber(fields[19]) or 0
    local profileUpdatedAt = tonumber(fields[20]) or 0
    local settingsChecksum = TrimText(fields[21])
    local permissionsChecksum = TrimText(fields[22])
    local operationalChecksum = TrimText(fields[23])
    local leftAt = tonumber(fields[24]) or nil
    local lootRevision = math.max(0, tonumber(fields[25]) or operationalRevision)
    local sessionRevision = math.max(0, tonumber(fields[26]) or operationalRevision)
    local lootChecksum = TrimText(fields[27])
    if lootChecksum == "" then
      lootChecksum = operationalChecksum
    end
    local sessionChecksum = TrimText(fields[28])
    if sessionChecksum == "" then
      sessionChecksum = operationalChecksum
    end
    if sessionId == "" or profileName == "" or memberKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if not DoesActiveSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsActiveSessionHostSender(activeSession, sender) then
      return
    end
    if not IsCurrentGroupCharacter(NormalizeSenderKey(sender)) then
      return
    end

    local localProfileName = FirstNonEmptyText(activeProfileName, activeSession.profileName, activeSession.remoteProfileName, profileName)
    if string.upper(status) == "REMOVED" then
      UpsertLootSessionMember(localProfileName, sessionId, memberKey, {
        status = "REMOVED",
        joinedAt = joinedAt,
        leftAt = leftAt or (time and time() or 0),
        profileMaster = profileMaster,
        role = role,
        sharedProfileId = sharedProfileId,
        settingsRevision = settingsRevision,
        permissionsRevision = permissionsRevision,
        operationalRevision = operationalRevision,
        lootRevision = lootRevision,
        sessionRevision = sessionRevision,
        settingsChecksum = settingsChecksum,
        permissionsChecksum = permissionsChecksum,
        operationalChecksum = operationalChecksum,
        lootChecksum = lootChecksum,
        sessionChecksum = sessionChecksum,
        profileUpdatedAt = profileUpdatedAt,
        addonVersion = addonVersion,
        clientVersion = clientVersion,
        className = className,
        classFile = classFile,
        specName = specName,
        specIcon = specIcon,
        localAutoPassEnabled = localAutoPassEnabled,
      })
      RefreshEditor()
      return
    end

    UpsertLootSessionMember(localProfileName, sessionId, memberKey, {
      status = status ~= "" and status or "JOINED",
      joinedAt = joinedAt,
      profileMaster = profileMaster,
      role = role,
      sharedProfileId = sharedProfileId,
      settingsRevision = settingsRevision,
      permissionsRevision = permissionsRevision,
      operationalRevision = operationalRevision,
      lootRevision = lootRevision,
      sessionRevision = sessionRevision,
      settingsChecksum = settingsChecksum,
      permissionsChecksum = permissionsChecksum,
      operationalChecksum = operationalChecksum,
      lootChecksum = lootChecksum,
      sessionChecksum = sessionChecksum,
      profileUpdatedAt = profileUpdatedAt,
      leftAt = leftAt,
      addonVersion = addonVersion,
      clientVersion = clientVersion,
      className = className,
      classFile = classFile,
      specName = specName,
      specIcon = specIcon,
      localAutoPassEnabled = localAutoPassEnabled,
    })
    AddCharacterToList(memberKey)
    RefreshEditor()
  end

  local function HandleProfileState(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local memberKey = NormalizeCharacterKey(fields[4] ~= "" and fields[4] or sender)
    local sharedProfileId = TrimText(fields[5])
    local settingsRevision = tonumber(fields[6]) or 0
    local permissionsRevision = tonumber(fields[7]) or 0
    local operationalRevision = tonumber(fields[8]) or 0
    local profileUpdatedAt = tonumber(fields[9]) or 0
    local settingsChecksum = TrimText(fields[10])
    local permissionsChecksum = TrimText(fields[11])
    local operationalChecksum = TrimText(fields[12])
    local lootRevision = math.max(0, tonumber(fields[13]) or operationalRevision)
    local sessionRevision = math.max(0, tonumber(fields[14]) or operationalRevision)
    local lootChecksum = TrimText(fields[15])
    if lootChecksum == "" then
      lootChecksum = operationalChecksum
    end
    local sessionChecksum = TrimText(fields[16])
    if sessionChecksum == "" then
      sessionChecksum = operationalChecksum
    end
    if sessionId == "" or profileName == "" or memberKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not DoesActiveSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      return
    end
    if not IsClaimedActorSenderMatch(sender, memberKey) then
      return
    end
    if not IsJoinedSessionCharacter(activeSession, memberKey) then
      return
    end

    local ok, member = UpsertLootSessionMember(profileName, sessionId, memberKey, {
      sharedProfileId = sharedProfileId,
      settingsRevision = settingsRevision,
      permissionsRevision = permissionsRevision,
      operationalRevision = operationalRevision,
      lootRevision = lootRevision,
      sessionRevision = sessionRevision,
      settingsChecksum = settingsChecksum,
      permissionsChecksum = permissionsChecksum,
      operationalChecksum = operationalChecksum,
      lootChecksum = lootChecksum,
      sessionChecksum = sessionChecksum,
      profileUpdatedAt = profileUpdatedAt,
      lastSyncAt = time and time() or 0,
      suppressProfileTouch = true,
    })
    if ok then
      BroadcastMember(profileName, sessionId, memberKey, member or (activeSession.members and activeSession.members[memberKey]) or {})
      QueueAutoDetailedComparison(memberKey, "profile_state")
      RefreshEditor()
    end
  end

  local function HandleLocalAutoPass(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local memberKey = NormalizeCharacterKey(fields[4] ~= "" and fields[4] or sender)
    local enabled = NormalizeEnabledFlag(fields[5], true)
    if sessionId == "" or profileName == "" or memberKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not DoesActiveSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      return
    end
    if not IsClaimedActorSenderMatch(sender, memberKey) then
      return
    end
    if not IsCurrentGroupCharacter(memberKey) then
      return
    end
    if not IsJoinedSessionCharacter(activeSession, memberKey) then
      return
    end

    local ok, member = UpsertLootSessionMember(profileName, sessionId, memberKey, {
      localAutoPassEnabled = enabled,
      suppressProfileTouch = true,
    })
    if not ok then
      return
    end

    local broadcastData = member or (type(activeSession.members) == "table" and activeSession.members[memberKey]) or {
      name = memberKey,
      status = "JOINED",
      joinedAt = time and time() or 0,
      localAutoPassEnabled = enabled,
    }
    BroadcastMember(profileName, sessionId, memberKey, broadcastData)
    BroadcastAutoPassNotice(sessionId, profileName, memberKey, enabled)
    Print(memberKey .. " set local Auto Pass " .. (enabled and "|cff4adf6bON|r" or "|cffff5a5aOFF|r") .. ".")
    RefreshEditor()
  end

  local function HandleAutoPassNotice(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local memberKey = NormalizeCharacterKey(fields[4])
    local enabled = NormalizeEnabledFlag(fields[5], true)
    if sessionId == "" or profileName == "" or memberKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not DoesActiveSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not IsActiveSessionHostSender(activeSession, sender) then
      return
    end
    if not IsCurrentGroupCharacter(NormalizeSenderKey(sender)) then
      return
    end
    if AreCharacterKeysSame(NormalizeSenderKey(sender), selfKey) then
      return
    end
    if AreCharacterKeysSame(memberKey, selfKey) then
      return
    end

    Print(memberKey .. " set local Auto Pass " .. (enabled and "|cff4adf6bON|r" or "|cffff5a5aOFF|r") .. ".")
  end

  local function BroadcastActiveSessionRoleUpdate(profileName, memberKey)
    local activeSession, activeProfileName = GetActiveLootSession()
    if not activeSession or tostring(activeProfileName or "") ~= tostring(profileName or "") then
      return false, "No matching active session."
    end

    local resolvedMemberKey = NormalizeCharacterKey(memberKey)
    if resolvedMemberKey == "" then
      return false, "Character-Realm is required."
    end

    local member = FindSessionMember(activeSession, resolvedMemberKey)
    if type(member) ~= "table" then
      return false, "Session member not found."
    end

    member.profileMaster = GetLootProfileMaster(profileName)
    member.role = GetLootProfileRole(profileName, resolvedMemberKey)
    return BroadcastMember(profileName, activeSession.id, resolvedMemberKey, member)
  end

  local function HandleDecline(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local memberKey = NormalizeCharacterKey(fields[4] ~= "" and fields[4] or sender)
    if sessionId == "" or profileName == "" or memberKey == "" then
      return
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    if not DoesActiveSessionMatch(activeSession, activeProfileName, sessionId, profileName) then
      return
    end
    if not AreCharacterKeysSame(activeSession.host or "", selfKey) then
      return
    end
    if not IsClaimedActorSenderMatch(sender, memberKey) then
      return
    end
    if not IsCurrentGroupCharacter(memberKey) then
      return
    end

    Print(memberKey .. " declined the loot session \"" .. profileName .. "\".")
  end

  local function HandleStop(fields, sender)
    local sessionId = TrimText(fields[2])
    local profileName = TrimText(fields[3])
    local host = NormalizeCharacterKey(fields[4])
    local endedAt = tonumber(fields[5]) or (time and time() or 0)
    if sessionId == "" or profileName == "" then
      return
    end
    if host == "" or not IsClaimedActorSenderMatch(sender, host) then
      return
    end
    if not IsCurrentGroupCharacter(host) then
      return
    end

    local pendingInvite = pendingInvites[sessionId]
    if type(pendingInvite) == "table" and TrimText(pendingInvite.profileName) == profileName and AreCharacterKeysSame(pendingInvite.host, host) then
      pendingInvites[sessionId] = nil
    end
    local pendingJoin = pendingJoinRequests[sessionId]
    if type(pendingJoin) == "table" and type(pendingJoin.invite) == "table"
        and TrimText(pendingJoin.invite.profileName) == profileName
        and AreCharacterKeysSame(pendingJoin.invite.host, host) then
      pendingJoinRequests[sessionId] = nil
    end

    local activeSession, activeProfileName = GetActiveLootSession()
    if type(activeSession) ~= "table" or TrimText(activeSession.id) ~= sessionId then
      RefreshEditor()
      return
    end
    if not IsActiveSessionHostSender(activeSession, sender) then
      return
    end

    local localProfileName = TrimText(activeProfileName) ~= "" and activeProfileName or profileName
    local stopped = FinishLootSession(localProfileName, sessionId, endedAt, "FINISHED")
    if not stopped then
      RefreshEditor()
      return
    end
    SetProfileSyncRuntimeState(sessionId, profileName, "session_stopped", "info",
      "Shared profile sync is idle because the active session ended.", {
        sender = host ~= "" and host or NormalizeSenderKey(sender),
        refreshEditor = false,
      })
    Print("Loot session \"" .. profileName .. "\" ended by " .. ((host ~= "" and host) or NormalizeSenderKey(sender) or "Unknown") .. ".")
    RefreshEditor()
  end

  return {
    EnsureSessionPopup = EnsureSessionPopup,
    HasJoinedActiveLootSession = HasJoinedActiveLootSession,
    StartLootSessionFlow = StartLootSessionFlow,
    ActivatePreparedLootSessionFlow = ActivatePreparedLootSessionFlow,
    SendActiveSessionInviteFlow = SendActiveSessionInviteFlow,
    PushActiveProfileSnapshotFlow = PushActiveProfileSnapshotFlow,
    BroadcastActiveProfileSnapshotFlow = BroadcastActiveProfileSnapshotFlow,
    BroadcastActiveProfileDeltaFlow = BroadcastActiveProfileDeltaFlow,
    QueueActiveProfileCheckpointFlow = QueueActiveProfileCheckpointFlow,
    BroadcastMember = BroadcastMember,
    RequestActiveProfileSubchecksumFlow = RequestActiveProfileSubchecksumFlow,
    RequestActiveProfileSnapshotFlow = RequestActiveProfileSnapshotFlow,
    StopLootSessionFlow = StopLootSessionFlow,
    RemoveActiveSessionMemberFlow = RemoveActiveSessionMemberFlow,
    HandleGroupRosterChanged = HandleGroupRosterChanged,
    NotifyLocalAutoPassChanged = NotifyLocalAutoPassChanged,
    BroadcastActiveSessionRoleUpdate = BroadcastActiveSessionRoleUpdate,
    HandleStartInvite = HandleStartInvite,
    HandleBegin = HandleBegin,
    HandleJoin = HandleJoin,
    HandleJoinAck = HandleJoinAck,
    HandleMember = HandleMember,
    HandleLocalAutoPass = HandleLocalAutoPass,
    HandleAutoPassNotice = HandleAutoPassNotice,
    HandleDecline = HandleDecline,
    HandleProfileState = HandleProfileState,
    HandleProfileDeltaRequest = HandleProfileDeltaRequest,
    HandleProfileDelta = HandleProfileDelta,
    HandleProfileDeltaAck = HandleProfileDeltaAck,
    HandleProfileDeltaNack = HandleProfileDeltaNack,
    HandleStop = HandleStop,
  }
end
