import { useState, useEffect } from 'react';
import { useParams, Link } from 'react-router';
import { Loader2, CheckCircle2, XCircle, Ban, Clock, ArrowLeft, Square, Film, Music } from 'lucide-react';
import { useClient } from 'hooks/useClient';
import { toast } from 'sonner';

// Detail view for a `download` job — a compact two-phase progress readout (metadata → download), polled
// from the job's persisted progress (the executor emits counter snapshots, not per-item events).

export type Counts = { done: number; failed: number; total: number };
export type DownloadProgress = {
  phase: 'expanding' | 'metadata' | 'download' | 'done';
  meta: Counts;
  dl: Counts;
  current?: string;
};
type DownloadJob = {
  id: string;
  mode: string;
  taskName: string;
  status: 'pending' | 'running' | 'completed' | 'failed' | 'stopped' | 'interrupted';
  error: string | null;
  cwd: string | null;
  inputs?: Record<string, unknown> | null;
  progress: DownloadProgress | null;
  createdAt: string;
};

const POLL_MS = 1500;
const isTerminal = (s: string) => s === 'completed' || s === 'failed' || s === 'stopped' || s === 'interrupted';

const statusBadge = (status: string) => {
  switch (status) {
    case 'running':
      return {
        icon: <Loader2 className="h-4 w-4 animate-spin" />,
        label: 'Running',
        cls: 'text-amber-600 dark:text-amber-500',
      };
    case 'pending':
      return { icon: <Clock className="h-4 w-4" />, label: 'Queued', cls: 'text-blue-600 dark:text-blue-400' };
    case 'completed':
      return { icon: <CheckCircle2 className="h-4 w-4" />, label: 'Completed', cls: 'text-duck-teal' };
    case 'failed':
      return { icon: <XCircle className="h-4 w-4" />, label: 'Failed', cls: 'text-red-600 dark:text-red-400' };
    case 'stopped':
      return { icon: <Ban className="h-4 w-4" />, label: 'Stopped', cls: 'text-duck-dark/50 dark:text-foreground/50' };
    default:
      return {
        icon: <XCircle className="h-4 w-4" />,
        label: 'Interrupted',
        cls: 'text-orange-600 dark:text-orange-400',
      };
  }
};

// A labelled progress bar: fill = processed/total; caption states kept/saved vs skipped/failed.
export const PhaseBar = ({
  label,
  c,
  active,
  savedLabel,
  failedLabel,
}: {
  label: string;
  c: Counts;
  active: boolean;
  savedLabel: string;
  failedLabel: string;
}) => {
  const processed = c.done + c.failed;
  const pct = c.total ? (processed / c.total) * 100 : 0;
  return (
    <div className="flex flex-col gap-1.5">
      <div className="flex items-center justify-between text-xs">
        <span
          className={`font-medium ${active ? 'text-duck-dark dark:text-foreground' : 'text-duck-dark/50 dark:text-foreground/50'}`}
        >
          {label}
        </span>
        <span className="tabular-nums text-duck-dark/50 dark:text-foreground/50">
          {processed}/{c.total || '—'}
        </span>
      </div>
      <div className="h-2.5 overflow-hidden rounded-full bg-duck-dark/10 dark:bg-foreground/10">
        <div className="h-full rounded-full bg-duck-teal transition-all duration-300" style={{ width: `${pct}%` }} />
      </div>
      <div className="flex gap-3 text-[11px] text-duck-dark/50 dark:text-foreground/50">
        <span className="text-duck-teal">
          {c.done} {savedLabel}
        </span>
        {c.failed > 0 && (
          <span className="text-red-500/80">
            {c.failed} {failedLabel}
          </span>
        )}
      </div>
    </div>
  );
};

export const DownloadJobDetail = () => {
  const { id } = useParams<{ id: string }>();
  const client = useClient();
  const [job, setJob] = useState<DownloadJob | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!id) return;
    let cancelled = false;
    const load = async () => {
      try {
        const j = await client.get<DownloadJob>(`/jobs/${id}`);
        if (!cancelled) setJob(j);
        return j;
      } catch {
        return null;
      } finally {
        if (!cancelled) setLoading(false);
      }
    };
    void load();
    const timer = setInterval(async () => {
      const j = await load();
      if (j && isTerminal(j.status)) clearInterval(timer);
    }, POLL_MS);
    return () => {
      cancelled = true;
      clearInterval(timer);
    };
  }, [id]);

  const stop = async () => {
    if (!id) return;
    try {
      await client.post(`/jobs/${id}/stop`, {});
      toast.success('Stop requested');
    } catch {
      toast.error('Failed to stop');
    }
  };

  if (loading)
    return (
      <div className="flex-1 flex items-center justify-center text-duck-dark/50 dark:text-foreground/50">
        <Loader2 className="h-5 w-5 animate-spin" />
      </div>
    );
  if (!job)
    return (
      <div className="flex-1 flex flex-col items-center justify-center gap-3 text-duck-dark/60 dark:text-foreground/60">
        <span>Job not found.</span>
        <Link to="/jobs" className="text-duck-teal hover:underline">
          Back to jobs
        </Link>
      </div>
    );

  const badge = statusBadge(job.status);
  const running = !isTerminal(job.status);
  const p = job.progress;
  const isAudio = job.inputs?.format !== 'video';
  const phaseLabel =
    !p || p.phase === 'expanding'
      ? 'Preparing…'
      : p.phase === 'metadata'
        ? 'Fetching titles'
        : p.phase === 'download'
          ? 'Downloading'
          : 'Done';

  return (
    <div className="flex-1 flex flex-col min-h-0">
      <div className="px-5 py-3 border-b border-duck-dark/10 flex items-center gap-3">
        <Link
          to="/jobs"
          className="text-duck-dark/50 dark:text-foreground/50 hover:text-duck-dark dark:hover:text-foreground"
        >
          <ArrowLeft className="h-4 w-4" />
        </Link>
        <div className="flex items-center gap-1.5 min-w-0">
          {isAudio ? (
            <Music className="h-4 w-4 shrink-0 text-duck-teal" />
          ) : (
            <Film className="h-4 w-4 shrink-0 text-duck-teal" />
          )}
          <div className="flex flex-col min-w-0">
            <span className="text-sm font-medium text-duck-dark dark:text-foreground truncate">{job.taskName}</span>
            {job.cwd && <span className="text-xs text-duck-dark/40 dark:text-foreground/40 truncate">→ {job.cwd}</span>}
          </div>
        </div>
        <span className={`ml-auto flex items-center gap-1.5 text-sm ${badge.cls}`}>
          {badge.icon} {badge.label}
        </span>
        {running && (
          <button
            onClick={stop}
            className="flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md bg-red-500/10 text-red-600 dark:text-red-400 hover:bg-red-500/20 cursor-pointer transition-colors"
          >
            <Square className="h-3 w-3" /> Stop
          </button>
        )}
      </div>

      <div className="flex-1 min-h-0 overflow-y-auto p-5">
        <div className="mx-auto flex max-w-md flex-col gap-5">
          <div className="text-sm text-duck-dark/60 dark:text-foreground/60">{phaseLabel}</div>
          <PhaseBar
            label="Titles"
            c={p?.meta ?? { done: 0, failed: 0, total: 0 }}
            active={p?.phase === 'metadata'}
            savedLabel="found"
            failedLabel="skipped"
          />
          <PhaseBar
            label="Download"
            c={p?.dl ?? { done: 0, failed: 0, total: 0 }}
            active={p?.phase === 'download'}
            savedLabel="saved"
            failedLabel="failed"
          />
          {running && p?.phase === 'download' && p.current && (
            <div className="truncate text-xs text-duck-dark/50 dark:text-foreground/50" title={p.current}>
              <Loader2 className="mr-1.5 inline h-3 w-3 animate-spin" />
              {p.current}
            </div>
          )}
          {job.error && !running && <div className="text-xs text-red-600 dark:text-red-400">{job.error}</div>}
        </div>
      </div>
    </div>
  );
};
