import type {
  ActivityActor,
  ActivityCategory,
  ActivityEvent,
  ActivitySeverity,
} from '@overdeck/activity-contract'

export const OBSERVABILITY_REPORT_SCHEMA_VERSION = 1 as const

export type ReportCoverageStatus = 'complete' | 'partial' | 'stale' | 'unavailable'
export type ReportSourceStatus = 'ok' | 'absent' | 'error' | 'stale'
export type ReportMetricUnit = 'count' | 'percent' | 'milliseconds' | 'tokens' | 'currency'

export interface ObservabilityReportQuery {
  from: string
  to: string
  timezone: string
  projects?: string[]
  sources?: string[]
  severity?: ActivitySeverity
  q?: string
}

export interface ReportCoverageGap {
  domain: 'activity' | 'execution' | 'reliability' | 'capacity' | 'history' | 'lineage'
  metric?: string
  sourceId?: string
  from?: string
  to?: string
  reason: string
}

export interface ReportSourceCoverage {
  id: string
  label: string
  category: ActivityCategory
  authority: 'authoritative' | 'derived'
  status: ReportSourceStatus
  storage: string
  retention?: string
  queryBounds: string
  coverageFrom?: string
  earliest?: string
  latest?: string
  matchingRecords: number
  retainedRecords: number
  skipped: number
  reason?: string
  href: string
}

export interface ReportCoverage {
  status: ReportCoverageStatus
  from: string
  to: string
  generatedAt: string
  sources: ReportSourceCoverage[]
  gaps: ReportCoverageGap[]
}

export interface ReportEvidenceQuery {
  sourceId: string
  from: string
  to: string
  recordId?: string
  severity?: ActivitySeverity
  q?: string
}

export interface ReportMetric {
  id: 'recorded-events' | 'failures' | 'active-sources' | 'source-problems'
  label: string
  value: number | null
  unit: ReportMetricUnit
  numerator?: number
  denominator?: number
  coverage: ReportCoverageStatus
  evidenceQuery?: ReportEvidenceQuery
}

export interface ReportSeriesGap {
  from: string
  to: string
  reason: string
}

export interface ReportSeries {
  id: 'activity-volume'
  label: string
  unit: 'count'
  coverage: ReportCoverageStatus
  points: Array<{ ts: string; value: number }>
  gaps: ReportSeriesGap[]
}

export interface ReportCategoryBreakdown {
  category: ActivityCategory
  count: number
}

export interface ReportActivityRecord {
  id: string
  ts: string
  kind: 'event'
  title: string
  category: ActivityCategory
  severity: ActivitySeverity
  actor: ActivityActor
  sourceId: string
  project?: string
  host?: string
  runtime?: string
  session?: string
  account?: string
  durationMs?: number
  result?: ActivityEvent['result']
  evidenceQuery: ReportEvidenceQuery
}

export interface ReportSourceProblem {
  id: string
  kind: 'source-error' | 'skipped-records'
  title: string
  sourceId: string
  severity: 'warn' | 'error'
  count?: number
  reason: string
  evidenceQuery: ReportEvidenceQuery
}

export type ReportAttentionRecord = ReportActivityRecord | ReportSourceProblem

export interface ActivityReportSection {
  kind: 'activity'
  status: ReportCoverageStatus
  title: 'Activity and source trust'
  metrics: ReportMetric[]
  series: ReportSeries[]
  categoryBreakdown: ReportCategoryBreakdown[]
  attention: ReportAttentionRecord[]
  sources: ReportSourceCoverage[]
  truncated: boolean
  errors: string[]
}

export interface ExecutionMetric extends Omit<ReportMetric, 'id'> {
  id: 'requests' | 'shipped-requests' | 'factory-runs' | 'failed-runs'
}

export interface ReportCountBreakdown {
  key: string
  label: string
  count: number
}

export interface ExecutionDurationPoint {
  ts: string
  value: number
  runId: string
}

export interface ExecutionPhaseSummary {
  label: string
  status: string
  durationMs: number | null
  attempts: number | null
  retries: number | null
  gatePassed: number
  gateFailed: number
  toolCalls: number
}

export interface ExecutionRunRecord {
  id: string
  label: string
  project?: string
  status: string
  outcome: 'succeeded' | 'failed' | 'running' | 'cancelled' | 'unknown'
  startedAt?: string
  endedAt?: string
  durationMs: number | null
  attempts: number
  retries: number
  failedGates: number
  toolCalls: number
  changedFiles: number
  insertions: number | null
  deletions: number | null
  models: string[]
  accounts: string[]
  sessions: string[]
  hosts: string[]
  phases: ExecutionPhaseSummary[]
  href: string
}

export interface ExecutionRequestRecord {
  id: string
  title: string
  project: string
  state: 'asked' | 'in_flight' | 'blocked_needs_owner' | 'orphaned' | 'shipped' | 'canceled'
  askedAt: string
  updatedAt: string
  worker?: string
  proofHref?: string
  requestHref: string
  correlation: 'linked' | 'unlinked' | 'missing-run'
  correlationReason?: string
  factoryRunId?: string
  factoryRunHref?: string
  delivery: {
    landedAt?: string
    deployedAt?: string
    proofRecorded: boolean
  }
}

export interface ExecutionReportSection {
  kind: 'execution'
  status: ReportCoverageStatus
  title: 'Work execution and delivery'
  metrics: ExecutionMetric[]
  requestStates: ReportCountBreakdown[]
  runOutcomes: ReportCountBreakdown[]
  failureBreakdown: ReportCountBreakdown[]
  durationSeries: ExecutionDurationPoint[]
  requests: ExecutionRequestRecord[]
  runs: ExecutionRunRecord[]
  gaps: ReportCoverageGap[]
  truncated: boolean
  errors: string[]
}

export interface ReliabilityMetric extends Omit<ReportMetric, 'id'> {
  id: 'incidents' | 'unresolved-incidents' | 'resolved-incidents' | 'recorded-failures'
}

export interface ReliabilityIncidentRecord {
  id: string
  title: string
  priority?: string
  incidentType?: string
  state: string
  createdAt?: string
  resolvedAt?: string
  durationMs: number | null
  ageMs: number | null
  failureClass?: string
  href: string
}

export interface ReliabilityFailureGroup {
  key: string
  label: string
  source: string
  category: ActivityCategory
  count: number
  firstAt: string
  latestAt: string
  project?: string
  host?: string
  service?: string
  href?: string
}

export interface ReliabilityDurationPoint {
  ts: string
  value: number
  incidentId: string
}

export interface ReliabilityReportSection {
  kind: 'reliability'
  status: ReportCoverageStatus
  title: 'Reliability and recovery'
  metrics: ReliabilityMetric[]
  incidents: ReliabilityIncidentRecord[]
  failureGroups: ReliabilityFailureGroup[]
  resolvedDurationSeries: ReliabilityDurationPoint[]
  projectBreakdown: ReportCountBreakdown[]
  hostBreakdown: ReportCountBreakdown[]
  serviceBreakdown: ReportCountBreakdown[]
  gaps: ReportCoverageGap[]
  truncated: boolean
  errors: string[]
}

export interface CapacityMetric extends Omit<ReportMetric, 'id'> {
  id: 'recorded-tokens' | 'recorded-cost' | 'active-sessions' | 'queued-builds'
}

export interface CapacityUsageBreakdown {
  key: string
  label: string
  tokens: number
  cost: number | null
  attempts: number
  unattributed: boolean
}

export interface CapacityAccountRecord {
  id: string
  label: string
  provider: string
  usedPercent: number | null
  status: string
  spendAmount: number | null
  spendLimit: number | null
  currency: string | null
  resetAt?: string
}

export interface CapacitySnapshot {
  activeSessions: number | null
  liveAgents: number | null
  runningBuilds: number | null
  queuedBuilds: number | null
  buildWaitP95Ms: number | null
}

export interface CapacityReportSection {
  kind: 'capacity'
  status: ReportCoverageStatus
  title: 'Capacity, accounts, and spend'
  metrics: CapacityMetric[]
  byModel: CapacityUsageBreakdown[]
  byAccount: CapacityUsageBreakdown[]
  byHost: CapacityUsageBreakdown[]
  byProject: CapacityUsageBreakdown[]
  accounts: CapacityAccountRecord[]
  snapshot: CapacitySnapshot
  costPerSucceededRun: number | null
  gaps: ReportCoverageGap[]
  truncated: boolean
  errors: string[]
}

export interface ReportBucketCoverage {
  status: ReportCoverageStatus
  key: string
  gaps: ReportCoverageGap[]
}

export interface ReportBucket {
  bucketStart: string
  bucketEnd: string
  metricKey: string
  metricVersion: number
  label: string
  unit: ReportMetricUnit
  dimensionKey: string
  value: number
  coverage: ReportBucketCoverage
  sourceWatermark: Record<string, string | null>
  generatedAt: string
  backfilled: boolean
}

export interface HistoricalMetric {
  key: string
  label: string
  unit: ReportMetricUnit
  metricVersion: number
  current: number | null
  previous: number | null
  delta: number | null
  direction: 'up' | 'down' | 'flat' | 'unknown'
  coverage: ReportCoverageStatus
  comparisonCompatible: boolean
  comparisonReason?: string
}

export interface HistoricalSeries {
  key: string
  label: string
  unit: ReportMetricUnit
  metricVersion: number
  points: Array<{ ts: string; value: number }>
  gaps: ReportSeriesGap[]
}

export interface HistoryReportSection {
  kind: 'history'
  status: ReportCoverageStatus
  title: 'Durable history and comparison'
  bucketHours: 1
  rangeDays: number
  retentionDays: number
  earliestAvailable?: string
  metrics: HistoricalMetric[]
  series: HistoricalSeries[]
  gaps: ReportCoverageGap[]
  quarantinedRows: number
  errors: string[]
}

export interface LineageEvidenceReference {
  source: 'request-registry' | 'factory-run' | 'request-evidence'
  recordId: string
  href: string
}

export interface LineageStage {
  kind: 'request' | 'run' | 'gate' | 'change' | 'land' | 'deploy' | 'proof'
  label: string
  status: 'recorded' | 'missing' | 'failed'
  detail: string
  recordedAt?: string
  evidence?: LineageEvidenceReference
}

export interface LineageRecord {
  requestId: string
  title: string
  project: string
  complete: boolean
  stages: LineageStage[]
  gaps: ReportCoverageGap[]
}

export interface LineageReportSection {
  kind: 'lineage'
  status: ReportCoverageStatus
  title: 'Delivery lineage'
  lineages: LineageRecord[]
  gaps: ReportCoverageGap[]
  truncated: boolean
  errors: string[]
}

export type ReportSection = ActivityReportSection | ExecutionReportSection | ReliabilityReportSection | CapacityReportSection | HistoryReportSection | LineageReportSection

export interface ObservabilityReport {
  schemaVersion: typeof OBSERVABILITY_REPORT_SCHEMA_VERSION
  query: ObservabilityReportQuery
  generatedAt: string
  coverage: ReportCoverage
  sections: ReportSection[]
  filters: {
    projects: string[]
    sources: Array<{ id: string; label: string }>
  }
}

export const REQUEST_STORY_SCHEMA_VERSION = 1 as const

export type RequestStoryCoverageStatus = 'complete' | 'partial' | 'unavailable' | 'stale' | 'pending_delivery'

export type RequestEventKind =
  | 'intake'
  | 'claimed'
  | 'owner_answer'
  | 'state_transition'
  | 'progress'
  | 'recovery_required'
  | 'run_linked'
  | 'phase_started'
  | 'phase_finished'
  | 'retry'
  | 'gate_result'
  | 'tool_result'
  | 'change_recorded'
  | 'land_submitted'
  | 'land_result'
  | 'deploy_started'
  | 'deploy_result'
  | 'proof_recorded'
  | 'failure'
  | 'legacy_receipt'
  | 'legacy_transition'

export interface RequestStoryActor {
  type: 'owner' | 'agent' | 'machinery' | 'unknown'
  id?: string
  displayName?: string
}

export interface RequestStoryEvent {
  id: string
  requestId: string
  kind: RequestEventKind
  occurredAt: string
  recordedAt: string
  summary: string
  actor: RequestStoryActor
  sessionId?: string
  hostId?: string
  accountId?: string
  sourceId: string
  sourceEventId: string
  producerId: string
  sourceRecordId?: string
  payload: Record<string, unknown>
  legacy: boolean
}

export type RequestEvidenceLinkKind =
  | 'factory_run'
  | 'phase'
  | 'gate'
  | 'tool'
  | 'change'
  | 'log'
  | 'branch'
  | 'land_submission'
  | 'commit'
  | 'deployment'
  | 'proof'

export interface RequestStoryEvidenceLink {
  kind: RequestEvidenceLinkKind
  targetSource: string
  targetId: string
  occurredAt: string
  sourceId: string
  sourceEventId: string
  ownerUrl?: string
  metadata: Record<string, unknown>
}

export interface RequestDeliveryLineageSelection {
  branch?: RequestStoryEvidenceLink
  submission?: RequestStoryEvidenceLink
  commit?: RequestStoryEvidenceLink
  deployment?: RequestStoryEvidenceLink
  proof?: RequestStoryEvidenceLink
  complete: boolean
}

function latestRequestEvidenceLink(
  links: RequestStoryEvidenceLink[],
  kind: RequestEvidenceLinkKind,
): RequestStoryEvidenceLink | undefined {
  return links.filter((link) => link.kind === kind)
    .sort((left, right) => right.occurredAt.localeCompare(left.occurredAt))[0]
}

export function selectRequestDeliveryLineage(links: RequestStoryEvidenceLink[]): RequestDeliveryLineageSelection {
  const commit = latestRequestEvidenceLink(links, 'commit')
  const resultSubmission = commit
    ? links.find((link) => link.kind === 'land_submission' && link.sourceEventId === commit.sourceEventId)
    : undefined
  const ticketSubmissions = resultSubmission
    ? links.filter((link) => link.kind === 'land_submission' && link.targetId === resultSubmission.targetId)
    : []
  const submission = ticketSubmissions
    .filter((candidate) => links.some((link) => link.kind === 'branch' && link.sourceEventId === candidate.sourceEventId))
    .sort((left, right) => left.occurredAt.localeCompare(right.occurredAt))[0]
    ?? resultSubmission
    ?? latestRequestEvidenceLink(links, 'land_submission')
  const branch = submission
    ? links.find((link) => link.kind === 'branch' && link.sourceEventId === submission.sourceEventId)
    : undefined
  const latestDeployment = latestRequestEvidenceLink(links, 'deployment')
  const deployment = latestDeployment
    && typeof latestDeployment.metadata.status === 'string'
    && typeof latestDeployment.metadata.readiness === 'string'
    ? latestDeployment
    : undefined
  const latestProof = latestRequestEvidenceLink(links, 'proof')
  const proof = latestProof && typeof latestProof.metadata.result === 'string' ? latestProof : undefined
  const release = commit?.targetId
  return {
    ...(branch ? { branch } : {}),
    ...(submission ? { submission } : {}),
    ...(commit ? { commit } : {}),
    ...(deployment ? { deployment } : {}),
    ...(proof ? { proof } : {}),
    complete: Boolean(
      branch && submission && commit && deployment && proof && release
      && deployment.metadata.release === release
      && proof.metadata.release === release,
    ),
  }
}

export type RequestEvidenceAttachmentMediaType = 'text/plain' | 'text/x-diff' | 'application/json'

export interface RequestEvidenceAttachmentV1 {
  digest: string
  contentBase64: string
  byteCount: number
  mediaType: RequestEvidenceAttachmentMediaType
  redactionStatus: 'redacted' | 'not_required'
  truncated: boolean
  originalByteCount?: number
}

export interface RequestStoryAttachment {
  digest: string
  byteCount: number
  mediaType: RequestEvidenceAttachmentMediaType
  redactionStatus: 'redacted' | 'not_required'
  truncated: boolean
  originalByteCount?: number
  status: 'available' | 'expired' | 'corrupt'
  url?: string
}

export interface RequestStoryCoverage {
  fact: 'original_request' | 'activity' | 'activity_delivery' | 'work_evidence' | 'delivery_evidence'
  status: RequestStoryCoverageStatus
  sourceId: string
  reason?: string
}

export type RequestEvidenceEventKind = Exclude<RequestEventKind, 'legacy_receipt' | 'legacy_transition'>

export interface RequestEvidenceEnvelopeV1 {
  schemaVersion: 1
  requestId: string
  sourceId: string
  sourceEventId: string
  producerId: string
  occurredAt: string
  event: {
    kind: RequestEvidenceEventKind
    summary: string
    actor: RequestStoryActor
    sessionId?: string
    hostId?: string
    accountId?: string
    payload: Record<string, unknown>
  }
  createRequest?: {
    title: string
    project: string
    priority: string
    origin: 'owner' | 'agent-incident' | 'agent-judgement'
    originalBody: string
    originalBodyFormat: 'plain_text' | 'markdown'
    workKey?: string
    detail?: string
    sessionName?: string
    sessionId?: string
  }
  projection?: {
    expectedState: string
    state: string
    worker?: string | null
    detail?: string | null
    sessionName?: string | null
    sessionId?: string | null
  }
  links?: Array<{
    kind: RequestEvidenceLinkKind
    targetSource: string
    targetId: string
    ownerUrl?: string
    metadata?: Record<string, unknown>
  }>
  attachments?: RequestEvidenceAttachmentV1[]
}

export interface RequestEvidenceSourceHealthV1 {
  schemaVersion: 1
  requestId: string
  sourceId: string
  producerId: string
  reportedAt: string
  queueCount: number
  oldestQueuedAt: string | null
  quarantineCount: number
  lastAcknowledgedAt: string | null
}

export interface RequestEvidenceAcknowledgementV1 {
  requestId: string
  sourceId: string
  sourceEventId: string
  replayed: boolean
}

export interface RequestStoryV1 {
  schemaVersion: typeof REQUEST_STORY_SCHEMA_VERSION
  requestId: string
  title: string
  project: string
  state: string
  priority: string
  askedAt: string
  updatedAt: string
  originalRequest: {
    body: string | null
    format: 'plain_text' | 'markdown' | null
    source: string | null
  }
  events: RequestStoryEvent[]
  links: RequestStoryEvidenceLink[]
  attachments: RequestStoryAttachment[]
  coverage: RequestStoryCoverage[]
}
