import { DetailDrawer, KvPanel, SectionCard, SwimlaneTrace, formatDurationMs, type TraceLane } from '@overdeck/deck-ui'
import { useId, useState, type JSX } from 'react'
import type { FactoryPhaseView, FactoryRunView } from '../../lib/factory-types'
import { FactoryEventTable } from './FactoryEventTable'
import { FactoryAttemptTable, FactoryGateTable } from './FactoryTraceTables'
import {
  displayStatus,
  displayText,
  formatAbsoluteTimestamp,
  hostsForAttempts,
  isFactoryRunning,
  parseTimestampMs,
} from './factory-helpers'

type Zoom = 'fit' | 'hour' | 'live'

function phaseDurationMs(phase: FactoryPhaseView, nowMs: number): number | null {
  if (phase.durationMs !== null && phase.durationMs !== undefined) return phase.durationMs
  const startedMs = parseTimestampMs(phase.startedAt)
  const endedMs = parseTimestampMs(phase.endedAt)
  if (startedMs === null) return null
  if (endedMs !== null && endedMs >= startedMs) return endedMs - startedMs
  if (isFactoryRunning(phase.status) && nowMs >= startedMs) return nowMs - startedMs
  return null
}

function timelineLanes(phases: FactoryPhaseView[], nowMs: number): TraceLane[] {
  return [...phases]
    .sort((left, right) => (left.seq ?? Number.MAX_SAFE_INTEGER) - (right.seq ?? Number.MAX_SAFE_INTEGER))
    .map((phase) => {
      const startedMs = parseTimestampMs(phase.startedAt)
      const durationMs = phaseDurationMs(phase, nowMs)
      return {
        taskId: phase.phaseId,
        name: [phase.name, phase.owner].filter(Boolean).join(' · ') || '—',
        wave: phase.seq,
        segments: startedMs === null || durationMs === null ? [] : [{
          t0: startedMs,
          durMs: durationMs,
          cat: displayStatus(phase.status),
          status: displayStatus(phase.status),
          agentId: phase.owner ?? undefined,
          running: isFactoryRunning(phase.status),
          note: phase.description ?? phase.error ?? undefined,
        }],
      }
    })
}

export function FactoryTimeline({ run }: { run: FactoryRunView }): JSX.Element {
  const [zoom, setZoom] = useState<Zoom>('fit')
  const [selectedPhaseId, setSelectedPhaseId] = useState<string | null>(null)
  const titleId = useId()
  const nowMs = Date.now()
  const lanes = timelineLanes(run.phases, nowMs)
  const selectedPhase = run.phases.find((phase) => phase.phaseId === selectedPhaseId) ?? null
  const selectedEvents = run.events.filter((event) => event.phaseId === selectedPhaseId)
  const selectedAttempts = (run.attempts ?? []).filter((attempt) => attempt.phaseId === selectedPhaseId)
  const selectedGates = (run.gates ?? []).filter((gate) => gate.phaseId === selectedPhaseId)
  const unavailable = new Set(run.unavailableTables ?? [])
  const selectedDurationMs = selectedPhase ? phaseDurationMs(selectedPhase, nowMs) : null

  return (
    <>
      <SwimlaneTrace
        lanes={lanes}
        nowMs={isFactoryRunning(run.status) ? nowMs : null}
        bands={[]}
        zoom={zoom}
        onZoom={setZoom}
        onSegmentClick={(laneId) => setSelectedPhaseId(laneId)}
        title="Phase timeline"
        description="one row per phase · real wall-clock position and duration"
        showGroups={false}
      />
      {selectedPhase ? (
        <DetailDrawer eyebrow="Phase detail" title={displayText(selectedPhase.name, selectedPhase.phaseId)} titleId={titleId} onClose={() => setSelectedPhaseId(null)}>
          <div className="mt-4 flex flex-col gap-3">
            <KvPanel rows={[
              { label: 'phase id', value: selectedPhase.phaseId },
              { label: 'kind', value: displayText(selectedPhase.kind) },
              { label: 'owner', value: displayText(selectedPhase.owner) },
              { label: 'description', value: displayText(selectedPhase.description) },
              { label: 'status', value: displayStatus(selectedPhase.status) },
              { label: 'host', value: hostsForAttempts(selectedAttempts) },
              { label: 'started', value: formatAbsoluteTimestamp(selectedPhase.startedAt) },
              { label: 'ended', value: formatAbsoluteTimestamp(selectedPhase.endedAt) },
              { label: 'duration', value: selectedDurationMs === null ? '—' : formatDurationMs(selectedDurationMs) },
              { label: 'attempt', value: selectedPhase.attempt === null ? '—' : String(selectedPhase.attempt) },
              { label: 'retries', value: selectedPhase.retries === null ? '—' : String(selectedPhase.retries) },
              { label: 'error', value: displayText(selectedPhase.error) },
            ]} />
            <SectionCard title="Events">
              {selectedEvents.length > 0 ? <FactoryEventTable events={selectedEvents} runStartedAt={run.startedAt} phases={run.phases} /> : <p className="text-xs text-fg-muted">No events recorded for this phase.</p>}
            </SectionCard>
            <SectionCard title="Agent attempts">
              {unavailable.has('agent_attempts') ? <p className="text-xs text-fg-muted">Not recorded by this run&apos;s factory version.</p> : selectedAttempts.length > 0 ? <FactoryAttemptTable attempts={selectedAttempts} /> : <p className="text-xs text-fg-muted">No agent attempts recorded for this phase.</p>}
            </SectionCard>
            <SectionCard title="Gates">
              {unavailable.has('gate_results') ? <p className="text-xs text-fg-muted">Not recorded by this run&apos;s factory version.</p> : selectedGates.length > 0 ? <FactoryGateTable gates={selectedGates} /> : <p className="text-xs text-fg-muted">No gates recorded for this phase.</p>}
            </SectionCard>
          </div>
        </DetailDrawer>
      ) : null}
    </>
  )
}
