import {
  DataTable,
  withColumnResizing,
  withPagination,
  withSearch,
  withSorting,
  type DataTableColumn,
} from './internal/DataTable'
import { StatusDot, type StatusDotColor } from './internal/StatusDot'
import { formatRelativeTime } from './format'

export type BotStatus = 'live' | 'slow' | 'down' | 'idle'

export interface BotRow {
  id?: string
  name: string
  subtitle?: string
  status: BotStatus
  /** Overrides the default status label, e.g. "running · last call 2h ago". */
  statusDetail?: string
  messages24h: number | null
  messagesTotal?: number | null
  errors: number | null
  cost: number | null
  costTotal?: number | null
  /** Any fleet signal: poll, LLM call, or mirrored Telegram row. */
  lastActivityAt?: string | null
  /** Last mirrored Telegram row in D1 chat_messages only. */
  lastMessageAt?: string | null
}

export interface BotTableProps {
  bots: BotRow[]
  /** Overview cards hide low-priority columns; the /bots page shows every column. */
  density?: 'compact' | 'full'
}

const STATUS_DOT: Record<BotStatus, StatusDotColor> = {
  live: 'green',
  slow: 'amber',
  down: 'red',
  idle: 'muted',
}

const STATUS_SORT: Record<BotStatus, number> = {
  live: 4,
  slow: 3,
  idle: 2,
  down: 1,
}

function fmt(n: number | null, prefix = ''): string {
  return n === null ? '—' : `${prefix}${n}`
}

function timestampSort(iso: string | null | undefined): number {
  if (!iso) return -1
  const ms = Date.parse(iso)
  return Number.isFinite(ms) ? ms : -1
}

function relativeTimeCell(iso: string | null | undefined) {
  if (!iso) return '—'
  const ms = Date.parse(iso)
  if (!Number.isFinite(ms)) return '—'
  return <time dateTime={iso}>{formatRelativeTime(ms)}</time>
}

function costCell(cost24h: number | null, costTotal?: number | null): string {
  if (cost24h !== null && cost24h > 0) return `$${cost24h}`
  if (costTotal !== null && costTotal !== undefined && costTotal > 0) {
    return costTotal < 0.01 ? `$${costTotal.toFixed(4)} tot` : `$${costTotal} tot`
  }
  return '—'
}

function botSearchText(row: BotRow): string {
  return [row.name, row.subtitle, row.statusDetail, row.status].filter(Boolean).join(' ')
}

function nameCell(row: BotRow) {
  if (!row.subtitle) return <span className="font-medium">{row.name}</span>
  return (
    <span>
      <span className="block font-medium">{row.name}</span>
      <span className="block text-[11px] text-fg-muted">{row.subtitle}</span>
    </span>
  )
}

function statusCell(row: BotRow) {
  return <StatusDot color={STATUS_DOT[row.status]} label={row.statusDetail ?? row.status} />
}

function buildColumns(density: 'compact' | 'full'): Array<DataTableColumn<BotRow>> {
  const columns: Array<DataTableColumn<BotRow>> = [
    {
      id: 'name',
      header: 'Bot',
      sortable: true,
      resizable: true,
      sortValue: (row) => row.name,
      searchValue: botSearchText,
      cell: nameCell,
      minWidth: 140,
    },
    {
      id: 'status',
      header: 'Status',
      sortable: true,
      resizable: true,
      sortValue: (row) => STATUS_SORT[row.status],
      searchValue: (row) => row.statusDetail ?? row.status,
      cell: statusCell,
      minWidth: 160,
    },
    {
      id: 'messages',
      header: 'Msgs 24h',
      sortable: true,
      resizable: true,
      sortValue: (row) => row.messages24h ?? -1,
      searchValue: (row) => String(row.messages24h ?? ''),
      cell: (row) => <span className="tabular-nums">{fmt(row.messages24h)}</span>,
      minWidth: 88,
    },
  ]

  if (density === 'full') {
    columns.push(
      {
        id: 'total',
        header: 'Total',
        sortable: true,
        resizable: true,
        sortValue: (row) => row.messagesTotal ?? -1,
        searchValue: (row) => String(row.messagesTotal ?? ''),
        cell: (row) => <span className="tabular-nums">{fmt(row.messagesTotal ?? null)}</span>,
        minWidth: 72,
      },
    )
  }

  columns.push(
    {
      id: 'errors',
      header: density === 'full' ? 'Errors 24h' : 'Errors',
      sortable: true,
      resizable: true,
      sortValue: (row) => row.errors ?? -1,
      searchValue: (row) => String(row.errors ?? ''),
      cell: (row) => <span className="tabular-nums">{fmt(row.errors)}</span>,
      minWidth: 88,
    },
    {
      id: 'cost',
      header: density === 'full' ? 'Cost 24h' : 'Cost',
      sortable: true,
      resizable: true,
      sortValue: (row) => row.cost ?? row.costTotal ?? -1,
      searchValue: (row) => costCell(row.cost, row.costTotal),
      cell: (row) => (
        <span className="tabular-nums">
          {density === 'full' ? costCell(row.cost, row.costTotal) : fmt(row.cost, '$')}
        </span>
      ),
      minWidth: 88,
    },
  )

  if (density === 'full') {
    columns.push(
      {
        id: 'lastActive',
        header: 'Last active',
        sortable: true,
        resizable: true,
        sortValue: (row) => timestampSort(row.lastActivityAt),
        searchValue: (row) => row.lastActivityAt ?? '',
        cell: (row) => relativeTimeCell(row.lastActivityAt),
        minWidth: 104,
      },
      {
        id: 'lastMessage',
        header: 'Last message',
        sortable: true,
        resizable: true,
        sortValue: (row) => timestampSort(row.lastMessageAt),
        searchValue: (row) => row.lastMessageAt ?? '',
        cell: (row) => relativeTimeCell(row.lastMessageAt),
        minWidth: 104,
      },
    )
  }

  return columns
}

/** Botmaster per-bot status/traffic/cost table backed by platform DataTable. */
export function BotTable({ bots, density = 'compact' }: BotTableProps) {
  const compact = density === 'compact'
  const capabilities = compact
    ? [withSorting()]
    : [
        withSorting(),
        withSearch({ label: 'Filter bots' }),
        withColumnResizing(),
        withPagination({ pageSize: 20 }),
      ]

  return (
    <DataTable
      caption="Bots"
      columns={buildColumns(density)}
      rows={bots}
      getRowId={(row) => row.id ?? row.name}
      capabilities={capabilities}
      emptyState={<span className="text-fg-muted">No bots in the latest snapshot.</span>}
    />
  )
}
