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

INTERNAL_API.LIDCOUNCIL_CreateOutboundQueueSelectionHelpers_Impl = function(deps)
  deps = type(deps) == "table" and deps or {}
  local TrimText = type(deps.TrimText) == "function" and deps.TrimText or function(value)
    return tostring(value or "")
  end
  local NormalizeCharacterKey = type(deps.NormalizeCharacterKey) == "function" and deps.NormalizeCharacterKey or TrimText
  local GetNow = type(deps.GetNow) == "function" and deps.GetNow or function()
    return 0
  end
  local GetQueueItemPriority = type(deps.GetQueueItemPriority) == "function" and deps.GetQueueItemPriority or function()
    return 10
  end
  local GetQueue = type(deps.GetQueue) == "function" and deps.GetQueue or function()
    return {}
  end
  local ResolveArchiveQueuePacingTarget = type(deps.ResolveArchiveQueuePacingTarget) == "function"
    and deps.ResolveArchiveQueuePacingTarget
    or function()
      return ""
    end
  local GetArchivePacingState = type(deps.GetArchivePacingState) == "function"
    and deps.GetArchivePacingState
    or function()
      return nil
    end

  local function InvalidateArchivePacingSelectionCache()
    local archivePacing = GetArchivePacingState()
    if type(archivePacing) ~= "table" then
      return
    end
    archivePacing.singleTarget = nil
    archivePacing.singleTargetPriority = nil
  end

  local function SelectReadyOutboundCommQueueIndex(queue, now, archivePacing, options)
    local resolvedQueue = type(queue) == "table" and queue or {}
    local resolvedNow = math.max(0, tonumber(now) or GetNow())
    options = type(options) == "table" and options or {}
    local nextDeferredAt = 0
    local firstReadyIndex
    local firstQueued = resolvedQueue[1]
    local firstNotBeforeAt = math.max(0, tonumber(type(firstQueued) == "table" and firstQueued.notBeforeAt or 0) or 0)
    if options.fastReadyHead == true and type(firstQueued) == "table" and firstNotBeforeAt <= resolvedNow then
      firstReadyIndex = 1
    else
      for index, queued in ipairs(resolvedQueue) do
        local notBeforeAt = math.max(0, tonumber(type(queued) == "table" and queued.notBeforeAt or 0) or 0)
        if notBeforeAt <= resolvedNow then
          firstReadyIndex = firstReadyIndex or index
        elseif nextDeferredAt <= 0 or notBeforeAt < nextDeferredAt then
          nextDeferredAt = notBeforeAt
        end
      end
    end
    if not firstReadyIndex then
      return nil, nextDeferredAt, false
    end

    local firstReadyItem = resolvedQueue[firstReadyIndex]
    local firstReadyKind = TrimText(type(firstReadyItem) == "table" and firstReadyItem.kind or "")
    local firstReadyTarget = ResolveArchiveQueuePacingTarget(firstReadyItem)
    archivePacing = type(archivePacing) == "table" and archivePacing or {}
    local burstLimit = math.max(1, tonumber(archivePacing.burstLimit) or 2)
    local lastTarget = NormalizeCharacterKey(archivePacing.lastTarget)
    local consecutiveChunks = math.max(0, tonumber(archivePacing.consecutiveChunks) or 0)
    if firstReadyKind ~= "PSYNC_CHUNK" or firstReadyTarget == "" or lastTarget ~= firstReadyTarget
      or consecutiveChunks < burstLimit
    then
      return firstReadyIndex, nextDeferredAt, false
    end

    local firstReadyPriority = GetQueueItemPriority(firstReadyItem)
    if options.fastReadyHead == true
      and NormalizeCharacterKey(archivePacing.singleTarget) == firstReadyTarget
      and math.max(0, tonumber(archivePacing.singleTargetPriority) or 0) == firstReadyPriority
    then
      return firstReadyIndex, nextDeferredAt, false
    end
    local earlierTransferIds = {}
    local differentPacingTargetExists = false
    for index = 1, firstReadyIndex - 1 do
      local metadata = type(resolvedQueue[index]) == "table" and type(resolvedQueue[index].metadata) == "table"
        and resolvedQueue[index].metadata
        or {}
      local transferId = TrimText(metadata.transferId)
      if transferId ~= "" then
        earlierTransferIds[transferId] = true
      end
    end
    for index = firstReadyIndex + 1, #resolvedQueue do
      local queued = resolvedQueue[index]
      local notBeforeAt = math.max(0, tonumber(type(queued) == "table" and queued.notBeforeAt or 0) or 0)
      if GetQueueItemPriority(queued) == firstReadyPriority then
        local target = ResolveArchiveQueuePacingTarget(queued)
        if target ~= "" and target ~= firstReadyTarget then
          differentPacingTargetExists = true
        end
        if notBeforeAt <= resolvedNow then
          local metadata = type(queued) == "table" and type(queued.metadata) == "table" and queued.metadata or {}
          local transferId = TrimText(metadata.transferId)
          if target ~= "" and target ~= firstReadyTarget and (transferId == "" or not earlierTransferIds[transferId]) then
            return index, nextDeferredAt, true
          end
        end
      end
      local metadata = type(queued) == "table" and type(queued.metadata) == "table" and queued.metadata or {}
      local transferId = TrimText(metadata.transferId)
      if transferId ~= "" then
        earlierTransferIds[transferId] = true
      end
    end
    if options.fastReadyHead == true and not differentPacingTargetExists then
      archivePacing.singleTarget = firstReadyTarget
      archivePacing.singleTargetPriority = firstReadyPriority
    end
    return firstReadyIndex, nextDeferredAt, false
  end

  local function InsertOutboundCommQueueItem(item, preserveTransferOrder, queue)
    local resolvedQueue = type(queue) == "table" and queue or GetQueue()
    local itemPriority = GetQueueItemPriority(item)
    local queueCount = #resolvedQueue
    local insertAt = queueCount + 1
    local itemMetadata = type(item) == "table" and type(item.metadata) == "table" and item.metadata or {}
    local itemTransferId = preserveTransferOrder == true and TrimText(itemMetadata.transferId) or ""
    local tailPriority = queueCount > 0 and GetQueueItemPriority(resolvedQueue[queueCount]) or 0
    if queueCount == 0 or (itemTransferId == "" and itemPriority >= tailPriority) then
      resolvedQueue[queueCount + 1] = item
      InvalidateArchivePacingSelectionCache()
      return queueCount + 1
    end
    if itemTransferId == "" then
      local low = 1
      local high = queueCount
      while low <= high do
        local middle = math.floor((low + high) / 2)
        if GetQueueItemPriority(resolvedQueue[middle]) <= itemPriority then
          low = middle + 1
        else
          high = middle - 1
        end
      end
      insertAt = low
    else
      for index, queued in ipairs(resolvedQueue) do
        local queuedPriority = GetQueueItemPriority(queued)
        if itemPriority < queuedPriority then
          insertAt = index
          break
        end
        if itemPriority == queuedPriority then
          local queuedMetadata = type(queued) == "table" and type(queued.metadata) == "table" and queued.metadata or {}
          if itemTransferId == TrimText(queuedMetadata.transferId) then
            insertAt = index
            break
          end
        end
      end
    end
    table.insert(resolvedQueue, insertAt, item)
    InvalidateArchivePacingSelectionCache()
    return insertAt
  end

  return {
    SelectReadyOutboundCommQueueIndex = SelectReadyOutboundCommQueueIndex,
    InsertOutboundCommQueueItem = InsertOutboundCommQueueItem,
  }
end
