import { useQuery } from '@tanstack/react-query'
import { useState } from 'react'
import {
  DetailDrawer,
  KvPanel,
  StatusChip,
  TerminalView,
  formatDurationMs,
  formatRelativeTime,
  type KvRow,
  type TerminalInput,
} from '@overdeck/deck-ui'
import { fetchSessionScreen, postCollectorAction } from '../../lib/collector-client'
import {
  idleTime,
  isRunning,
  runningTime,
  sessionStateChip,
  type AgentSessionRow,
  type Elapsed,
} from '../../lib/session-types'
import { ResumeCommand } from './ResumeCommand'

const SCREEN_POLL_MS = 1_000

const ATTACH_HEADING: Record<string, string> = {
  tmux: 'Reopen from a terminal',
  ssh: 'Reopen on its host',
  resume: 'Resume from a terminal',
}

/** Frozen for a session that is no longer running — never a clock that keeps climbing. */
function duration(elapsed: Elapsed, nowMs: number): string {
  switch (elapsed.kind) {
    case 'ticking': return formatDurationMs(nowMs - elapsed.startAtMs)
    case 'static': return formatDurationMs(elapsed.ms)
    case 'lastSeen': return formatRelativeTime(elapsed.atMs, nowMs)
    default: return '—'
  }
}

function metaRows(row: AgentSessionRow): KvRow[] {
  const now = Date.now()
  const running = runningTime(row, now)
  const idle = idleTime(row, now)
  const rows: KvRow[] = [
    { label: 'CLI', value: row.cli },
    { label: 'Started by', value: row.launchedBy ?? 'not recorded' },
    { label: 'Launched by session', value: row.parent ?? '—' },
    { label: 'Host', value: row.host ?? 'not recorded' },
    { label: 'Project', value: row.project },
    { label: 'Branch', value: row.branch ?? '—' },
    { label: isRunning(row.state) ? 'Running for' : 'Ran for', value: duration(running, now) },
    { label: idle.kind === 'lastSeen' ? 'Last seen' : 'Idle for', value: duration(idle, now) },
    { label: 'Window', value: row.attached === null ? 'unknown' : row.attached ? 'attached' : 'none attached' },
    { label: 'Activity', value: row.activity ?? 'not recorded' },
    { label: 'PID', value: row.source.pid === null ? '—' : String(row.source.pid) },
    { label: 'Transcript', value: row.source.transcriptPath ?? '—' },
  ]
  if (row.finishReason) rows.push({ label: 'Ended because', value: row.finishReason })
  if (row.evidence) rows.push({ label: 'Classifier evidence', value: row.evidence })
  for (const [label, bad] of [['Run length problem', running], ['Idle time problem', idle]] as const) {
    if (bad.kind === 'unknown' && bad.problem) {
      rows.push({ label, value: bad.problem, intent: 'err' })
    }
  }
  return rows
}

export function SessionAttachDrawer({ row, onClose }: { row: AgentSessionRow; onClose(): void }) {
  const [busy, setBusy] = useState(false)
  const [sendError, setSendError] = useState<string | null>(null)
  const chip = sessionStateChip(row.ledgerState)

  const screenQuery = useQuery({
    queryKey: ['session-screen', row.id],
    queryFn: () => fetchSessionScreen(row.id),
    enabled: row.screenAttachable,
    refetchInterval: SCREEN_POLL_MS,
    refetchIntervalInBackground: false,
    retry: false,
  })

  async function send(input: TerminalInput): Promise<void> {
    setBusy(true)
    setSendError(null)
    try {
      await postCollectorAction('sessions.sendKeys', {
        id: row.id,
        ...(input.text !== undefined ? { text: input.text } : {}),
        ...(input.key !== undefined ? { key: input.key } : {}),
      })
      await screenQuery.refetch()
    } catch (error) {
      setSendError(error instanceof Error ? error.message : String(error))
    } finally {
      setBusy(false)
    }
  }

  const screenError = screenQuery.error instanceof Error ? screenQuery.error.message : null
  const responseError = screenQuery.data && !screenQuery.data.ok ? screenQuery.data.error ?? 'capture failed' : null
  const blocked = row.screenAttachable ? null : row.screenBlockedReason ?? 'the browser cannot render this session'
  const reason = blocked ?? responseError ?? screenError ?? undefined
  const state = blocked !== null
    ? (row.state === 'finished' ? 'ended' as const : 'unavailable' as const)
    : screenQuery.data?.ok
      ? 'attached' as const
      : screenQuery.isLoading
        ? 'connecting' as const
        : 'unavailable' as const
  const capturedAt = screenQuery.data?.ok ? Date.parse(screenQuery.data.capturedAt) : null

  return (
    <DetailDrawer
      eyebrow={row.project}
      title={
        <span className="flex items-center gap-2">
          {row.title ?? row.id}
          <StatusChip status={chip.status} label={chip.label} />
        </span>
      }
      titleId={`session-${row.id}`}
      onClose={onClose}
      draggable
      modal={false}
    >
      <div className="flex flex-col gap-3">
        {row.title ? <p className="text-[11px] text-fg-subtle">{row.id}</p> : null}
        <KvPanel rows={metaRows(row)} />

        <TerminalView
          screen={screenQuery.data?.ok ? screenQuery.data.screen : null}
          state={state}
          label={`session ${row.id}`}
          onSend={row.screenAttachable ? send : undefined}
          busy={busy}
          rows={22}
          {...(reason ? { reason } : {})}
          {...(capturedAt !== null && !Number.isNaN(capturedAt)
            ? { capturedNote: `screen captured ${formatRelativeTime(capturedAt)}` }
            : {})}
        />

        {sendError ? <p className="text-[11px] text-danger">{sendError}</p> : null}

        {row.attach.kind !== 'none' && row.attach.command ? (
          <ResumeCommand
            command={row.attach.command}
            cwd={row.source.worktree ?? row.source.cwd}
            heading={ATTACH_HEADING[row.attach.kind] ?? 'Reconnect from a terminal'}
            {...(row.attach.kind === 'resume' && !row.accountKnown
              ? { note: 'No account is recorded for this session, which the recorder means as the default account — this command is complete as written.' }
              : {})}
          />
        ) : (
          <p className="text-[11px] text-fg-muted">
            Cannot reconnect: {row.attach.reason ?? 'no reconnect path is known for this session'}.
          </p>
        )}
      </div>
    </DetailDrawer>
  )
}
