import { useCallback, useEffect, useState } from "react";
import { onDownloadProgress, onDownloadState } from "../api";
import type { DownloadState } from "../types";

export interface LiveDownload {
  state: DownloadState;
  pct: number | null;
  speed: number | null;
  eta: number | null;
  error: string | null;
  path: string | null;
}

/**
 * Live download state keyed by video id, driven by backend events. Overlays the
 * snapshot the feed query returns, so progress updates don't require refetching.
 */
export function useDownloads(onFinished: () => void) {
  const [live, setLive] = useState<Record<string, LiveDownload>>({});

  /**
   * Drops a video's overlay. Required after deleting a download: the database
   * row is gone, but a stale `done` entry here would keep the row showing
   * "Saved" until the app restarts.
   */
  const clear = useCallback((videoId: string) => {
    setLive((prev) => {
      if (!(videoId in prev)) return prev;
      const next = { ...prev };
      delete next[videoId];
      return next;
    });
  }, []);

  useEffect(() => {
    const unlisteners: Array<() => void> = [];

    onDownloadProgress((p) => {
      setLive((prev) => ({
        ...prev,
        [p.video_id]: {
          state: "running",
          pct: p.pct,
          speed: p.speed,
          eta: p.eta,
          error: null,
          path: prev[p.video_id]?.path ?? null,
        },
      }));
    }).then((u) => unlisteners.push(u));

    onDownloadState((s) => {
      setLive((prev) => ({
        ...prev,
        [s.video_id]: {
          state: s.state,
          pct: s.state === "done" ? 100 : (prev[s.video_id]?.pct ?? null),
          speed: null,
          eta: null,
          error: s.error,
          path: s.path,
        },
      }));
      if (s.state === "done" || s.state === "failed" || s.state === "cancelled") {
        onFinished();
      }
    }).then((u) => unlisteners.push(u));

    return () => unlisteners.forEach((u) => u());
  }, [onFinished]);

  return { live, clear };
}
