import type { ReactNode } from 'react';
import type { Torrent } from '../shared';
import { Check, Copy } from 'lucide-react';
import { useState } from 'react';
import {
  formatDate,
  formatDuration,
  formatEta,
  formatPercent,
  formatRatio,
  formatSize,
  formatSpeed,
  PRIORITY_LABELS,
  statusLabel,
} from '../format';
import { copyToClipboard } from 'helpers/clipboard';

// The "what is this torrent" tab: transfer numbers, then the immutable facts from the metainfo.

type GeneralTabProps = { torrent: Torrent };

export const GeneralTab = ({ torrent: t }: GeneralTabProps) => (
  <div className="space-y-5 p-4">
    {t.error !== 0 && t.errorString && (
      <p className="rounded-lg bg-destructive/10 px-3 py-2 text-xs text-destructive">{t.errorString}</p>
    )}

    <Section title="Transfer">
      <Field label="Status" value={statusLabel(t)} />
      <Field label="Progress" value={formatPercent(t.percentDone)} />
      <Field label="Downloaded" value={formatSize(t.downloadedEver)} />
      <Field label="Uploaded" value={formatSize(t.uploadedEver)} />
      <Field label="Ratio" value={formatRatio(t.uploadRatio)} />
      <Field label="Remaining" value={formatSize(t.leftUntilDone)} />
      <Field label="Down speed" value={formatSpeed(t.rateDownload) || '—'} />
      <Field label="Up speed" value={formatSpeed(t.rateUpload) || '—'} />
      <Field label="ETA" value={t.percentDone >= 1 ? '—' : formatEta(t.eta)} />
      <Field label="Seeds / peers" value={`${t.peersSendingToUs} / ${t.peersGettingFromUs}`} />
      <Field label="Seeding time" value={formatDuration(t.secondsSeeding)} />
      {/* Corrupt bytes are re-downloaded silently, so this is the only place a failing disk or a bad peer
          shows up before the ratio quietly goes wrong. */}
      <Field label="Corrupt" value={t.corruptEver ? formatSize(t.corruptEver) : '—'} />
    </Section>

    <Section title="Dates">
      <Field label="Added" value={formatDate(t.addedDate)} />
      <Field label="Completed" value={formatDate(t.doneDate)} />
      <Field label="Last active" value={formatDate(t.activityDate)} />
      <Field label="Created" value={formatDate(t.dateCreated)} />
    </Section>

    <Section title="Torrent">
      <Field label="Total size" value={formatSize(t.totalSize)} />
      <Field label="Files" value={String(t['file-count'] ?? '—')} />
      <Field label="Pieces" value={`${t.pieceCount} × ${formatSize(t.pieceSize)}`} />
      <Field label="Privacy" value={t.isPrivate ? 'Private torrent' : 'Public torrent'} />
      <Field label="Priority" value={PRIORITY_LABELS[t.bandwidthPriority] ?? '—'} />
      <Field label="Queue position" value={String(t.queuePosition)} />
      <Field label="Creator" value={t.creator || '—'} />
      <Field label="Peer limit" value={String(t['peer-limit'] ?? '—')} />
    </Section>

    <Section title="Location" columns={1}>
      <Field label="Download directory" value={t.downloadDir} mono />
      <Field label="Hash" value={t.hashString ?? '—'} mono copy={t.hashString} />
      <Field label="Magnet" value={t.magnetLink || '—'} mono truncate copy={t.magnetLink} />
      {t.labels.length > 0 && <Field label="Labels" value={t.labels.join(', ')} />}
      {t.comment && <Field label="Comment" value={t.comment} />}
    </Section>

    {t.peersFrom && (
      <Section title="Peer sources">
        <Field label="Tracker" value={String(t.peersFrom.fromTracker)} />
        <Field label="DHT" value={String(t.peersFrom.fromDht)} />
        <Field label="PEX" value={String(t.peersFrom.fromPex)} />
        <Field label="Incoming" value={String(t.peersFrom.fromIncoming)} />
        <Field label="Local discovery" value={String(t.peersFrom.fromLpd)} />
        <Field label="Cache" value={String(t.peersFrom.fromCache)} />
      </Section>
    )}
  </div>
);

const Section = ({ title, children, columns = 2 }: { title: string; children: ReactNode; columns?: number }) => (
  <section>
    <h3 className="mb-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">{title}</h3>
    <dl className={`grid gap-x-6 gap-y-1.5 ${columns === 1 ? 'grid-cols-1' : 'grid-cols-1 sm:grid-cols-2'}`}>
      {children}
    </dl>
  </section>
);

type FieldProps = { label: string; value: string; mono?: boolean; truncate?: boolean; copy?: string };

const Field = ({ label, value, mono, truncate, copy }: FieldProps) => (
  <div className="flex min-w-0 items-baseline gap-3 text-xs">
    <dt className="w-32 shrink-0 text-muted-foreground">{label}</dt>
    <dd className={`min-w-0 flex-1 ${mono ? 'font-mono' : ''} ${truncate ? 'truncate' : 'break-words'}`} title={value}>
      {value}
    </dd>
    {copy && <CopyButton value={copy} />}
  </div>
);

const CopyButton = ({ value }: { value: string }) => {
  const [copied, setCopied] = useState(false);
  return (
    <button
      type="button"
      className="shrink-0 text-muted-foreground hover:text-foreground"
      onClick={() => {
        // copyToClipboard handles the insecure-origin case — navigator.clipboard does not exist over
        // plain http, which Officer IS reached over on a tailnet. This comment used to say "Officer is
        // always behind HTTPS"; it was not, and the button silently copied nothing.
        void copyToClipboard(value).then(
          () => {
            setCopied(true);
            setTimeout(() => setCopied(false), 1200);
          },
          () => undefined,
        );
      }}
      aria-label="Copy"
    >
      {copied ? <Check className="h-3 w-3 text-emerald-500" /> : <Copy className="h-3 w-3" />}
    </button>
  );
};
