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_ResolveOutboundDiagnosticState_Impl = function(diagnostics)
  diagnostics = type(diagnostics) == "table" and diagnostics or {}
  local lastKind = tostring(diagnostics.lastKind or "")
  local lastAt = math.max(0, tonumber(diagnostics.lastAt) or 0)
  local resolvedKind = tostring(diagnostics.lastResolvedKind or "")
  local resolvedAt = math.max(0, tonumber(diagnostics.lastResolvedAt) or 0)
  local failedTarget = string.lower(tostring(diagnostics.lastTarget or ""))
  local resolvedTarget = string.lower(tostring(diagnostics.lastResolvedTarget or ""))
  if lastKind == "" then
    return {
      state = "none",
      unresolved = false,
      recovered = false,
      currentHealthAffected = false,
      fallbackRecovered = false,
    }
  end
  local recovered = resolvedKind == lastKind
    and (failedTarget == "" or resolvedTarget == failedTarget)
    and resolvedAt > 0
    and resolvedAt >= lastAt
  return {
    state = recovered and "recovered" or "unresolved",
    unresolved = not recovered,
    recovered = recovered,
    currentHealthAffected = not recovered,
    fallbackRecovered = recovered and tostring(diagnostics.lastCategory or "") == "payload_rejected",
  }
end

INTERNAL_API.LIDCOUNCIL_AppendOutboundDiagnosticStateValidationChecks_Impl = function(addCheck)
  if type(addCheck) ~= "function" then
    return
  end
  local resolve = INTERNAL_API.LIDCOUNCIL_ResolveOutboundDiagnosticState_Impl
  local function state(input)
    local result = resolve(input)
    return table.concat({
      tostring(result.state or ""),
      tostring(result.unresolved == true),
      tostring(result.recovered == true),
      tostring(result.currentHealthAffected == true),
      tostring(result.fallbackRecovered == true),
    }, "/")
  end
  addCheck("outbound diagnostic has neutral empty state", "none/false/false/false/false", state({}))
  addCheck("outbound diagnostic marks unresolved payload", "unresolved/true/false/true/false", state({
    lastCategory = "payload_rejected", lastKind = "PSTATE", lastAt = 10,
  }))
  addCheck("outbound diagnostic recognizes recovered fallback", "recovered/false/true/false/true", state({
    lastCategory = "payload_rejected", lastKind = "PSTATE", lastAt = 10, lastResolvedKind = "PSTATE", lastResolvedAt = 11,
  }))
  addCheck("outbound diagnostic rejects mismatched recovery opcode", "unresolved/true/false/true/false", state({
    lastCategory = "payload_rejected", lastKind = "PSTATE", lastAt = 10, lastResolvedKind = "PSUB_STATE", lastResolvedAt = 11,
  }))
  addCheck("outbound diagnostic rejects stale recovery timestamp", "unresolved/true/false/true/false", state({
    lastCategory = "payload_rejected", lastKind = "PSTATE", lastAt = 10, lastResolvedKind = "PSTATE", lastResolvedAt = 9,
  }))
  addCheck("outbound diagnostic rejects recovery for another target", "unresolved/true/false/true/false", state({
    lastCategory = "payload_rejected", lastKind = "PSTATE", lastTarget = "A-Realm", lastAt = 10,
    lastResolvedKind = "PSTATE", lastResolvedTarget = "B-Realm", lastResolvedAt = 11,
  }))
end

INTERNAL_API.LIDCOUNCIL_CreateOutboundDiagnosticsHelpers_Impl = function(deps)
  deps = type(deps) == "table" and deps or {}
  local stats = type(deps.Stats) == "table" and deps.Stats 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 (type(GetServerTime) == "function" and GetServerTime()) or (time and time() or 0)
  end
  local GetActiveSessionId = type(deps.GetActiveSessionId) == "function" and deps.GetActiveSessionId or function()
    return ""
  end
  local RecordOpcodeTelemetry = type(deps.RecordOpcodeTelemetry) == "function" and deps.RecordOpcodeTelemetry or function()
  end

  local function GetDiagnosticScope(metadata)
    metadata = type(metadata) == "table" and metadata or {}
    for _, fieldName in ipairs({
      "scope",
      "subdomainsPreview",
      "requestSubdomainsPreview",
      "domainsPreview",
      "requestDomainsPreview",
      "domain",
    }) do
      local value = TrimText(metadata[fieldName])
      if value ~= "" then
        return value
      end
    end
    for _, fieldName in ipairs({ "scopeSubdomains", "requestedSubdomains", "scopeDomains", "requestedDomains" }) do
      local values = type(metadata[fieldName]) == "table" and metadata[fieldName] or nil
      if values then
        for _, value in ipairs(values) do
          local text = TrimText(value)
          if text ~= "" then
            return text
          end
        end
      end
    end
    return ""
  end

  local function GetOutboundIssueDiagnosticsForSession(sessionId)
    local resolvedSessionId = TrimText(sessionId)
    local scopeKey = resolvedSessionId ~= "" and ("session:" .. string.lower(resolvedSessionId)) or "unscoped"
    local diagnosticsByScope = type(stats.outboundIssueDiagnosticsByScope) == "table"
      and stats.outboundIssueDiagnosticsByScope
      or {}
    local diagnostics = type(diagnosticsByScope[scopeKey]) == "table" and diagnosticsByScope[scopeKey] or {}
    local history = {}
    for _, entry in ipairs(type(diagnostics.history) == "table" and diagnostics.history or {}) do
      if type(entry) == "table" and #history < 8 then
        history[#history + 1] = {
          category = TrimText(entry.category),
          kind = TrimText(entry.kind),
          reason = TrimText(entry.reason),
          bytes = math.max(0, tonumber(entry.bytes) or 0),
          sessionId = TrimText(entry.sessionId),
          target = NormalizeCharacterKey(entry.target),
          scope = TrimText(entry.scope),
          transferId = TrimText(entry.transferId),
          lane = TrimText(entry.lane),
          mode = TrimText(entry.mode),
          transferKind = TrimText(entry.transferKind),
          at = math.max(0, tonumber(entry.at) or 0),
        }
      end
    end
    local result = {
      sessionId = resolvedSessionId,
      payloadRejectedTotal = math.max(0, tonumber(diagnostics.payloadRejectedTotal) or 0),
      apiFailureTotal = math.max(0, tonumber(diagnostics.apiFailureTotal) or 0),
      throttleExhaustedTotal = math.max(0, tonumber(diagnostics.throttleExhaustedTotal) or 0),
      lastCategory = TrimText(diagnostics.lastCategory),
      lastKind = TrimText(diagnostics.lastKind),
      lastReason = TrimText(diagnostics.lastReason),
      lastBytes = math.max(0, tonumber(diagnostics.lastBytes) or 0),
      lastAt = math.max(0, tonumber(diagnostics.lastAt) or 0),
      lastTarget = NormalizeCharacterKey(diagnostics.lastTarget),
      lastResolvedKind = TrimText(diagnostics.lastResolvedKind),
      lastResolvedTarget = NormalizeCharacterKey(diagnostics.lastResolvedTarget),
      lastResolvedAt = math.max(0, tonumber(diagnostics.lastResolvedAt) or 0),
      history = history,
    }
    local state = INTERNAL_API.LIDCOUNCIL_ResolveOutboundDiagnosticState_Impl(result)
    result.state = state.state
    result.unresolved = state.unresolved
    result.recovered = state.recovered
    result.currentHealthAffected = state.currentHealthAffected
    result.fallbackRecovered = state.fallbackRecovered
    return result
  end

  local function RecordOutboundFailureDiagnostic(category, kind, reason, payloadBytes, metadata)
    local resolvedCategory = TrimText(category)
    if resolvedCategory ~= "payload_rejected" and resolvedCategory ~= "api_failure" and resolvedCategory ~= "throttle_exhausted" then
      return false
    end
    local resolvedKind = TrimText(kind)
    local resolvedReason = TrimText(reason)
    local resolvedBytes = math.max(0, tonumber(payloadBytes) or 0)
    metadata = type(metadata) == "table" and metadata or {}
    local resolvedScope = GetDiagnosticScope(metadata)
    local resolvedTransferId = TrimText(metadata.transferId)
    local resolvedLane = TrimText(metadata.lane)
    local resolvedMode = TrimText(metadata.mode)
    local resolvedTransferKind = TrimText(metadata.transferKind)
    local resolvedSessionId = TrimText(metadata.sessionId)
    if resolvedSessionId == "" then
      resolvedSessionId = TrimText(GetActiveSessionId())
    end
    local scopeKey = resolvedSessionId ~= "" and ("session:" .. string.lower(resolvedSessionId)) or "unscoped"
    local diagnosticsByScope = type(stats.outboundIssueDiagnosticsByScope) == "table"
      and stats.outboundIssueDiagnosticsByScope
      or {}
    local scopeOrder = type(stats.outboundIssueScopeOrder) == "table" and stats.outboundIssueScopeOrder or {}
    local scopedDiagnostics = diagnosticsByScope[scopeKey]
    if type(scopedDiagnostics) ~= "table" then
      scopedDiagnostics = {
        sessionId = resolvedSessionId,
        payloadRejectedTotal = 0,
        apiFailureTotal = 0,
        throttleExhaustedTotal = 0,
        lastCategory = "",
        lastKind = "",
        lastReason = "",
        lastBytes = 0,
        lastAt = 0,
        lastTarget = "",
        lastResolvedKind = "",
        lastResolvedTarget = "",
        lastResolvedAt = 0,
        history = {},
      }
      diagnosticsByScope[scopeKey] = scopedDiagnostics
      table.insert(scopeOrder, 1, scopeKey)
      while #scopeOrder > 12 do
        diagnosticsByScope[table.remove(scopeOrder)] = nil
      end
      stats.outboundIssueDiagnosticsByScope = diagnosticsByScope
      stats.outboundIssueScopeOrder = scopeOrder
    end
    if resolvedCategory == "api_failure" then
      stats.apiFailureTotal = math.max(0, tonumber(stats.apiFailureTotal) or 0) + 1
      scopedDiagnostics.apiFailureTotal = math.max(0, tonumber(scopedDiagnostics.apiFailureTotal) or 0) + 1
    elseif resolvedCategory == "throttle_exhausted" then
      stats.throttleExhaustedTotal = math.max(0, tonumber(stats.throttleExhaustedTotal) or 0) + 1
      scopedDiagnostics.throttleExhaustedTotal = math.max(0, tonumber(scopedDiagnostics.throttleExhaustedTotal) or 0) + 1
    else
      scopedDiagnostics.payloadRejectedTotal = math.max(0, tonumber(scopedDiagnostics.payloadRejectedTotal) or 0) + 1
    end
    stats.lastOutboundIssueCategory = resolvedCategory
    stats.lastOutboundIssueKind = resolvedKind
    stats.lastOutboundIssueReason = resolvedReason
    stats.lastOutboundIssueBytes = resolvedBytes
    stats.lastOutboundIssueAt = GetNow()
    scopedDiagnostics.lastCategory = resolvedCategory
    scopedDiagnostics.lastKind = resolvedKind
    scopedDiagnostics.lastReason = resolvedReason
    scopedDiagnostics.lastBytes = resolvedBytes
    scopedDiagnostics.lastAt = stats.lastOutboundIssueAt
    scopedDiagnostics.lastTarget = NormalizeCharacterKey(metadata.target)
    scopedDiagnostics.lastResolvedKind = ""
    scopedDiagnostics.lastResolvedTarget = ""
    scopedDiagnostics.lastResolvedAt = 0

    local history = type(stats.outboundIssueHistory) == "table" and stats.outboundIssueHistory or {}
    table.insert(history, 1, {
      category = resolvedCategory,
      kind = resolvedKind,
      reason = resolvedReason,
      bytes = resolvedBytes,
      sessionId = TrimText(metadata.sessionId),
      target = NormalizeCharacterKey(metadata.target),
      scope = resolvedScope,
      transferId = resolvedTransferId,
      lane = resolvedLane,
      mode = resolvedMode,
      transferKind = resolvedTransferKind,
      at = stats.lastOutboundIssueAt,
    })
    while #history > 8 do
      table.remove(history)
    end
    stats.outboundIssueHistory = history
    local scopedHistory = type(scopedDiagnostics.history) == "table" and scopedDiagnostics.history or {}
    table.insert(scopedHistory, 1, {
      category = resolvedCategory,
      kind = resolvedKind,
      reason = resolvedReason,
      bytes = resolvedBytes,
      sessionId = resolvedSessionId,
      target = NormalizeCharacterKey(metadata.target),
      scope = resolvedScope,
      transferId = resolvedTransferId,
      lane = resolvedLane,
      mode = resolvedMode,
      transferKind = resolvedTransferKind,
      at = scopedDiagnostics.lastAt,
    })
    while #scopedHistory > 8 do
      table.remove(scopedHistory)
    end
    scopedDiagnostics.history = scopedHistory
    return true
  end

  local function RecordOutboundDiagnosticResolved(kind, metadata)
    local resolvedKind = TrimText(kind)
    if resolvedKind == "" then
      return false
    end
    metadata = type(metadata) == "table" and metadata or {}
    local resolvedSessionId = TrimText(metadata.sessionId)
    if resolvedSessionId == "" then
      resolvedSessionId = TrimText(GetActiveSessionId())
    end
    local scopeKey = resolvedSessionId ~= "" and ("session:" .. string.lower(resolvedSessionId)) or "unscoped"
    local diagnosticsByScope = type(stats.outboundIssueDiagnosticsByScope) == "table"
      and stats.outboundIssueDiagnosticsByScope
      or {}
    local scopedDiagnostics = diagnosticsByScope[scopeKey]
    if type(scopedDiagnostics) ~= "table" or TrimText(scopedDiagnostics.lastKind) ~= resolvedKind then
      return false
    end

    local issueTarget = NormalizeCharacterKey(scopedDiagnostics.lastTarget)
    local successTarget = NormalizeCharacterKey(metadata.target)
    if issueTarget ~= "" and string.lower(successTarget) ~= string.lower(issueTarget) then
      return false
    end

    -- Keep the failure in history, but mark it recovered only after the exact opcode succeeds.
    scopedDiagnostics.lastResolvedKind = resolvedKind
    scopedDiagnostics.lastResolvedTarget = successTarget
    scopedDiagnostics.lastResolvedAt = GetNow()
    return true
  end

  local function RecordOutboundPayloadReject(kind, reason, payloadBytes, metadata)
    local resolvedKind = TrimText(kind)
    local resolvedReason = TrimText(reason)
    local resolvedBytes = math.max(0, tonumber(payloadBytes) or 0)
    metadata = type(metadata) == "table" and metadata or {}
    stats.rejectedPayloadTotal = math.max(0, tonumber(stats.rejectedPayloadTotal) or 0) + 1
    stats.lastRejectedPayloadKind = resolvedKind
    stats.lastRejectedPayloadReason = resolvedReason
    stats.lastRejectedPayloadBytes = resolvedBytes
    stats.lastRejectedPayloadAt = GetNow()
    RecordOpcodeTelemetry({ kind = resolvedKind, metadata = metadata }, "payload_rejected", resolvedBytes)
    RecordOutboundFailureDiagnostic("payload_rejected", resolvedKind, resolvedReason, resolvedBytes, metadata)

    local history = type(stats.payloadRejectHistory) == "table" and stats.payloadRejectHistory or {}
    table.insert(history, 1, {
      kind = resolvedKind,
      reason = resolvedReason,
      bytes = resolvedBytes,
      sessionId = TrimText(metadata.sessionId),
      target = NormalizeCharacterKey(metadata.target),
      at = stats.lastRejectedPayloadAt,
    })
    while #history > 8 do
      table.remove(history)
    end
    stats.payloadRejectHistory = history
  end

  return {
    GetOutboundIssueDiagnosticsForSession = GetOutboundIssueDiagnosticsForSession,
    RecordOutboundFailureDiagnostic = RecordOutboundFailureDiagnostic,
    RecordOutboundPayloadReject = RecordOutboundPayloadReject,
    RecordOutboundDiagnosticResolved = RecordOutboundDiagnosticResolved,
  }
end
