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

local TRACE_VERSION = 2
local TRACE_CAPACITY = 2000
local FRAME_GAP_THRESHOLD_SECONDS = 0.25
local SAMPLE_INTERVAL_SECONDS = 1.0
local IDLE_HEARTBEAT_SECONDS = 10.0
local MAX_DETAIL_LENGTH = 420

local function GetMonotonicTime()
  if type(GetTimePreciseSec) == "function" then
    return math.max(0, tonumber(GetTimePreciseSec()) or 0)
  end
  if type(debugprofilestop) == "function" then
    return math.max(0, (tonumber(debugprofilestop()) or 0) / 1000)
  end
  if type(GetTime) == "function" then
    return math.max(0, tonumber(GetTime()) or 0)
  end
  return math.max(0, tonumber(type(time) == "function" and time() or 0) or 0)
end

local function GetWallTime()
  if type(GetServerTime) == "function" then
    return math.max(0, tonumber(GetServerTime()) or 0)
  end
  return math.max(0, tonumber(type(time) == "function" and time() or 0) or 0)
end

local function TrimText(value)
  local text = tostring(value or "")
  text = text:gsub("[\r\n\t]+", " ")
  text = text:gsub("^%s+", ""):gsub("%s+$", "")
  if #text > MAX_DETAIL_LENGTH then
    text = text:sub(1, MAX_DETAIL_LENGTH - 3) .. "..."
  end
  return text
end

local function FormatNumber(value)
  local numberValue = tonumber(value)
  if not numberValue then
    return TrimText(value)
  end
  if numberValue == math.floor(numberValue) then
    return tostring(math.floor(numberValue))
  end
  return string.format("%.3f", numberValue)
end

local function CloneScalarFields(fields)
  local clone = {}
  for key, value in pairs(type(fields) == "table" and fields or {}) do
    local valueType = type(value)
    if valueType == "number" or valueType == "boolean" then
      clone[TrimText(key)] = value
    elseif valueType == "string" then
      clone[TrimText(key)] = TrimText(value)
    end
  end
  return clone
end

local function BuildFieldText(fields)
  local keys = {}
  for key in pairs(type(fields) == "table" and fields or {}) do
    if TrimText(key) ~= "" then
      keys[#keys + 1] = key
    end
  end
  table.sort(keys, function(left, right)
    return tostring(left) < tostring(right)
  end)
  local parts = {}
  for _, key in ipairs(keys) do
    local value = fields[key]
    local valueText
    if type(value) == "boolean" then
      valueText = value and "true" or "false"
    elseif type(value) == "number" then
      valueText = FormatNumber(value)
    else
      valueText = TrimText(value)
    end
    if valueText ~= "" then
      parts[#parts + 1] = TrimText(key) .. "=" .. valueText
    end
  end
  return table.concat(parts, " ")
end

local state = {
  active = false,
  records = {},
  head = 1,
  count = 0,
  totalEvents = 0,
  overwritten = 0,
  startedAt = 0,
  startedWall = 0,
  stoppedAt = 0,
  stoppedWall = 0,
  sampleAccumulator = 0,
  phaseStack = {},
  currentPhase = "",
  lastPhase = "",
  lastEvent = "",
  lastTransport = nil,
  baselineTransport = nil,
  lastSampleSignature = "",
  lastSampleRecordedAt = 0,
  lastLockdownState = nil,
  lastCooldownState = nil,
  context = {},
  summary = {},
}

local function ResetSummary()
  state.summary = {
    maxFrameGapMs = 0,
    maxFrameGapAt = 0,
    maxEditorRefreshMs = 0,
    maxSnapshotPrepareMs = 0,
    maxInboundJoinMs = 0,
    maxJoinFollowupMs = 0,
    maxQueueDepth = 0,
    lockdownEnters = 0,
    throttleCooldownEnters = 0,
    markerCount = 0,
    performanceEvents = 0,
    suppressedQueueSamples = 0,
    phaseMaximums = {},
    eventCounts = {},
  }
end

local function ResetTraceStorage()
  state.records = {}
  state.head = 1
  state.count = 0
  state.totalEvents = 0
  state.overwritten = 0
  state.startedAt = 0
  state.startedWall = 0
  state.stoppedAt = 0
  state.stoppedWall = 0
  state.sampleAccumulator = 0
  state.phaseStack = {}
  state.currentPhase = ""
  state.lastPhase = ""
  state.lastEvent = ""
  state.lastTransport = nil
  state.baselineTransport = nil
  state.lastSampleSignature = ""
  state.lastSampleRecordedAt = 0
  state.lastLockdownState = nil
  state.lastCooldownState = nil
  state.context = {}
  ResetSummary()
end

ResetSummary()

local function GetElapsed(now)
  local startedAt = math.max(0, tonumber(state.startedAt) or 0)
  if startedAt <= 0 then
    return 0
  end
  return math.max(0, (tonumber(now) or GetMonotonicTime()) - startedAt)
end

local function AppendRecord(eventName, detail, fields, now)
  if state.active ~= true then
    return false
  end
  local resolvedEventName = string.upper(TrimText(eventName))
  if resolvedEventName == "" then
    return false
  end
  now = tonumber(now) or GetMonotonicTime()
  local record = {
    elapsed = GetElapsed(now),
    event = resolvedEventName,
    detail = TrimText(detail),
    fields = CloneScalarFields(fields),
  }
  local index
  if state.count < TRACE_CAPACITY then
    index = ((state.head + state.count - 1) % TRACE_CAPACITY) + 1
    state.count = state.count + 1
  else
    index = state.head
    state.head = (state.head % TRACE_CAPACITY) + 1
    state.overwritten = state.overwritten + 1
  end
  state.records[index] = record
  state.totalEvents = state.totalEvents + 1
  state.lastEvent = resolvedEventName
  local eventCounts = state.summary.eventCounts
  eventCounts[resolvedEventName] = math.max(0, tonumber(eventCounts[resolvedEventName]) or 0) + 1
  state.summary.maxQueueDepth = math.max(
    math.max(0, tonumber(state.summary.maxQueueDepth) or 0),
    math.max(0, tonumber(type(fields) == "table" and (fields.queue or fields.queueDepth) or 0) or 0)
  )
  if resolvedEventName == "LOCKDOWN_ENTER" then
    state.summary.lockdownEnters = state.summary.lockdownEnters + 1
    state.lastLockdownState = true
  elseif resolvedEventName == "LOCKDOWN_EXIT" then
    state.lastLockdownState = false
  elseif resolvedEventName == "THROTTLE_COOLDOWN_ENTER" then
    state.summary.throttleCooldownEnters = state.summary.throttleCooldownEnters + 1
    state.lastCooldownState = true
  elseif resolvedEventName == "THROTTLE_COOLDOWN_EXIT" then
    state.lastCooldownState = false
  elseif resolvedEventName == "MARKER" then
    state.summary.markerCount = state.summary.markerCount + 1
  end
  return true
end

local function RecordEvent(eventName, detail, fields)
  return AppendRecord(eventName, detail, fields, GetMonotonicTime())
end

local function BeginPhase(phaseName, detail, fields)
  if state.active ~= true then
    return nil
  end
  local resolvedName = string.upper(TrimText(phaseName))
  if resolvedName == "" then
    return nil
  end
  local token = {
    name = resolvedName,
    startedAt = GetMonotonicTime(),
    parent = state.currentPhase,
  }
  state.phaseStack[#state.phaseStack + 1] = token
  state.currentPhase = resolvedName
  AppendRecord(resolvedName .. "_BEGIN", detail, fields, token.startedAt)
  return token
end

local function EndPhase(token, detail, fields)
  if type(token) ~= "table" or state.active ~= true then
    return false, 0
  end
  local completedAt = GetMonotonicTime()
  local durationMs = math.max(0, (completedAt - math.max(0, tonumber(token.startedAt) or completedAt)) * 1000)
  local resolvedName = string.upper(TrimText(token.name))
  local resolvedFields = CloneScalarFields(fields)
  resolvedFields.durationMs = durationMs
  AppendRecord(resolvedName .. "_END", detail, resolvedFields, completedAt)
  local maximums = state.summary.phaseMaximums
  maximums[resolvedName] = math.max(math.max(0, tonumber(maximums[resolvedName]) or 0), durationMs)
  if resolvedName == "COMM_INBOUND_JOIN" then
    state.summary.maxInboundJoinMs = math.max(state.summary.maxInboundJoinMs, durationMs)
  elseif resolvedName == "ACCEPTED_JOIN_FOLLOWUP" then
    state.summary.maxJoinFollowupMs = math.max(state.summary.maxJoinFollowupMs, durationMs)
  end
  local removed = false
  for index = #state.phaseStack, 1, -1 do
    if state.phaseStack[index] == token then
      table.remove(state.phaseStack, index)
      removed = true
      break
    end
  end
  if removed then
    local parent = state.phaseStack[#state.phaseStack]
    state.currentPhase = type(parent) == "table" and TrimText(parent.name) or TrimText(token.parent)
  end
  state.lastPhase = resolvedName
  return true, durationMs
end

local TRACE_PERFORMANCE_METRICS = {
  editor_refresh = true,
  snapshot_prepare_total = true,
  snapshot_export = true,
  snapshot_chunks = true,
  snapshot_manifest = true,
}

local function RecordPerformance(metricName, durationMs, metadata)
  if state.active ~= true then
    return false
  end
  local metricKey = TrimText(metricName)
  local elapsedMs = math.max(0, tonumber(durationMs) or 0)
  if not TRACE_PERFORMANCE_METRICS[metricKey]
    and not (metricKey == "queue_flush_total" and elapsedMs >= 10)
  then
    return false
  end
  metadata = type(metadata) == "table" and metadata or {}
  local fields = {
    durationMs = elapsedMs,
    queue = math.max(0, tonumber(metadata.queueDepth) or 0),
    chunks = math.max(0, tonumber(metadata.chunkCount) or 0),
    bytes = math.max(0, tonumber(metadata.bytes) or 0),
    context = TrimText(metadata.context),
  }
  state.summary.performanceEvents = state.summary.performanceEvents + 1
  if metricKey == "editor_refresh" then
    state.summary.maxEditorRefreshMs = math.max(state.summary.maxEditorRefreshMs, elapsedMs)
  elseif metricKey == "snapshot_prepare_total" then
    state.summary.maxSnapshotPrepareMs = math.max(state.summary.maxSnapshotPrepareMs, elapsedMs)
  end
  local recorded = AppendRecord("PERF_" .. metricKey, "", fields, GetMonotonicTime())
  if recorded then
    state.lastPhase = "PERF_" .. metricKey
  end
  return recorded
end

local function ReadTransportSample()
  local provider = INTERNAL_API.LIDCOUNCIL_GetRaidTraceTransportSample_Impl
  if type(provider) ~= "function" then
    return {}
  end
  local ok, sample = pcall(provider)
  if not ok or type(sample) ~= "table" then
    return {}
  end
  return sample
end

local function GetGroupSize()
  if type(GetNumGroupMembers) == "function" then
    return math.max(0, tonumber(GetNumGroupMembers()) or 0)
  end
  return 0
end

local function SampleTransport(reason)
  if state.active ~= true then
    return false
  end
  local sample = ReadTransportSample()
  sample.groupSize = GetGroupSize()
  sample.reason = TrimText(reason)
  if state.context.character == nil or state.context.character == "" then
    state.context.character = TrimText(sample.character)
  end
  if state.context.role == nil or state.context.role == ""
    or (state.context.role == "NONE" and TrimText(sample.role) ~= "" and TrimText(sample.role) ~= "NONE")
  then
    state.context.role = TrimText(sample.role)
  end
  if state.context.sessionId == nil or state.context.sessionId == "" then
    state.context.sessionId = TrimText(sample.sessionId)
  end
  if state.context.profileName == nil or state.context.profileName == "" then
    state.context.profileName = TrimText(sample.profileName)
  end

  local sampledAt = GetMonotonicTime()
  local lockdown = sample.lockdown == true
  local cooldownActive = math.max(0, tonumber(sample.cooldownRemaining) or 0) > 0
  if state.lastLockdownState ~= nil and lockdown ~= state.lastLockdownState then
    AppendRecord(lockdown and "LOCKDOWN_ENTER" or "LOCKDOWN_EXIT", "sampled transport state", {
      queue = math.max(0, tonumber(sample.queueDepth) or 0),
    }, sampledAt)
  end
  if state.lastCooldownState ~= nil and cooldownActive ~= state.lastCooldownState then
    AppendRecord(cooldownActive and "THROTTLE_COOLDOWN_ENTER" or "THROTTLE_COOLDOWN_EXIT", "sampled transport state", {
      queue = math.max(0, tonumber(sample.queueDepth) or 0),
      remaining = math.max(0, tonumber(sample.cooldownRemaining) or 0),
    }, sampledAt)
  end
  state.lastLockdownState = lockdown
  state.lastCooldownState = cooldownActive

  local queueDepth = math.max(0, tonumber(sample.queueDepth) or 0)
  state.summary.maxQueueDepth = math.max(state.summary.maxQueueDepth, queueDepth)
  local fields = {
    queue = queueDepth,
    running = sample.queueRunning == true,
    attempted = math.max(0, tonumber(sample.attemptedTotal) or 0),
    sent = math.max(0, tonumber(sample.sentTotal) or 0),
    throttled = math.max(0, tonumber(sample.throttledTotal) or 0),
    failed = math.max(0, tonumber(sample.failedTotal) or 0),
    terminal = math.max(0, tonumber(sample.terminalFailureTotal) or 0),
    lockdown = lockdown,
    cooldown = math.max(0, tonumber(sample.cooldownRemaining) or 0),
    joinPending = math.max(0, tonumber(sample.acceptedJoinPending) or 0),
    joinAccepted = math.max(0, tonumber(sample.acceptedJoinTotal) or 0),
    joinProcessed = math.max(0, tonumber(sample.acceptedJoinProcessed) or 0),
    group = sample.groupSize,
    session = TrimText(sample.sessionStatus),
  }
  local sampleSignature = table.concat({
    tostring(fields.queue),
    tostring(fields.running),
    tostring(fields.attempted),
    tostring(fields.sent),
    tostring(fields.throttled),
    tostring(fields.failed),
    tostring(fields.terminal),
    tostring(fields.lockdown),
    tostring(math.floor((tonumber(fields.cooldown) or 0) * 10 + 0.5)),
    tostring(fields.joinPending),
    tostring(fields.joinAccepted),
    tostring(fields.joinProcessed),
    tostring(fields.group),
    tostring(fields.session),
  }, "|")
  local forceSample = reason == "start" or reason == "stop"
  local heartbeatDue = state.lastSampleRecordedAt <= 0
    or (sampledAt - state.lastSampleRecordedAt) >= IDLE_HEARTBEAT_SECONDS
  if forceSample or sampleSignature ~= state.lastSampleSignature or heartbeatDue then
    AppendRecord("QUEUE_SAMPLE", "", fields, sampledAt)
    state.lastSampleSignature = sampleSignature
    state.lastSampleRecordedAt = sampledAt
  else
    state.summary.suppressedQueueSamples = math.max(0, tonumber(state.summary.suppressedQueueSamples) or 0) + 1
  end
  local clonedSample = CloneScalarFields(sample)
  state.lastTransport = clonedSample
  if type(state.baselineTransport) ~= "table" then
    state.baselineTransport = CloneScalarFields(sample)
  end
  return true
end

local function ClearTrace()
  if state.active == true then
    return false, "Stop the active raid trace before clearing it."
  end
  ResetTraceStorage()
  return true
end

local function StartTrace(note)
  if state.active == true then
    return false, "A raid trace is already running."
  end
  ResetTraceStorage()
  state.active = true
  state.startedAt = GetMonotonicTime()
  state.startedWall = GetWallTime()
  AppendRecord("TRACE_START", TrimText(note) ~= "" and note or "Raid-scale diagnostic trace started.", {
    version = TRACE_VERSION,
    capacity = TRACE_CAPACITY,
    frameGapMs = FRAME_GAP_THRESHOLD_SECONDS * 1000,
  }, state.startedAt)
  SampleTransport("start")
  return true
end

local function StopTrace(note)
  if state.active ~= true then
    return false, "No raid trace is running."
  end
  SampleTransport("stop")
  local now = GetMonotonicTime()
  AppendRecord("TRACE_STOP", TrimText(note) ~= "" and note or "Raid-scale diagnostic trace stopped.", nil, now)
  state.stoppedAt = now
  state.stoppedWall = GetWallTime()
  state.active = false
  state.currentPhase = ""
  state.phaseStack = {}
  return true
end

local function AddMarker(note)
  if state.active ~= true then
    return false, "Start the raid trace before adding a marker."
  end
  local marker = TrimText(note)
  if marker == "" then
    marker = "Manual checkpoint"
  end
  AppendRecord("MARKER", marker, {
    group = GetGroupSize(),
    phase = TrimText(state.currentPhase),
  }, GetMonotonicTime())
  return true
end

local function GetChronologicalRecords()
  local records = {}
  for offset = 0, state.count - 1 do
    local index = ((state.head + offset - 1) % TRACE_CAPACITY) + 1
    if type(state.records[index]) == "table" then
      records[#records + 1] = state.records[index]
    end
  end
  return records
end

local function FormatRecordLine(record)
  local parts = {
    string.format("+%08.3f", math.max(0, tonumber(record.elapsed) or 0)),
    "[" .. TrimText(record.event) .. "]",
  }
  local detail = TrimText(record.detail)
  if detail ~= "" then
    parts[#parts + 1] = detail
  end
  local fieldText = BuildFieldText(record.fields)
  if fieldText ~= "" then
    parts[#parts + 1] = fieldText
  end
  return table.concat(parts, " ")
end

local function GetRecentLines(limit)
  local records = GetChronologicalRecords()
  local lines = {}
  local resolvedLimit = math.max(1, math.min(40, math.floor(tonumber(limit) or 10)))
  local first = math.max(1, #records - resolvedLimit + 1)
  for index = first, #records do
    lines[#lines + 1] = FormatRecordLine(records[index])
  end
  return lines
end

local function BuildCounterDelta(label, first, last)
  return label .. ": " .. tostring(math.max(0, (tonumber(last) or 0) - (tonumber(first) or 0)))
end

local function FormatWallTimestamp(value)
  local timestamp = math.max(0, tonumber(value) or 0)
  if timestamp <= 0 then
    return "unknown"
  end
  if type(date) == "function" then
    return tostring(date("%Y-%m-%d %H:%M:%S", timestamp))
  end
  return tostring(timestamp)
end

local function BuildReport()
  local now = GetMonotonicTime()
  local duration = state.startedAt > 0
    and math.max(0, (state.active and now or math.max(state.stoppedAt, state.startedAt)) - state.startedAt)
    or 0
  local baseline = type(state.baselineTransport) == "table" and state.baselineTransport or {}
  local latest = type(state.lastTransport) == "table" and state.lastTransport or baseline
  local summary = state.summary
  local eventCounts = type(summary.eventCounts) == "table" and summary.eventCounts or {}
  local function EventCount(eventName)
    return math.max(0, tonumber(eventCounts[eventName]) or 0)
  end
  local lines = {
    "LidCouncil Raid Test Trace",
    "Trace format: " .. tostring(TRACE_VERSION),
    "Status: " .. (state.active and "RUNNING" or (state.startedAt > 0 and "STOPPED" or "EMPTY")),
    "Started: " .. FormatWallTimestamp(state.startedWall),
    "Duration: " .. string.format("%.3fs", duration),
    "Character: " .. (TrimText(state.context.character) ~= "" and TrimText(state.context.character) or "unknown"),
    "Role: " .. (TrimText(state.context.role) ~= "" and TrimText(state.context.role) or "unknown"),
    "Session: " .. (TrimText(state.context.sessionId) ~= "" and TrimText(state.context.sessionId) or "none"),
    "Profile: " .. (TrimText(state.context.profileName) ~= "" and TrimText(state.context.profileName) or "none"),
    "Events: " .. tostring(state.count) .. " stored / " .. tostring(state.totalEvents)
      .. " recorded / " .. tostring(state.overwritten) .. " overwritten",
    "",
    "Summary",
    "Max frame gap: " .. string.format("%.1fms", summary.maxFrameGapMs),
    "Max editor refresh: " .. string.format("%.1fms", summary.maxEditorRefreshMs),
    "Max snapshot preparation: " .. string.format("%.1fms", summary.maxSnapshotPrepareMs),
    "Max inbound JOIN handler: " .. string.format("%.1fms", summary.maxInboundJoinMs),
    "Max accepted JOIN follow-up: " .. string.format("%.1fms", summary.maxJoinFollowupMs),
    "Queue high-water: " .. tostring(summary.maxQueueDepth),
    "Lockdown entries: " .. tostring(summary.lockdownEnters),
    "Throttle cooldown entries: " .. tostring(summary.throttleCooldownEnters),
    "Manual markers: " .. tostring(summary.markerCount),
    "Unchanged queue samples suppressed: " .. tostring(math.max(0, tonumber(summary.suppressedQueueSamples) or 0)),
    string.format(
      "Board sync lifecycle: %d snapshots | %d activated | %d newest coalesced | %d released | %d ACKs | %d failed",
      EventCount("BSYNC_SNAPSHOT_READY"),
      EventCount("BSYNC_DISPATCH_ACTIVATED"),
      EventCount("BSYNC_REQUEST_COALESCED"),
      EventCount("BSYNC_LATEST_RELEASED"),
      EventCount("BSYNC_ACK_COMPLETE"),
      EventCount("BSYNC_TRANSACTION_FAILED")
    ),
    string.format(
      "Board sync recovery: %d receipt timeouts | %d selective repairs | %d full rebuilds | %d ignored ACKs",
      EventCount("BSYNC_RECEIPT_TIMEOUT"),
      EventCount("BSYNC_SELECTIVE_REPAIR"),
      EventCount("BSYNC_FULL_REBUILD"),
      EventCount("BSYNC_ACK_IGNORED")
    ),
    string.format(
      "Test item lifecycle: %d requested | %d repeated coalesced | %d preload ready | %d preload timeout | %d boards built",
      EventCount("TEST_ITEMS_REQUEST"),
      EventCount("TEST_ITEMS_REQUEST_COALESCED"),
      EventCount("TEST_ITEMS_PRELOAD_READY"),
      EventCount("TEST_ITEMS_PRELOAD_TIMEOUT"),
      EventCount("TEST_ITEMS_BOARD_READY")
    ),
    BuildCounterDelta("Attempted sends during trace", baseline.attemptedTotal, latest.attemptedTotal),
    BuildCounterDelta("Successful sends during trace", baseline.sentTotal, latest.sentTotal),
    BuildCounterDelta("Throttle results during trace", baseline.throttledTotal, latest.throttledTotal),
    BuildCounterDelta("Send failures during trace", baseline.failedTotal, latest.failedTotal),
    BuildCounterDelta("Terminal failures during trace", baseline.terminalFailureTotal, latest.terminalFailureTotal),
    "Final queue depth: " .. tostring(math.max(0, tonumber(latest.queueDepth) or 0)),
    "",
    "Timeline",
  }
  for _, record in ipairs(GetChronologicalRecords()) do
    lines[#lines + 1] = FormatRecordLine(record)
  end
  return table.concat(lines, "\n")
end

local function GetStatus()
  local duration = state.startedAt > 0
    and math.max(0, ((state.active and GetMonotonicTime()) or math.max(state.stoppedAt, state.startedAt)) - state.startedAt)
    or 0
  return {
    version = TRACE_VERSION,
    capacity = TRACE_CAPACITY,
    active = state.active == true,
    hasTrace = state.startedAt > 0,
    eventCount = state.count,
    totalEvents = state.totalEvents,
    overwritten = state.overwritten,
    durationSeconds = duration,
    startedWall = state.startedWall,
    stoppedWall = state.stoppedWall,
    currentPhase = TrimText(state.currentPhase),
    lastPhase = TrimText(state.lastPhase),
    lastEvent = TrimText(state.lastEvent),
    context = CloneScalarFields(state.context),
    summary = CloneScalarFields(state.summary),
    recentLines = GetRecentLines(10),
  }
end

local function GetContract()
  return {
    version = TRACE_VERSION,
    capacity = TRACE_CAPACITY,
    frameGapThresholdSeconds = FRAME_GAP_THRESHOLD_SECONDS,
    sampleIntervalSeconds = SAMPLE_INTERVAL_SECONDS,
    idleHeartbeatSeconds = IDLE_HEARTBEAT_SECONDS,
    changedTransportSamplesOnly = true,
    uiRefreshPerEvent = false,
    bulkPacketsRecordedIndividually = false,
    supportsMarkers = true,
    supportsPerformanceTimings = true,
    supportsTransportSamples = true,
  }
end

local traceFrame = type(CreateFrame) == "function" and CreateFrame("Frame") or nil
if traceFrame then
  traceFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
  traceFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
  traceFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
  traceFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
  traceFrame:RegisterEvent("ENCOUNTER_START")
  traceFrame:RegisterEvent("ENCOUNTER_END")
  traceFrame:SetScript("OnEvent", function(_, eventName, ...)
    if state.active ~= true then
      return
    end
    if eventName == "GROUP_ROSTER_UPDATE" then
      RecordEvent("GROUP_ROSTER_UPDATE", "", { group = GetGroupSize() })
    elseif eventName == "PLAYER_REGEN_DISABLED" then
      RecordEvent("COMBAT_ENTER", "", { group = GetGroupSize() })
    elseif eventName == "PLAYER_REGEN_ENABLED" then
      RecordEvent("COMBAT_EXIT", "", { group = GetGroupSize() })
    elseif eventName == "PLAYER_ENTERING_WORLD" then
      local isInitialLogin, isReloadingUi = ...
      RecordEvent("PLAYER_ENTERING_WORLD", "", {
        initialLogin = isInitialLogin == true,
        reloadingUi = isReloadingUi == true,
        group = GetGroupSize(),
      })
    elseif eventName == "ENCOUNTER_START" then
      local encounterId, encounterName, difficultyId, groupSize = ...
      RecordEvent("ENCOUNTER_START", TrimText(encounterName), {
        encounterId = tonumber(encounterId) or 0,
        difficulty = tonumber(difficultyId) or 0,
        group = tonumber(groupSize) or GetGroupSize(),
      })
    elseif eventName == "ENCOUNTER_END" then
      local encounterId, encounterName, difficultyId, groupSize, success = ...
      RecordEvent("ENCOUNTER_END", TrimText(encounterName), {
        encounterId = tonumber(encounterId) or 0,
        difficulty = tonumber(difficultyId) or 0,
        group = tonumber(groupSize) or GetGroupSize(),
        success = tonumber(success) or 0,
      })
    end
  end)
  traceFrame:SetScript("OnUpdate", function(_, elapsed)
    if state.active ~= true then
      return
    end
    local frameElapsed = math.max(0, tonumber(elapsed) or 0)
    if frameElapsed >= FRAME_GAP_THRESHOLD_SECONDS then
      local gapMs = frameElapsed * 1000
      state.summary.maxFrameGapMs = math.max(state.summary.maxFrameGapMs, gapMs)
      state.summary.maxFrameGapAt = GetElapsed(GetMonotonicTime())
      AppendRecord("FRAME_GAP", "Main-thread frame gap detected.", {
        durationMs = gapMs,
        currentPhase = TrimText(state.currentPhase),
        lastPhase = TrimText(state.lastPhase),
        previousEvent = TrimText(state.lastEvent),
      }, GetMonotonicTime())
    end
    state.sampleAccumulator = state.sampleAccumulator + frameElapsed
    if state.sampleAccumulator >= SAMPLE_INTERVAL_SECONDS then
      state.sampleAccumulator = 0
      SampleTransport("interval")
    end
  end)
end

API.LIDCOUNCIL_StartRaidTestTrace = StartTrace
API.LIDCOUNCIL_StopRaidTestTrace = StopTrace
API.LIDCOUNCIL_ClearRaidTestTrace = ClearTrace
API.LIDCOUNCIL_AddRaidTestTraceMarker = AddMarker
API.LIDCOUNCIL_GetRaidTestTraceStatus = GetStatus
API.LIDCOUNCIL_BuildRaidTestTraceReport = BuildReport

INTERNAL_API.LIDCOUNCIL_StartRaidTestTrace_Impl = StartTrace
INTERNAL_API.LIDCOUNCIL_StopRaidTestTrace_Impl = StopTrace
INTERNAL_API.LIDCOUNCIL_ClearRaidTestTrace_Impl = ClearTrace
INTERNAL_API.LIDCOUNCIL_AddRaidTestTraceMarker_Impl = AddMarker
INTERNAL_API.LIDCOUNCIL_GetRaidTestTraceStatus_Impl = GetStatus
INTERNAL_API.LIDCOUNCIL_BuildRaidTestTraceReport_Impl = BuildReport
INTERNAL_API.LIDCOUNCIL_RecordRaidTestTraceEvent_Impl = RecordEvent
INTERNAL_API.LIDCOUNCIL_BeginRaidTestTracePhase_Impl = BeginPhase
INTERNAL_API.LIDCOUNCIL_EndRaidTestTracePhase_Impl = EndPhase
INTERNAL_API.LIDCOUNCIL_RecordRaidTestTracePerformance_Impl = RecordPerformance
INTERNAL_API.LIDCOUNCIL_GetRaidTestTraceContract_Impl = GetContract
