"use client";

import { Suspense, useCallback, useEffect, useState } from "react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { ArrowLeft, Loader2 } from "lucide-react";
import type { Project, RenderProgress } from "@/types";
import { ExportProgress } from "@/components/export-progress";
import { VideoPreview } from "@/components/video-preview";
import {
  DEFAULT_ANIMATION,
  DEFAULT_LAYOUT,
  DEFAULT_STYLE,
} from "@/lib/defaults";

function ExportContent() {
  const searchParams = useSearchParams();
  const router = useRouter();
  const id = searchParams.get("id");

  const [project, setProject] = useState<Project | null>(null);
  const [loading, setLoading] = useState(true);
  const [rendering, setRendering] = useState(false);
  const [progress, setProgress] = useState<RenderProgress | null>(null);
  const [downloadUrl, setDownloadUrl] = useState<string>();
  const [filename, setFilename] = useState<string>();

  useEffect(() => {
    if (!id) {
      router.push("/");
      return;
    }

    void (async () => {
      const res = await fetch(`/api/project?id=${id}`);
      const data = await res.json();
      if (!res.ok) {
        router.push("/");
        return;
      }
      setProject(data);
      setLoading(false);
    })();
  }, [id, router]);

  const pollProgress = useCallback(async () => {
    if (!id) return;
    const res = await fetch(`/api/progress?id=${id}`);
    const data = (await res.json()) as RenderProgress;
    setProgress(data);
    if (data.stage === "done" || data.stage === "error") {
      setRendering(false);
    }
  }, [id]);

  const startRender = useCallback(async () => {
    if (!project || !id) return;
    setRendering(true);
    setProgress({ percent: 0, stage: "extracting", message: "Starting..." });

    const pollInterval = setInterval(() => void pollProgress(), 1000);

    try {
      const res = await fetch("/api/render", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          id,
          captions: project.captions,
          style: project.style,
          layout: project.layout,
          animation: project.animation,
        }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error);

      await new Promise<void>((resolve, reject) => {
        const waitForDone = setInterval(async () => {
          const progressRes = await fetch(`/api/progress?id=${id}`);
          const progressData = (await progressRes.json()) as RenderProgress;
          setProgress(progressData);

          if (progressData.stage === "done") {
            clearInterval(waitForDone);
            setDownloadUrl(`/api/download/${id}`);
            setFilename(`captioned_${id}.mp4`);
            resolve();
          } else if (progressData.stage === "error") {
            clearInterval(waitForDone);
            reject(new Error(progressData.message));
          }
        }, 1000);
      });
    } catch (error) {
      setProgress({
        percent: 0,
        stage: "error",
        message: error instanceof Error ? error.message : "Render failed",
      });
    } finally {
      clearInterval(pollInterval);
      setRendering(false);
    }
  }, [project, id, pollProgress]);

  if (loading || !project || !id) {
    return (
      <div className="flex min-h-screen items-center justify-center">
        <Loader2 className="h-8 w-8 animate-spin text-zinc-400" />
      </div>
    );
  }

  return (
    <div className="min-h-screen bg-zinc-50">
      <header className="border-b border-zinc-200 bg-white">
        <div className="mx-auto flex max-w-3xl items-center gap-4 px-6 py-4">
          <Link href={`/editor?id=${id}`} className="flex items-center gap-2 text-sm text-zinc-600 hover:text-zinc-900">
            <ArrowLeft className="h-4 w-4" /> Edit captions
          </Link>
          <h1 className="font-bold">Export Video</h1>
        </div>
      </header>

      <main className="mx-auto max-w-3xl space-y-8 px-6 py-10">
        <VideoPreview
          videoUrl={`/api/video/${id}`}
          audioUrl={project.audioPath ? `/api/audio/${id}` : undefined}
          captions={project.captions}
          style={project.style ?? DEFAULT_STYLE}
          layout={project.layout ?? DEFAULT_LAYOUT}
          animation={project.animation ?? DEFAULT_ANIMATION}
          videoMeta={project.videoMeta}
        />

        <ExportProgress
          progress={progress}
          downloadUrl={downloadUrl}
          filename={filename}
          rendering={rendering}
          onStartRender={() => void startRender()}
        />
      </main>
    </div>
  );
}

export default function ExportPage() {
  return (
    <Suspense fallback={<div className="flex min-h-screen items-center justify-center"><Loader2 className="h-8 w-8 animate-spin" /></div>}>
      <ExportContent />
    </Suspense>
  );
}
