import process from 'node:process'
import { Command } from 'commander'
import { logger } from '../../core/logger.ts'
import { DAEMON_BASE_URL } from '../../core/paths.ts'
import {
  formatCost,
  formatDuration,
  formatTable,
  formatTime,
  formatTokenBuckets,
  shortId,
} from '../tui/table.ts'

type TaskOptions = {
  json: boolean
}

type ThreadListItem = {
  id: string
  agent: string
  title: string | null
  startedAt: number
  endedAt: number | null
  durMs: number | null
  runCount: number
  actionCount: number
  costUsd: number
  tokensIn: number | null
  tokensOut: number | null
  cacheReadTokens: number | null
  cacheWriteTokens: number | null
  outcomeValueUsd: number
  thomas: number
}

type RunListItem = {
  id: string
  status: string
  startedAt: number
  durMs: number | null
  costUsd: number
  tokensIn: number | null
  tokensOut: number | null
  cacheReadTokens: number | null
  cacheWriteTokens: number | null
  actionCount: number
}

type ThreadDetail = {
  thread: ThreadListItem
  runs: RunListItem[]
}

export const taskCommand = new Command('task')
  .description('Show a task: its rollup and the runs that make it up.')
  .argument('<task-id>', 'Task (thread) ID — full or short prefix, from `openthomas tasks`.')
  .option('--json', 'Output normalized JSON.', false)
  .action(async (taskId: string, options: TaskOptions) => {
    const url = `${DAEMON_BASE_URL}/api/threads/${encodeURIComponent(taskId)}`
    let res: Response
    try {
      res = await fetch(url, { signal: AbortSignal.timeout(3000) })
    } catch {
      logger.print('Daemon not reachable. Start it with `openthomas wire` or `openthomas daemon`.')
      process.exitCode = 1
      return
    }
    if (res.status === 404) {
      logger.print(`Task not found: ${taskId}`)
      process.exitCode = 1
      return
    }
    if (!res.ok) {
      logger.print(`Daemon error: HTTP ${res.status}`)
      process.exitCode = 1
      return
    }

    const detail = (await res.json()) as ThreadDetail

    if (options.json) {
      process.stdout.write(`${JSON.stringify(detail, null, 2)}\n`)
      return
    }

    const t = detail.thread
    logger.print(`Task   ${t.id}`)
    if (t.title) logger.print(`Title  ${t.title}`)
    logger.print(`Agent  ${t.agent}`)
    logger.print(`When   ${formatTime(t.startedAt)}  (${formatDuration(t.durMs)})`)
    logger.print(`Runs   ${t.runCount}  ·  ${t.actionCount} actions`)
    logger.print(
      `Spend  ${formatCost(t.costUsd)} → ${formatCost(t.outcomeValueUsd)} value` +
        `  (T=${formatThomas(t.thomas)})`,
    )
    logger.print('')

    if (detail.runs.length === 0) {
      logger.print('(no runs)')
      return
    }

    const rows = detail.runs.map((r) => [
      shortId(r.id),
      formatTime(r.startedAt),
      r.status,
      formatDuration(r.durMs),
      String(r.actionCount),
      formatCost(r.costUsd),
      formatTokenBuckets(r.tokensIn, r.tokensOut, r.cacheReadTokens, r.cacheWriteTokens),
    ])
    logger.print(
      formatTable(['RUN', 'STARTED', 'STATUS', 'DUR', 'ACT', 'COST', 'CACHED/FRESH/OUT'], rows),
    )
    logger.print('')
    logger.print('Drill into a run with `openthomas show <run-id>`.')
  })

function formatThomas(t: number): string {
  if (t === 0) return '0'
  if (t < 1) return t.toFixed(2)
  if (t < 100) return t.toFixed(1)
  return Math.round(t).toLocaleString()
}
