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

  local RootDB = deps.RootDB
  local DeepCopy = deps.DeepCopy
  local GetCharacterKey = deps.GetCharacterKey
  local GetLootProfile = deps.GetLootProfile
  local TrimText = deps.TrimText
  local ExtractItemID = deps.ExtractItemID
  local NormalizeSelectionNote = deps.NormalizeSelectionNote
  local NormalizeCharacterKey = deps.NormalizeCharacterKey
  local NextLiveBoardId = deps.NextLiveBoardId
  local TouchLootProfileDomain = deps.TouchLootProfileDomain
  local runtime = deps.runtime
  local uiState = deps.uiState
  local ResolveSelfKey = deps.ResolveSelfKey
  local PrimeSequenceItemKey = deps.PrimeSequenceItemKey
  local liveBoardHistorySummaryCache = {}

  local function IsRealSimulationItemKey(itemKey)
    local resolvedKey = TrimText(itemKey)
    return resolvedKey ~= "" and string.sub(resolvedKey, 1, 8) == "TESTSIM-"
  end

  local function IsRealSimulationRuntimeSnapshot(snapshot)
    if type(snapshot) ~= "table" or type(snapshot.itemOrder) ~= "table" then
      return false
    end
    local hasItems = false
    for _, itemKey in ipairs(snapshot.itemOrder) do
      local resolvedKey = TrimText(itemKey)
      if resolvedKey ~= "" then
        hasItems = true
        if not IsRealSimulationItemKey(resolvedKey) then
          return false
        end
      end
    end
    return hasItems
  end

  local function EnsureRuntimeBoardContext(session, profileName)
    local resolvedProfileName = TrimText(profileName or runtime.profileName)
    local sessionId = TrimText(type(session) == "table" and session.id or runtime.sessionId)
    if TrimText(runtime.boardId) == "" then
      runtime.boardId = sessionId ~= "" and ("live-" .. sessionId) or NextLiveBoardId()
    end
    runtime.historyProfileName = resolvedProfileName
    return runtime.boardId, runtime.historyProfileName
  end

  local function EnsurePreviewBoardContext(preview)
    if type(preview) ~= "table" then
      return "", ""
    end
    if TrimText(preview.boardId) == "" then
      preview.boardId = NextLiveBoardId()
    end
    if TrimText(preview.historyProfileName) == "" then
      preview.historyProfileName = TrimText(preview.sourceProfileName ~= "" and preview.sourceProfileName or preview.profileName)
    end
    if not tonumber(preview.createdAt) then
      preview.createdAt = time and time() or 0
    end
    return preview.boardId, preview.historyProfileName
  end

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

  local function 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 BuildLiveBoardCheckpointSubdomain(snapshot)
    snapshot = type(snapshot) == "table" and snapshot or {}
    local boardId = TrimText(snapshot.boardId)
    if boardId ~= "" then
      return BuildDynamicCheckpointSubdomainKey("slb", "board:" .. boardId)
    end
    local sessionId = TrimText(snapshot.sessionId)
    if sessionId ~= "" then
      return BuildDynamicCheckpointSubdomainKey("slb", "session:" .. sessionId)
    end
    local updatedAt = math.max(0, tonumber(snapshot.updatedAt) or 0)
    local createdAt = math.max(0, tonumber(snapshot.createdAt) or 0)
    if updatedAt <= 0 and createdAt <= 0 then
      return ""
    end
    return BuildDynamicCheckpointSubdomainKey("slb", "stamp:" .. tostring(updatedAt) .. ":" .. tostring(createdAt))
  end

  local function BuildLiveBoardCheckpointRows(snapshot, opts)
    opts = type(opts) == "table" and opts or {}
    if type(opts.prebuiltRowsBySubdomain) == "table" then
      return opts.prebuiltRowsBySubdomain
    end
    local subdomain = BuildLiveBoardCheckpointSubdomain(snapshot)
    local itemKey = TrimText(opts.itemKey)
    if subdomain == "" or itemKey == "" then
      return nil
    end

    local rows = {}
    local snapshotItem = type(snapshot) == "table" and type(snapshot.items) == "table" and snapshot.items[itemKey] or nil
    if TrimText(opts.voterKey) ~= "" then
      local voterKey = TrimText(opts.voterKey)
      local votePayload = {
        snapshot = {
          items = {
            [itemKey] = {
              votesByVoter = {},
              voteUpdatedAtByVoter = {},
              voteSequenceByVoter = {},
            },
          },
        },
      }
      if type(snapshotItem) == "table" then
        local targetKey = TrimText(type(snapshotItem.votesByVoter) == "table" and snapshotItem.votesByVoter[voterKey] or "")
        if targetKey ~= "" then
          votePayload.snapshot.items[itemKey].votesByVoter[voterKey] = targetKey
        end
        local updatedAt = tonumber(type(snapshotItem.voteUpdatedAtByVoter) == "table" and snapshotItem.voteUpdatedAtByVoter[voterKey] or nil)
        if updatedAt then
          votePayload.snapshot.items[itemKey].voteUpdatedAtByVoter[voterKey] = updatedAt
        end
        local sequence = tonumber(type(snapshotItem.voteSequenceByVoter) == "table" and snapshotItem.voteSequenceByVoter[voterKey] or nil)
        if sequence then
          votePayload.snapshot.items[itemKey].voteSequenceByVoter[voterKey] = sequence
        end
      end
      rows[#rows + 1] = {
        id = "live_board:vote:" .. itemKey .. ":" .. voterKey,
        subdomain = subdomain,
        applySpec = {
          kind = "live_board_vote",
          itemKey = itemKey,
          voterKey = voterKey,
        },
        remotePayload = votePayload,
      }
    end

    if TrimText(opts.selectionMemberKey) ~= "" then
      local memberKey = TrimText(opts.selectionMemberKey)
      local selectionPayload = {
        snapshot = {
          items = {
            [itemKey] = {
              selections = {},
            },
          },
        },
      }
      if type(snapshotItem) == "table"
        and type(snapshotItem.selections) == "table"
        and type(snapshotItem.selections[memberKey]) == "table"
      then
        selectionPayload.snapshot.items[itemKey].selections[memberKey] = DeepCopy(snapshotItem.selections[memberKey])
      end
      rows[#rows + 1] = {
        id = "live_board:selection:" .. itemKey .. ":" .. memberKey,
        subdomain = subdomain,
        applySpec = {
          kind = "live_board_member_selection",
          itemKey = itemKey,
          memberKey = memberKey,
        },
        remotePayload = selectionPayload,
      }
    end

    local fieldKeys = type(opts.fieldKeys) == "table" and opts.fieldKeys or nil
    if type(fieldKeys) == "table" then
      for _, fieldKey in ipairs(fieldKeys) do
        local resolvedFieldKey = TrimText(fieldKey)
        if resolvedFieldKey ~= "" then
          rows[#rows + 1] = {
            id = "live_board:field:" .. itemKey .. ":" .. resolvedFieldKey,
            subdomain = subdomain,
            applySpec = {
              kind = "table_field",
              tableField = "snapshot.items_scalar",
              itemKey = itemKey,
              key = resolvedFieldKey,
            },
            remotePayload = {
              snapshot = {
                items = {
                  [itemKey] = {
                    [resolvedFieldKey] = type(snapshotItem) == "table" and DeepCopy(snapshotItem[resolvedFieldKey]) or nil,
                  },
                },
              },
            },
          }
        end
      end
    end

    if #rows == 0 then
      rows[#rows + 1] = {
        id = "live_board:item:" .. itemKey,
        subdomain = subdomain,
        applySpec = {
          kind = "live_board_item",
          itemKey = itemKey,
        },
        remotePayload = {
          snapshot = {
            items = {
              [itemKey] = DeepCopy(snapshotItem),
            },
          },
        },
      }
    end

    if opts.includeItemOrder == true then
      rows[#rows + 1] = {
        id = "live_board:item_order:" .. itemKey,
        subdomain = subdomain,
        applySpec = {
          kind = "snapshot_item_order",
        },
        remotePayload = {
          snapshot = {
            itemOrder = DeepCopy(type(snapshot) == "table" and snapshot.itemOrder or {}),
          },
        },
      }
    end
    return #rows > 0 and {
      [subdomain] = rows,
    } or nil
  end

  local function QueueLiveBoardCheckpoint(profileName, snapshot, opts)
    local queueCheckpoint = ResolveOptionalApiFunction("LIDCOUNCIL_QueueActiveProfileCheckpointFlow")
    if type(queueCheckpoint) ~= "function" then
      return false
    end
    local subdomain = BuildLiveBoardCheckpointSubdomain(snapshot)
    if subdomain == "" then
      return false
    end
    return queueCheckpoint(profileName, {
      reason = "board_checkpoint",
      domains = { "session" },
      subdomains = { subdomain },
      prebuiltRowsBySubdomain = BuildLiveBoardCheckpointRows(snapshot, opts),
    })
  end

  local function BuildHistorySelectionSnapshot(selection)
    local selectedSeq = tonumber(selection and selection.selectedSeq)
    if not selectedSeq or selectedSeq <= 0 then
      local fallbackSeq = tonumber(selection and selection.selectedAt)
      selectedSeq = (fallbackSeq and fallbackSeq > 0) and math.floor(fallbackSeq) or 1
    else
      selectedSeq = math.floor(selectedSeq)
    end
    return {
      optionKey = TrimText(selection and selection.optionKey or ""),
      label = TrimText(selection and selection.label or ""),
      rollValue = tonumber(selection and selection.rollValue),
      note = NormalizeSelectionNote(selection and selection.note or ""),
      selectedAt = tonumber(selection and selection.selectedAt),
      selectedSeq = selectedSeq,
      source = TrimText(selection and selection.source or ""),
      receiptState = TrimText(selection and selection.receiptState or ""),
      receiptRearmCount = math.max(0, math.floor(tonumber(selection and selection.receiptRearmCount) or 0)),
      pointBehavior = TrimText(selection and selection.pointBehavior or ""),
    }
  end

  local function NormalizeEntryVotes(entry)
    local hadVoteTable = type(entry) == "table" and type(entry.votesByVoter) == "table"
    local normalized = {}
    if type(entry) == "table" and type(entry.votesByVoter) == "table" then
      for voterKey, targetKey in pairs(entry.votesByVoter) do
        local normalizedVoterKey = NormalizeCharacterKey(voterKey)
        local normalizedTargetKey = NormalizeCharacterKey(targetKey)
        if normalizedVoterKey ~= "" and normalizedTargetKey ~= "" then
          normalized[normalizedVoterKey] = normalizedTargetKey
        end
      end
    end

    local legacyTargetKey = TrimText(type(entry) == "table" and entry.hostVoteFor or "")
    if legacyTargetKey ~= "" and not hadVoteTable then
      local selfKey = ResolveSelfKey()
      if selfKey ~= "" and normalized[selfKey] == nil then
        normalized[selfKey] = NormalizeCharacterKey(legacyTargetKey)
      end
    end

    if type(entry) == "table" then
      entry.votesByVoter = normalized
      local selfKey = ResolveSelfKey()
      local selfTargetKey = selfKey ~= "" and TrimText(normalized[selfKey]) or ""
      if selfTargetKey ~= "" then
        entry.hostVoteFor = selfTargetKey
      elseif legacyTargetKey ~= "" and next(normalized) == nil and not hadVoteTable then
        entry.hostVoteFor = NormalizeCharacterKey(legacyTargetKey)
      else
        entry.hostVoteFor = nil
      end
    end

    return normalized
  end

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

  local function NormalizeVoteSequence(entry)
    local normalized = {}
    local votesByVoter = NormalizeEntryVotes(entry)
    local updatedAtByVoter = NormalizeVoteUpdatedAt(entry)

    if type(entry) == "table" and type(entry.voteSequenceByVoter) == "table" then
      for voterKey, sequence in pairs(entry.voteSequenceByVoter) do
        local normalizedVoterKey = NormalizeCharacterKey(voterKey)
        local normalizedSequence = tonumber(sequence)
        if normalizedVoterKey ~= "" and normalizedSequence and normalizedSequence > 0 then
          normalized[normalizedVoterKey] = math.floor(normalizedSequence)
        end
      end
    end

    for voterKey in pairs(votesByVoter or {}) do
      if normalized[voterKey] == nil then
        local fallbackSequence = tonumber(updatedAtByVoter[voterKey])
        normalized[voterKey] = (fallbackSequence and fallbackSequence > 0) and math.floor(fallbackSequence) or 1
      end
    end

    if type(entry) == "table" then
      entry.voteSequenceByVoter = normalized
    end
    return normalized
  end

  local function GetEntryVoteTargetForVoter(entry, voterKey)
    local normalizedVotes = NormalizeEntryVotes(entry)
    local normalizedVoterKey = NormalizeCharacterKey(voterKey)
    if normalizedVoterKey == "" then
      return ""
    end
    return TrimText(normalizedVotes[normalizedVoterKey])
  end

  local function SetEntryVoteTarget(entry, voterKey, targetMemberKey)
    if type(entry) ~= "table" then
      return ""
    end

    local normalizedVotes = NormalizeEntryVotes(entry)
    local normalizedVoterKey = NormalizeCharacterKey(voterKey)
    local normalizedTargetKey = NormalizeCharacterKey(targetMemberKey)
    if normalizedVoterKey == "" then
      return ""
    end

    if normalizedTargetKey == "" then
      normalizedVotes[normalizedVoterKey] = nil
    else
      normalizedVotes[normalizedVoterKey] = normalizedTargetKey
    end

    entry.votesByVoter = normalizedVotes
    NormalizeEntryVotes(entry)
    return TrimText(normalizedVotes[normalizedVoterKey])
  end

  local function GetEntryVoteVoterKeys(entry, targetMemberKey)
    local normalizedTargetKey = NormalizeCharacterKey(targetMemberKey)
    if normalizedTargetKey == "" then
      return {}
    end

    local voterKeys = {}
    for voterKey, votedTargetKey in pairs(NormalizeEntryVotes(entry)) do
      if NormalizeCharacterKey(votedTargetKey) == normalizedTargetKey then
        voterKeys[#voterKeys + 1] = NormalizeCharacterKey(voterKey)
      end
    end

    table.sort(voterKeys, function(left, right)
      return string.lower(tostring(left or "")) < string.lower(tostring(right or ""))
    end)
    return voterKeys
  end

  local function GetEntryVoteCount(entry, targetMemberKey)
    return #GetEntryVoteVoterKeys(entry, targetMemberKey)
  end

  local function BuildHistoryItemSnapshot(entry)
    if type(entry) ~= "table" then
      return nil
    end

    local snapshot = {
      key = TrimText(entry.key),
      name = TrimText(entry.name),
      link = entry.link,
      icon = entry.icon,
      quality = tonumber(entry.quality),
      itemID = ExtractItemID(entry.itemID or entry.link),
      itemLevel = tonumber(entry.itemLevel),
      distributionMode = TrimText(entry.distributionMode),
      collectibleKind = TrimText(entry.collectibleKind),
      createdAt = tonumber(entry.createdAt),
      hostVoteFor = TrimText(entry.hostVoteFor),
      awardedTo = TrimText(entry.awardedTo),
      awardedPoints = tonumber(entry.awardedPoints),
      awardedNote = TrimText(entry.awardedNote),
      awardedAt = tonumber(entry.awardedAt),
      awardUpdatedAt = tonumber(entry.awardUpdatedAt),
      tradeState = TrimText(entry.tradeState),
      tradedAt = tonumber(entry.tradedAt),
      tradedBy = TrimText(entry.tradedBy),
      tradeUpdatedAt = tonumber(entry.tradeUpdatedAt),
      ledgerEntryId = TrimText(entry.ledgerEntryId),
      votesByVoter = DeepCopy(NormalizeEntryVotes(entry)),
      voteUpdatedAtByVoter = DeepCopy(NormalizeVoteUpdatedAt(entry)),
      voteSequenceByVoter = DeepCopy(NormalizeVoteSequence(entry)),
      selections = {},
    }

    for memberKey, selection in pairs(entry.selections or {}) do
      snapshot.selections[memberKey] = BuildHistorySelectionSnapshot(selection)
    end
    return snapshot
  end

  local function EnsureLiveBoardHistoryStore(profileName)
    local resolvedProfileName = TrimText(profileName)
    if resolvedProfileName == "" then
      return nil, nil
    end
    local profile = GetLootProfile(resolvedProfileName)
    if type(profile) ~= "table" then
      return nil, nil
    end
    profile.liveBoardHistory = type(profile.liveBoardHistory) == "table" and profile.liveBoardHistory or {}
    return profile.liveBoardHistory, profile
  end

  local function UpsertLiveBoardHistorySnapshot(profileName, snapshot)
    local history, profile = EnsureLiveBoardHistoryStore(profileName)
    if type(history) ~= "table" or type(snapshot) ~= "table" then
      return nil
    end

    snapshot.updatedAt = tonumber(snapshot.updatedAt) or ((type(GetServerTime) == "function" and GetServerTime()) or (time and time() or 0))
    local boardId = TrimText(snapshot.boardId)
    local existingIndex = nil
    if boardId ~= "" then
      for index, board in ipairs(history) do
        if type(board) == "table" and TrimText(board.boardId) == boardId then
          existingIndex = index
          break
        end
      end
    end

    local stored = DeepCopy(snapshot)
    if existingIndex then
      table.remove(history, existingIndex)
    end
    table.insert(history, 1, stored)
    while #history > 40 do
      table.remove(history)
    end
    liveBoardHistorySummaryCache[string.lower(TrimText(profileName))] = nil
    if type(profile) == "table" then
      if type(TouchLootProfileDomain) == "function" then
        TouchLootProfileDomain(profile, "operational")
      else
        profile.meta = profile.meta or {}
        profile.meta.updatedAt = (type(GetServerTime) == "function" and GetServerTime()) or (time and time() or 0)
      end
    end
    return stored
  end

  local function BuildRuntimeBoardHistorySnapshot()
    if TrimText(runtime.profileName) == "" or #runtime.itemOrder == 0 then
      return nil
    end

    local boardId, historyProfileName = EnsureRuntimeBoardContext(nil, runtime.profileName)
    local createdAt = time and time() or 0
    local items = {}
    for _, itemKey in ipairs(runtime.itemOrder) do
      local entry = runtime.items[itemKey]
      local snapshot = BuildHistoryItemSnapshot(entry)
      if snapshot then
        items[itemKey] = snapshot
        local itemCreatedAt = tonumber(entry and entry.createdAt)
        if itemCreatedAt and itemCreatedAt < createdAt then
          createdAt = itemCreatedAt
        end
      end
    end

    return {
      boardId = boardId,
      historyProfileName = historyProfileName,
      profileName = TrimText(runtime.profileName),
      sessionId = TrimText(runtime.sessionId),
      isSimulation = false,
      label = "Live Board",
      createdAt = createdAt,
      updatedAt = tonumber(runtime.boardUpdatedAt) or (time and time() or 0),
      selectedItemKey = TrimText(runtime.selectedItemKey),
      itemOrder = DeepCopy(runtime.itemOrder),
      items = items,
    }
  end

  local function PersistRuntimeBoardHistory(opts)
    local snapshot = BuildRuntimeBoardHistorySnapshot()
    if not snapshot then
      return nil
    end
    local updatedAt = (type(GetServerTime) == "function" and GetServerTime()) or (time and time() or 0)
    snapshot.updatedAt = math.max(tonumber(snapshot.updatedAt) or 0, updatedAt)
    if IsRealSimulationRuntimeSnapshot(snapshot) then
      snapshot.excludeFromHistory = true
    end
    local stored = UpsertLiveBoardHistorySnapshot(snapshot.historyProfileName, snapshot)
    runtime.boardUpdatedAt = tonumber(type(stored) == "table" and stored.updatedAt) or snapshot.updatedAt
    QueueLiveBoardCheckpoint(snapshot.historyProfileName, type(stored) == "table" and stored or snapshot, opts)
    return stored
  end

  local function GetLatestRuntimeBoardSnapshot(profileName, sessionId)
    local resolvedProfileName = TrimText(profileName)
    local resolvedSessionId = TrimText(sessionId)
    if resolvedProfileName == "" or resolvedSessionId == "" then
      return nil
    end

    local history = EnsureLiveBoardHistoryStore(resolvedProfileName)
    if type(history) ~= "table" then
      return nil
    end

    for _, snapshot in ipairs(history) do
      if type(snapshot) == "table"
        and not snapshot.isSimulation
        and TrimText(snapshot.sessionId) == resolvedSessionId
        and type(snapshot.items) == "table"
        and type(snapshot.itemOrder) == "table"
        and #snapshot.itemOrder > 0 then
        return DeepCopy(snapshot)
      end
    end
    return nil
  end

  local function RestoreRuntimeBoardSnapshot(session, profileName, snapshot)
    if type(session) ~= "table" or type(snapshot) ~= "table" then
      return false
    end

    runtime.boardId = TrimText(snapshot.boardId)
    runtime.boardUpdatedAt = tonumber(snapshot.updatedAt) or tonumber(runtime.boardUpdatedAt) or 0
    runtime.historyProfileName = TrimText(snapshot.historyProfileName ~= "" and snapshot.historyProfileName or profileName)
    runtime.selectedItemKey = nil
    runtime.selectedMemberKey = nil
    runtime.itemCounts = {}
    runtime.itemOrder = {}
    runtime.items = {}
    runtime.popupQueue = {}
    runtime.localRollItemKeys = {}
    runtime.hostRollItemKeys = {}
    runtime.hostReportItemKeys = {}

    for _, storedKey in ipairs(snapshot.itemOrder or {}) do
      local resolvedKey = TrimText(storedKey)
      local entry = resolvedKey ~= "" and DeepCopy(snapshot.items and snapshot.items[resolvedKey] or nil) or nil
      if type(entry) == "table" then
        entry.key = TrimText(entry.key ~= "" and entry.key or resolvedKey)
        entry.sessionId = runtime.sessionId
        entry.profileName = runtime.profileName
        entry.distributionMode = TrimText(entry.distributionMode)
        entry.collectibleKind = TrimText(entry.collectibleKind)
        entry.selections = type(entry.selections) == "table" and entry.selections or {}
        NormalizeEntryVotes(entry)
        NormalizeVoteUpdatedAt(entry)
        NormalizeVoteSequence(entry)

        for memberKey, selection in pairs(entry.selections or {}) do
          if type(selection) == "table" then
            local selectedSeq = tonumber(selection.selectedSeq)
            if not selectedSeq or selectedSeq <= 0 then
              local fallbackSeq = tonumber(selection.selectedAt)
              selection.selectedSeq = (fallbackSeq and fallbackSeq > 0) and math.floor(fallbackSeq) or 1
            else
              selection.selectedSeq = math.floor(selectedSeq)
            end
          end
        end

        if string.upper(TrimText(entry.distributionMode)) ~= "MANUAL_VISIBLE" then
          for memberKey, member in pairs(session.members or {}) do
            if tostring(type(member) == "table" and member.status or "JOINED") == "JOINED" and type(entry.selections[memberKey]) ~= "table" then
              entry.selections[memberKey] = {
                optionKey = "pending",
                label = "Pending",
                color = { 0.72, 0.72, 0.76 },
                selectedAt = nil,
                selectedSeq = nil,
                rollValue = nil,
                source = "RUNTIME",
              }
            end
          end
        else
          entry.selections = {}
          entry.votesByVoter = {}
        end

        runtime.items[entry.key] = entry
        runtime.itemOrder[#runtime.itemOrder + 1] = entry.key
        PrimeSequenceItemKey(entry.key)
      end
    end

    local selectedItemKey = TrimText(snapshot.selectedItemKey)
    if selectedItemKey ~= "" and runtime.items[selectedItemKey] then
      runtime.selectedItemKey = selectedItemKey
    else
      runtime.selectedItemKey = runtime.itemOrder[#runtime.itemOrder]
    end

    return #runtime.itemOrder > 0
  end

  local function BuildPreviewBoardHistorySnapshot(preview)
    if type(preview) ~= "table" then
      return nil
    end
    local boardId, historyProfileName = EnsurePreviewBoardContext(preview)
    if historyProfileName == "" then
      return nil
    end

    local items = {}
    for _, itemKey in ipairs(preview.itemOrder or {}) do
      local snapshot = BuildHistoryItemSnapshot(preview.items and preview.items[itemKey] or nil)
      if snapshot then
        items[itemKey] = snapshot
      end
    end

    return {
      boardId = boardId,
      historyProfileName = historyProfileName,
      profileName = TrimText(preview.profileName),
      sourceProfileName = TrimText(preview.sourceProfileName),
      sessionId = "",
      isSimulation = preview.isSimulation and true or false,
      label = TrimText(preview.summaryLabel ~= "" and preview.summaryLabel or (preview.isSimulation and "Simulation" or "Preview")),
      createdAt = tonumber(preview.createdAt) or (time and time() or 0),
      selectedItemKey = TrimText(preview.selectedItemKey),
      itemOrder = DeepCopy(preview.itemOrder or {}),
      items = items,
    }
  end

  local function PersistPreviewBoardHistory(preview)
    local snapshot = BuildPreviewBoardHistorySnapshot(preview)
    if not snapshot then
      return nil
    end
    local stored = UpsertLiveBoardHistorySnapshot(snapshot.historyProfileName, snapshot)
    if type(stored) == "table" and stored.isSimulation then
      local root = RootDB()
      root.ui = root.ui or {}
      root.ui.lastSimulationBoardHistoryProfile = TrimText(stored.historyProfileName)
      root.ui.lastSimulationBoardId = TrimText(stored.boardId)
      root.ui.lastSimulationUpdatedAt = tonumber(stored.updatedAt) or tonumber(stored.createdAt) or 0
    end
    return stored
  end

  local function GetLiveBoardHistoryEntries(profileName)
    local history = EnsureLiveBoardHistoryStore(profileName)
    if type(history) ~= "table" then
      return {}
    end
    local output = {}
    for _, snapshot in ipairs(history) do
      if type(snapshot) == "table" and snapshot.excludeFromHistory ~= true then
        output[#output + 1] = DeepCopy(snapshot)
      end
    end
    return output
  end

  local function BuildLiveBoardHistorySummary(snapshot)
    local totalItems = 0
    local awardedItems = 0
    for _, itemKey in ipairs(type(snapshot) == "table" and snapshot.itemOrder or {}) do
      local item = type(snapshot.items) == "table" and snapshot.items[itemKey] or nil
      if type(item) == "table" then
        totalItems = totalItems + 1
        if tonumber(item.awardedAt) or TrimText(item.awardedTo) ~= "" then
          awardedItems = awardedItems + 1
        end
      end
    end

    return {
      boardId = TrimText(type(snapshot) == "table" and snapshot.boardId or ""),
      createdAt = tonumber(type(snapshot) == "table" and snapshot.createdAt) or 0,
      updatedAt = tonumber(type(snapshot) == "table" and snapshot.updatedAt) or 0,
      isSimulation = type(snapshot) == "table" and snapshot.isSimulation and true or false,
      itemCount = totalItems,
      awardedItemCount = awardedItems,
    }
  end

  local function GetLiveBoardHistorySummaryCache(profileName, history, profile)
    local cacheKey = string.lower(TrimText(profileName))
    if cacheKey == "" or type(history) ~= "table" or type(profile) ~= "table" then
      return nil
    end

    local sessionRevision = 0
    if type(deps.GetLootProfileDomainRevision) == "function" then
      sessionRevision = tonumber(deps.GetLootProfileDomainRevision(profile, "session")) or 0
    end
    if sessionRevision <= 0 then
      sessionRevision = tonumber(type(profile.meta) == "table" and profile.meta.revision) or 0
    end

    local cached = liveBoardHistorySummaryCache[cacheKey]
    if type(cached) == "table"
      and cached.profile == profile
      and cached.history == history
      and cached.sessionRevision == sessionRevision then
      return cached
    end

    local summaries = {}
    local snapshotsByBoardId = {}
    local signatureParts = {}
    for _, snapshot in ipairs(history) do
      if type(snapshot) == "table" and snapshot.excludeFromHistory ~= true then
        local summary = BuildLiveBoardHistorySummary(snapshot)
        summaries[#summaries + 1] = summary
        local boardId = TrimText(summary.boardId)
        if boardId ~= "" then
          snapshotsByBoardId[boardId] = snapshot
        end
        signatureParts[#signatureParts + 1] = table.concat({
          boardId,
          tostring(tonumber(snapshot.updatedAt or snapshot.createdAt) or 0),
        }, ":")
      end
    end

    cached = {
      profile = profile,
      history = history,
      sessionRevision = sessionRevision,
      summaries = summaries,
      snapshotsByBoardId = snapshotsByBoardId,
      signature = table.concat(signatureParts, "\31"),
    }
    liveBoardHistorySummaryCache[cacheKey] = cached
    return cached
  end

  local function GetLiveBoardHistoryPage(profileName, requestedPage, requestedPageSize)
    local history, profile = EnsureLiveBoardHistoryStore(profileName)
    local pageSize = math.max(1, math.floor(tonumber(requestedPageSize) or 10))
    if type(history) ~= "table" then
      return {
        entries = {},
        page = 1,
        pageSize = pageSize,
        totalEntries = 0,
        totalPages = 1,
        signature = "",
      }
    end

    local cache = GetLiveBoardHistorySummaryCache(profileName, history, profile)
    local summaries = type(cache) == "table" and cache.summaries or {}
    local totalEntries = #summaries

    local totalPages = math.max(1, math.ceil(totalEntries / pageSize))
    local page = math.max(1, math.floor(tonumber(requestedPage) or 1))
    page = math.min(page, totalPages)
    local firstIndex = ((page - 1) * pageSize) + 1
    local lastIndex = math.min(totalEntries, firstIndex + pageSize - 1)
    local entries = {}
    for index = firstIndex, lastIndex do
      entries[#entries + 1] = summaries[index]
    end

    return {
      entries = entries,
      page = page,
      pageSize = pageSize,
      totalEntries = totalEntries,
      totalPages = totalPages,
      signature = type(cache) == "table" and cache.signature or "",
    }
  end

  local function GetLiveBoardHistorySnapshot(profileName, boardId)
    local resolvedBoardId = TrimText(boardId)
    if resolvedBoardId == "" then
      return nil
    end
    local history, profile = EnsureLiveBoardHistoryStore(profileName)
    if type(history) ~= "table" then
      return nil
    end
    local cache = GetLiveBoardHistorySummaryCache(profileName, history, profile)
    local snapshot = type(cache) == "table" and cache.snapshotsByBoardId[resolvedBoardId] or nil
    if type(snapshot) == "table" then
      return DeepCopy(snapshot)
    end
    return nil
  end

  local function GetLatestPreviewBoardSnapshot(profileName)
    local resolvedProfileName = TrimText(profileName)
    if resolvedProfileName == "" then
      return nil
    end

    local history = EnsureLiveBoardHistoryStore(resolvedProfileName)
    if type(history) ~= "table" then
      return nil
    end

    for _, snapshot in ipairs(history) do
      if type(snapshot) == "table"
        and snapshot.isSimulation
        and type(snapshot.items) == "table"
        and type(snapshot.itemOrder) == "table"
        and #snapshot.itemOrder > 0 then
        return DeepCopy(snapshot)
      end
    end
    return nil
  end

  local function GetBestPreviewBoardSnapshot(profileName)
    local resolvedProfileName = TrimText(profileName)
    local root = RootDB()
    local tried = {}

    local function markTried(name)
      local resolvedName = TrimText(name)
      if resolvedName == "" then
        return ""
      end
      local needle = string.lower(resolvedName)
      if tried[needle] then
        return ""
      end
      tried[needle] = true
      return resolvedName
    end

    local directName = markTried(resolvedProfileName)
    if directName ~= "" then
      local directSnapshot = GetLatestPreviewBoardSnapshot(directName)
      if directSnapshot then
        return directSnapshot
      end
    end

    local bestSnapshot = nil
    local bestUpdatedAt = nil
    local candidateNames = {
      root and root.currentProfile or nil,
      root and root.ui and root.ui.lastNonSimulationProfile or nil,
      "Simulation",
    }

    for _, candidateName in ipairs(candidateNames) do
      local resolvedCandidate = markTried(candidateName)
      if resolvedCandidate ~= "" then
        local snapshot = GetLatestPreviewBoardSnapshot(resolvedCandidate)
        if snapshot then
          local updatedAt = tonumber(snapshot.updatedAt) or tonumber(snapshot.createdAt) or 0
          if not bestSnapshot or updatedAt > (bestUpdatedAt or 0) then
            bestSnapshot = snapshot
            bestUpdatedAt = updatedAt
          end
        end
      end
    end

    if type(root) == "table" and type(root.profiles) == "table" then
      for candidateName in pairs(root.profiles) do
        local resolvedCandidate = markTried(candidateName)
        if resolvedCandidate ~= "" then
          local snapshot = GetLatestPreviewBoardSnapshot(resolvedCandidate)
          if snapshot then
            local updatedAt = tonumber(snapshot.updatedAt) or tonumber(snapshot.createdAt) or 0
            if not bestSnapshot or updatedAt > (bestUpdatedAt or 0) then
              bestSnapshot = snapshot
              bestUpdatedAt = updatedAt
            end
          end
        end
      end
    end

    return bestSnapshot
  end

  local function GetLastSimulationPreviewBoardSnapshot()
    local root = RootDB()
    local ui = type(root) == "table" and root.ui or nil
    local historyProfileName = TrimText(type(ui) == "table" and ui.lastSimulationBoardHistoryProfile or "")
    local boardId = TrimText(type(ui) == "table" and ui.lastSimulationBoardId or "")
    if historyProfileName == "" then
      return nil
    end

    local history = EnsureLiveBoardHistoryStore(historyProfileName)
    if type(history) ~= "table" then
      return nil
    end

    local fallbackSnapshot = nil
    local fallbackUpdatedAt = nil
    for _, snapshot in ipairs(history) do
      if type(snapshot) == "table" and snapshot.isSimulation then
        if boardId ~= "" and TrimText(snapshot.boardId) == boardId then
          return DeepCopy(snapshot)
        end
        local updatedAt = tonumber(snapshot.updatedAt) or tonumber(snapshot.createdAt) or 0
        if not fallbackSnapshot or updatedAt > (fallbackUpdatedAt or 0) then
          fallbackSnapshot = snapshot
          fallbackUpdatedAt = updatedAt
        end
      end
    end

    return fallbackSnapshot and DeepCopy(fallbackSnapshot) or nil
  end

  local function RestorePreviewBoardSnapshot(snapshot)
    if type(snapshot) ~= "table" or type(snapshot.items) ~= "table" or type(snapshot.itemOrder) ~= "table" or #snapshot.itemOrder == 0 then
      return nil
    end

    local resolvedProfileName = TrimText(snapshot.profileName)
    if resolvedProfileName == "" then
      resolvedProfileName = snapshot.isSimulation and "Simulation" or TrimText(snapshot.historyProfileName)
    end
    local resolvedSourceProfileName = TrimText(snapshot.sourceProfileName ~= "" and snapshot.sourceProfileName or snapshot.historyProfileName)
    if resolvedSourceProfileName == "" then
      resolvedSourceProfileName = resolvedProfileName
    end

    local sourceProfile = resolvedSourceProfileName ~= "" and GetLootProfile(resolvedSourceProfileName) or nil
    local metaByCharacter = type(sourceProfile) == "table" and type(sourceProfile.lootLedgerMeta) == "table" and sourceProfile.lootLedgerMeta or nil
    local selfKey = NormalizeCharacterKey(GetCharacterKey() or "")
    local memberKeys = {}
    local seenMemberKeys = {}

    local function addMemberKey(memberKey)
      local resolvedMemberKey = NormalizeCharacterKey(memberKey)
      if resolvedMemberKey == "" then
        return
      end
      local needle = string.lower(resolvedMemberKey)
      if seenMemberKeys[needle] then
        return
      end
      seenMemberKeys[needle] = true
      memberKeys[#memberKeys + 1] = resolvedMemberKey
    end

    for _, storedKey in ipairs(snapshot.itemOrder or {}) do
      local entry = type(snapshot.items) == "table" and snapshot.items[storedKey] or nil
      if type(entry) == "table" then
        for memberKey in pairs(entry.selections or {}) do
          addMemberKey(memberKey)
        end
        addMemberKey(entry.awardedTo)
      end
    end

    table.sort(memberKeys, function(left, right)
      return string.lower(tostring(left or "")) < string.lower(tostring(right or ""))
    end)

    local members = {}
    local memberInfoByKey = {}
    for _, memberKey in ipairs(memberKeys) do
      local meta = type(metaByCharacter) == "table" and type(metaByCharacter[memberKey]) == "table" and metaByCharacter[memberKey] or nil
      local row = {
        key = memberKey,
        name = memberKey,
        isHost = selfKey ~= "" and memberKey == selfKey,
        className = TrimText(type(meta) == "table" and meta.className or ""),
        classFile = TrimText(type(meta) == "table" and meta.classFile or ""),
        specName = TrimText(type(meta) == "table" and meta.specName or ""),
        specIcon = TrimText(type(meta) == "table" and meta.specIcon or ""),
        note = TrimText(type(meta) == "table" and meta.note or ""),
      }
      members[#members + 1] = row
      memberInfoByKey[memberKey] = row
    end

    local previewItems = {}
    local popupQueue = {}
    for _, storedKey in ipairs(snapshot.itemOrder or {}) do
      local entry = type(snapshot.items) == "table" and DeepCopy(snapshot.items[storedKey]) or nil
      if type(entry) == "table" then
        entry.key = TrimText(entry.key ~= "" and entry.key or storedKey)
        entry.selections = type(entry.selections) == "table" and entry.selections or {}
        NormalizeEntryVotes(entry)
        NormalizeVoteUpdatedAt(entry)
        NormalizeVoteSequence(entry)
        for memberKey, selection in pairs(entry.selections or {}) do
          if type(selection) == "table" then
            local selectedSeq = tonumber(selection.selectedSeq)
            if not selectedSeq or selectedSeq <= 0 then
              local fallbackSeq = tonumber(selection.selectedAt)
              selection.selectedSeq = (fallbackSeq and fallbackSeq > 0) and math.floor(fallbackSeq) or 1
            else
              selection.selectedSeq = math.floor(selectedSeq)
            end
          end
        end
        previewItems[entry.key] = entry
        if not entry.awardedAt then
          popupQueue[#popupQueue + 1] = entry.key
        end
      end
    end

    local selectedItemKey = TrimText(snapshot.selectedItemKey)
    if selectedItemKey == "" or not previewItems[selectedItemKey] then
      selectedItemKey = TrimText(snapshot.itemOrder[1])
    end

    return {
      profileName = resolvedProfileName ~= "" and resolvedProfileName or "Simulation",
      sourceProfileName = resolvedSourceProfileName,
      summaryLabel = TrimText(snapshot.label ~= "" and snapshot.label or (snapshot.isSimulation and "Simulation" or "Preview")),
      isSimulation = snapshot.isSimulation and true or false,
      selfKey = selfKey,
      members = members,
      memberInfoByKey = memberInfoByKey,
      itemOrder = DeepCopy(snapshot.itemOrder or {}),
      popupQueue = popupQueue,
      totalItems = #(snapshot.itemOrder or {}),
      items = previewItems,
      selectedItemKey = selectedItemKey,
      selectedMemberKey = nil,
      boardId = TrimText(snapshot.boardId),
      historyProfileName = TrimText(snapshot.historyProfileName),
      createdAt = tonumber(snapshot.createdAt) or (time and time() or 0),
      updatedAt = tonumber(snapshot.updatedAt) or (time and time() or 0),
    }
  end

  local function RestoreLatestPreviewBoardState(profileName)
    local snapshot = GetLastSimulationPreviewBoardSnapshot() or GetBestPreviewBoardSnapshot(profileName)
    if not snapshot then
      return nil
    end
    return RestorePreviewBoardSnapshot(snapshot)
  end

  return {
    EnsureRuntimeBoardContext = EnsureRuntimeBoardContext,
    EnsurePreviewBoardContext = EnsurePreviewBoardContext,
    NormalizeEntryVotes = NormalizeEntryVotes,
    GetEntryVoteTargetForVoter = GetEntryVoteTargetForVoter,
    SetEntryVoteTarget = SetEntryVoteTarget,
    GetEntryVoteVoterKeys = GetEntryVoteVoterKeys,
    GetEntryVoteCount = GetEntryVoteCount,
    NormalizeVoteUpdatedAt = NormalizeVoteUpdatedAt,
    NormalizeVoteSequence = NormalizeVoteSequence,
    BuildRuntimeBoardHistorySnapshot = BuildRuntimeBoardHistorySnapshot,
    PersistRuntimeBoardHistory = PersistRuntimeBoardHistory,
    GetLatestRuntimeBoardSnapshot = GetLatestRuntimeBoardSnapshot,
    RestoreRuntimeBoardSnapshot = RestoreRuntimeBoardSnapshot,
    BuildPreviewBoardHistorySnapshot = BuildPreviewBoardHistorySnapshot,
    PersistPreviewBoardHistory = PersistPreviewBoardHistory,
    GetLiveBoardHistoryEntries = GetLiveBoardHistoryEntries,
    GetLiveBoardHistoryPage = GetLiveBoardHistoryPage,
    GetLiveBoardHistorySnapshot = GetLiveBoardHistorySnapshot,
    RestoreLatestPreviewBoardState = RestoreLatestPreviewBoardState,
  }
end
