import { DataTable, withColumnResizing, withSearch, withSorting, type DataTableColumn } from './internal/DataTable'
import type { ClusterQueueModel, QueueTicket } from './offload-types'

export interface ClusterQueueProps { queue: ClusterQueueModel }
type QueueRow = QueueTicket | { wedge: true; host: string; detail: string }
function isWedge(row: QueueRow): row is Extract<QueueRow, { wedge: true }> { return 'wedge' in row }
function formatAge(seconds: number): string {
  if (seconds < 60) return `${Math.round(seconds)}s`
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m`
  const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60)
  return minutes > 0 ? `${hours}h${minutes.toString().padStart(2, '0')}m` : `${hours}h`
}
function ageBarWidth(ageSeconds: number, oldest: number): number { return oldest <= 0 ? 0 : Math.min(100, Math.round((ageSeconds / oldest) * 100)) }
function columns(oldest: number): DataTableColumn<QueueRow>[] { return [
  { id: 'position', header: '#', minWidth: 30, sortable: true, sortValue: (row) => isWedge(row) ? 0 : row.position, cell: (row) => <span className="font-mono text-[11px] tabular-nums text-fg-muted">{isWedge(row) ? '!' : row.position}</span> },
  { id: 'key', header: 'Key', minWidth: 84, sortable: true, sortValue: (row) => (isWedge(row) ? row.detail : row.key).toLowerCase(), searchValue: (row) => isWedge(row) ? row.detail : row.key, cell: (row) => isWedge(row) ? <span data-testid="cluster-queue-wedge" className="text-danger">dispatch to {row.host} wedged — {row.detail}</span> : <span className="font-mono text-[11px] text-fg-muted">{row.key}</span> },
  { id: 'repo', header: 'Repo', minWidth: 108, sortable: true, sortValue: (row) => (isWedge(row) ? '' : row.repo).toLowerCase(), searchValue: (row) => isWedge(row) ? '' : row.repo, cell: (row) => isWedge(row) ? '' : row.repo },
  { id: 'owner', header: 'Owner', minWidth: 64, sortable: true, sortValue: (row) => (isWedge(row) ? '' : row.owner.label ?? `${row.owner.pid}`).toLowerCase(), searchValue: (row) => isWedge(row) ? '' : row.owner.label ?? `${row.owner.pid}`, cell: (row) => isWedge(row) ? '' : <span className="font-mono text-[11px] text-fg-muted">{row.owner.label ?? `${row.owner.pid}`}</span> },
  { id: 'wait', header: 'Wait', minWidth: 96, sortable: true, sortValue: (row) => isWedge(row) ? 0 : row.enqueueAgeSeconds, cell: (row) => isWedge(row) ? '—' : <>{formatAge(row.enqueueAgeSeconds)}<div className="mt-1 h-1 w-[90px] rounded-sm bg-surface-raised"><i className="block h-full rounded-sm bg-warning" style={{ width: `${ageBarWidth(row.enqueueAgeSeconds, oldest)}%` }} /></div></> },
  { id: 'state', header: 'State', minWidth: 60, sortable: true, sortValue: (row) => (isWedge(row) ? 'reconcile' : row.state).toLowerCase(), searchValue: (row) => isWedge(row) ? 'reconcile' : row.state, cell: (row) => <span className="inline-flex items-center gap-1.5 whitespace-nowrap"><i className={`h-[7px] w-[7px] rounded-full ${isWedge(row) ? 'bg-danger' : 'bg-warning'}`} />{isWedge(row) ? 'reconcile' : row.state}</span> },
] }

export function ClusterQueue({ queue }: ClusterQueueProps) {
  const rows: QueueRow[] = queue.wedge ? [...queue.tickets, { wedge: true, ...queue.wedge }] : queue.tickets
  return <div data-testid="cluster-queue"><DataTable caption="Cluster queue" columns={columns(queue.oldestAgeSeconds)} rows={rows} getRowId={(row) => isWedge(row) ? `wedge-${row.host}` : row.key} capabilities={[withSorting(), withSearch({ label: 'Search cluster queue' }), withColumnResizing()]} /><div className="mt-2 text-[11px] text-fg-subtle" data-testid="cluster-queue-summary">one global FIFO · dispatch → {queue.dispatchTarget ?? '—'} · oldest {formatAge(queue.oldestAgeSeconds)}{queue.oldestAgeSeconds > queue.sloSeconds ? ' · SLO breached' : ''} · p95 {queue.p95AgeSeconds < 60 ? `${queue.p95AgeSeconds}s` : formatAge(queue.p95AgeSeconds)} · {queue.depth} waiting{queue.spill?.active ? ` · spill ${queue.spill.stale ? 'ON (stale)' : 'ON'}` : ''}</div></div>
}
