export function JobStatusPanel({ job }) {
  const percent = Math.round(job?.progress?.percent || 0);
  const transfer = transferStats(job);

  return (
    <section className="min-w-0 overflow-hidden rounded-md border border-zinc-800 bg-zinc-900/70">
      <div className="flex items-center justify-between border-b border-zinc-800 px-4 py-3">
        <h2 className="text-sm font-semibold">Job Status</h2>
        <span className={`rounded-md border px-2 py-1 text-xs ${statusClass(job?.status)}`}>
          {job?.status || 'idle'}
        </span>
      </div>
      <div className="grid min-w-0 gap-4 p-4 lg:grid-cols-[280px_minmax(0,1fr)]">
        <dl className="space-y-3 text-sm">
          <Info label="Type" value={job?.type || '-'} />
          <Info label="Current Step" value={job?.currentStep || 'No active job'} />
          <Info label="Progress" value={job ? `${percent}%` : '-'} />
          <Info label="Transferred" value={transfer.transferred} />
          <Info label="Rate" value={transfer.rate} />
          <Info label="ETA" value={transfer.eta} />
          <Info label="Started" value={formatTime(job?.startedAt)} />
          <Info label="Finished" value={formatTime(job?.finishedAt)} />
          {job?.error ? <Info label="Error" value={job.error} tone="text-red-300" /> : null}
        </dl>
        <div className="min-w-0 space-y-3">
          <div className="rounded-md border border-zinc-800 bg-zinc-950 p-3">
            <div className="mb-2 flex items-center justify-between gap-3 text-xs text-zinc-400">
              <span className="min-w-0 truncate">{job?.progress?.detail || job?.currentStep || 'No active job'}</span>
              <span className="font-mono text-zinc-300">{job ? `${percent}%` : '-'}</span>
            </div>
            <div className="h-2 overflow-hidden rounded-md bg-zinc-800">
              <div className="h-full bg-cyan-400 transition-all" style={{ width: `${job ? percent : 0}%` }} />
            </div>
            {job ? (
              <div className="mt-3 grid gap-2 text-xs text-zinc-500 sm:grid-cols-3">
                <Metric label="Transferred" value={transfer.transferred} />
                <Metric label="Rate" value={transfer.rate} />
                <Metric label="ETA" value={transfer.eta} />
              </div>
            ) : null}
          </div>
          <pre className="max-h-80 max-w-full overflow-auto rounded-md border border-zinc-800 bg-zinc-950 p-3 text-xs leading-5 text-zinc-300">
            {(job?.logs || ['No logs yet.']).join('\n')}
          </pre>
        </div>
      </div>
    </section>
  );
}

function Metric({ label, value }) {
  return (
    <div className="min-w-0">
      <div className="uppercase tracking-wide">{label}</div>
      <div className="mt-1 truncate font-mono text-zinc-300">{value}</div>
    </div>
  );
}

function Info({ label, value, tone = 'text-zinc-300' }) {
  return (
    <div>
      <dt className="text-xs uppercase tracking-wide text-zinc-500">{label}</dt>
      <dd className={`mt-1 break-words ${tone}`}>{value}</dd>
    </div>
  );
}

function transferStats(job) {
  const currentBytes = Number(job?.progress?.currentBytes || 0);
  const totalBytes = Number(job?.progress?.totalBytes || 0);
  const startedAt = job?.startedAt ? new Date(job.startedAt).getTime() : 0;
  const finishedAt = job?.finishedAt ? new Date(job.finishedAt).getTime() : Date.now();
  const elapsedSeconds = startedAt ? Math.max(1, (finishedAt - startedAt) / 1000) : 0;
  const bytesPerSecond = currentBytes && elapsedSeconds ? currentBytes / elapsedSeconds : 0;
  const remainingBytes = totalBytes && currentBytes ? Math.max(0, totalBytes - currentBytes) : 0;
  const remainingSeconds = bytesPerSecond && remainingBytes ? remainingBytes / bytesPerSecond : 0;

  return {
    transferred: currentBytes && totalBytes
      ? `${formatBytes(currentBytes)} / ${formatBytes(totalBytes)}`
      : currentBytes
        ? formatBytes(currentBytes)
        : '-',
    rate: bytesPerSecond ? `${formatBytes(bytesPerSecond)}/s` : '-',
    eta: remainingSeconds ? formatDuration(remainingSeconds) : job?.status === 'success' ? 'Done' : '-',
  };
}

function formatBytes(value) {
  if (!value) return '-';
  const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
  let size = Number(value);
  let unitIndex = 0;
  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024;
    unitIndex += 1;
  }
  return `${size.toFixed(unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`;
}

function formatDuration(secondsValue) {
  const totalSeconds = Math.max(0, Math.round(secondsValue));
  const hours = Math.floor(totalSeconds / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  const seconds = totalSeconds % 60;
  if (hours) return `${hours}h ${minutes}m`;
  if (minutes) return `${minutes}m ${seconds}s`;
  return `${seconds}s`;
}

function statusClass(status) {
  if (status === 'success') return 'border-emerald-800 bg-emerald-950 text-emerald-300';
  if (status === 'failed') return 'border-red-800 bg-red-950 text-red-300';
  if (status === 'running' || status === 'queued') return 'border-cyan-800 bg-cyan-950 text-cyan-300';
  return 'border-zinc-800 bg-zinc-950 text-zinc-400';
}

function formatTime(value) {
  if (!value) return '-';
  return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'medium' }).format(new Date(value));
}
