"use client";

import Image from "next/image";
import {
  AlertCircle,
  Archive,
  Check,
  Download,
  Film,
  FolderOpen,
  Play,
  Sparkles,
  X,
} from "lucide-react";
import { useEffect, useState } from "react";
import { mockVideoBehavior } from "@/mock-video/behavior.config";
import { downloadMockArchive } from "@/lib/mock-video";

const styleOptions = [
  { name: "Cinematic", image: "/generated/images/cinematic-city.webp" },
  { name: "Anime", image: "/generated/images/neon-portrait.webp" },
  { name: "Storybook", image: "/generated/images/storybook-forest.webp" },
  { name: "Dreamlike", image: "/generated/images/ocean-dream.webp" },
] as const;

type Project = { id: string; title: string; image: string; date: string };

export function Wizard({ initialTool = "story" }: { initialTool?: string }) {
  const [toolLabel, setToolLabel] = useState(initialTool);
  const [step, setStep] = useState(1);
  const [script, setScript] = useState(
    "A lonely astronaut discovers a hidden garden beneath the red dust of Mars.",
  );
  const [style, setStyle] = useState("Cinematic");
  const [ratio, setRatio] = useState("16:9");
  const [videoCount, setVideoCount] = useState(4);
  const [progress, setProgress] = useState(0);
  const [status, setStatus] = useState("Preparing your request...");
  const [toast, setToast] = useState("");
  const [downloadOpen, setDownloadOpen] = useState(false);
  const [downloadError, setDownloadError] = useState("");
  const [requestId, setRequestId] = useState("");
  const [videoUrl, setVideoUrl] = useState("");
  const [generationError, setGenerationError] = useState("");

  const poster =
    styleOptions.find((option) => option.name === style)?.image ||
    mockVideoBehavior.posterImage;

  useEffect(() => {
    const timer = window.setTimeout(() => {
      const tool = new URLSearchParams(window.location.search).get("tool");
      if (tool) setToolLabel(tool);
    }, 0);
    return () => window.clearTimeout(timer);
  }, []);

  useEffect(() => {
    window.scrollTo({ top: 0, behavior: "smooth" });
  }, [step]);

  useEffect(() => {
    if (step !== 2 || !requestId || generationError) return;
    let stopped = false;
    let pollTimer = 0;

    const poll = async () => {
      try {
        const response = await fetch(
          `/api/video/?requestId=${encodeURIComponent(requestId)}`,
          { cache: "no-store" },
        );
        const data = (await response.json()) as {
          status?: string;
          videoUrl?: string;
          error?: string;
        };
        if (!response.ok) {
          throw new Error(data.error || "We could not check the render status.");
        }
        if (stopped) return;

        if (data.status === "COMPLETED" && data.videoUrl) {
          setProgress(100);
          setStatus("Your preview is ready.");
          setVideoUrl(data.videoUrl);

          const project: Project = {
            id: crypto.randomUUID(),
            title: script.slice(0, 56) || "Untitled story",
            image: poster,
            date: new Date().toISOString(),
          };
          const projects: Project[] = JSON.parse(
            localStorage.getItem("moved-projects") ||
              localStorage.getItem("nuvid-projects") ||
              "[]",
          );
          localStorage.setItem(
            "moved-projects",
            JSON.stringify([project, ...projects].slice(0, 20)),
          );

          window.setTimeout(() => {
            if (!stopped) setStep(3);
          }, 450);
          return;
        }

        if (data.status === "IN_PROGRESS") {
          setProgress((value) => Math.max(value, 34));
          setStatus("Rendering motion, light and sound...");
        } else {
          setProgress((value) => Math.max(value, 12));
          setStatus("Your render is waiting in the queue...");
        }
        pollTimer = window.setTimeout(poll, 2500);
      } catch (error) {
        if (!stopped) {
          setGenerationError(
            error instanceof Error ? error.message : "Video generation failed.",
          );
        }
      }
    };

    poll();
    return () => {
      stopped = true;
      window.clearTimeout(pollTimer);
    };
  }, [generationError, poster, requestId, script, step]);

  useEffect(() => {
    if (step !== 2 || generationError) return;
    const timer = window.setInterval(() => {
      setProgress((value) => Math.min(92, value + (value < 30 ? 2 : 1)));
    }, 1100);
    return () => window.clearInterval(timer);
  }, [generationError, step]);

  const startGeneration = async () => {
    setProgress(4);
    setStatus("Submitting your description...");
    setGenerationError("");
    setRequestId("");
    setVideoUrl("");
    setStep(2);

    try {
      const response = await fetch("/api/video/", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ prompt: script, style, ratio }),
      });
      const data = (await response.json()) as {
        requestId?: string;
        error?: string;
      };
      if (!response.ok || !data.requestId) {
        throw new Error(data.error || "We could not start this video.");
      }
      setProgress(10);
      setStatus("Your render is waiting in the queue...");
      setRequestId(data.requestId);
    } catch (error) {
      setGenerationError(
        error instanceof Error ? error.message : "Video generation failed.",
      );
    }
  };

  const resetWizard = () => {
    setProgress(0);
    setRequestId("");
    setVideoUrl("");
    setGenerationError("");
    setStep(1);
  };

  const confirmDownload = async () => {
    try {
      setDownloadError("");
      await downloadMockArchive(script);
      setDownloadOpen(false);
      setToast("Your video archive is downloading");
      window.setTimeout(() => setToast(""), 2600);
    } catch {
      setDownloadError("The archive could not be downloaded. Please try again.");
    }
  };

  return (
    <div className="wizard-shell">
      <div className="wizard-top">
        <div>
          <p className="eyebrow">{toolLabel.replace(/-/g, " ")}</p>
          <h1>Create your story</h1>
        </div>
        <div className="step-track" aria-label={`Step ${step} of 3`}>
          {[1, 2, 3].map((number) => (
            <span key={number} className={number <= step ? "active" : ""}>
              {number < step ? <Check size={13} /> : number}
            </span>
          ))}
        </div>
      </div>

      {step === 1 && (
        <section className="wizard-panel">
          <div className="wizard-main">
            <label className="field-label" htmlFor="script">
              Describe your video
            </label>
            <textarea
              id="script"
              value={script}
              onChange={(event) => setScript(event.target.value)}
              maxLength={2500}
              placeholder="Describe the person, action, setting, camera, and mood..."
            />
            <div className="char-count">{script.length} / 2500</div>
            <div className="option-block">
              <span className="field-label">Visual style</span>
              <div className="style-grid">
                {styleOptions.map((option) => (
                  <button
                    key={option.name}
                    className={option.name === style ? "selected" : ""}
                    onClick={() => setStyle(option.name)}
                  >
                    <Image
                      src={option.image}
                      alt=""
                      fill
                      sizes="150px"
                      priority={option.name === "Cinematic"}
                    />
                    <span>{option.name}</span>
                    {option.name === style && (
                      <i>
                        <Check size={12} />
                      </i>
                    )}
                  </button>
                ))}
              </div>
            </div>
          </div>
          <aside className="wizard-side">
            <div className="option-block">
              <span className="field-label">Aspect ratio</span>
              <div className="ratio-row">
                {["16:9", "9:16", "1:1"].map((option) => (
                  <button
                    key={option}
                    className={option === ratio ? "selected" : ""}
                    onClick={() => setRatio(option)}
                  >
                    <i style={{ aspectRatio: option.replace(":", "/") }} />
                    {option}
                  </button>
                ))}
              </div>
            </div>
            <div className="option-block">
              <span className="field-label">
                Number of videos <strong>{videoCount}</strong>
              </span>
              <input
                type="range"
                min="1"
                max="4"
                value={videoCount}
                onChange={(event) => setVideoCount(Number(event.target.value))}
              />
              <div className="range-labels">
                <span>1</span>
                <span>4</span>
              </div>
            </div>
            <div className="generate-note">
              <Sparkles size={16} />
              <p>
                <strong>Everything looks ready</strong>
                <span>
                  We’ll generate one preview now. Your full set is available from
                  the download button.
                </span>
              </p>
            </div>
            <button
              className="button button-primary"
              onClick={startGeneration}
              disabled={!script.trim()}
            >
              Generate video <Sparkles size={16} />
            </button>
          </aside>
        </section>
      )}

      {step === 2 && (
        <section className="generation-panel">
          {generationError ? (
            <div className="generation-error" role="alert">
              <AlertCircle size={38} />
              <p className="eyebrow">Generation interrupted</p>
              <h2>We couldn’t create this preview.</h2>
              <p>{generationError}</p>
              <div>
                <button className="button button-primary" onClick={startGeneration}>
                  Try again
                </button>
                <button className="restart" onClick={resetWizard}>
                  Back to settings
                </button>
              </div>
            </div>
          ) : (
            <>
              <div className="generation-orbit">
                <Film size={34} />
                <i />
                <i />
                <i />
              </div>
              <p className="eyebrow">Creating your video</p>
              <h2>{progress}%</h2>
              <p>{status}</p>
              <div className="progress-bar">
                <span style={{ width: `${progress}%` }} />
              </div>
              <small>AI video rendering can take several minutes. Keep this tab open.</small>
            </>
          )}
        </section>
      )}

      {step === 3 && (
        <section className="result-panel">
          <div className="result-copy">
            <p className="eyebrow">Your preview is ready</p>
            <h2>
              A first look at
              <br />
              your story.
            </h2>
            <p>
              You’re viewing one generated preview. All {videoCount}{" "}
              {videoCount === 1 ? "video is" : "videos are"} available from the
              download button below.
            </p>
            <button
              className="button button-primary"
              onClick={() => setDownloadOpen(true)}
            >
              <Download size={17} /> Download your videos
            </button>
            <button className="restart" onClick={resetWizard}>
              Create another story
            </button>
          </div>
          <div
            className={`result-player ratio-${ratio.replace(":", "")}`}
            style={{ backgroundImage: `url(${poster})` }}
            onContextMenu={(event) => event.preventDefault()}
          >
            {videoUrl && (
              <video
                src={videoUrl}
                poster={poster}
                autoPlay
                muted
                playsInline
                loop
                controlsList="nodownload noplaybackrate noremoteplayback"
                disablePictureInPicture
                disableRemotePlayback
                draggable={false}
                preload="auto"
                onCanPlay={(event) =>
                  event.currentTarget.play().catch(() => undefined)
                }
                onTimeUpdate={(event) => {
                  if (event.currentTarget.currentTime >= 3) {
                    event.currentTarget.currentTime = 0;
                    event.currentTarget.play().catch(() => undefined);
                  }
                }}
                onContextMenu={(event) => event.preventDefault()}
                onDragStart={(event) => event.preventDefault()}
                aria-label="Your generated video"
              />
            )}
            <div className="player-meta">
              <span>
                {style} · {ratio}
              </span>
              <span>Preview 1 of {videoCount}</span>
            </div>
          </div>
          {toast && <div className="toast">{toast}</div>}
        </section>
      )}

      {downloadOpen && (
        <div
          className="download-backdrop"
          onMouseDown={(event) =>
            event.target === event.currentTarget && setDownloadOpen(false)
          }
        >
          <section
            className="download-dialog"
            role="dialog"
            aria-modal="true"
            aria-labelledby="download-title"
          >
            <button
              className="dialog-close"
              onClick={() => setDownloadOpen(false)}
              aria-label="Close download instructions"
            >
              <X size={18} />
            </button>
            <div className="archive-icon">
              <Archive size={27} />
            </div>
            <p className="eyebrow">Before you download</p>
            <h2 id="download-title">Your videos come in a ZIP archive.</h2>
            <p className="dialog-lead">
              The archive keeps all of your video files together in one download.
            </p>
            <ol>
              <li>
                <span>1</span>
                <div>
                  <strong>Download the archive</strong>
                  <p>Click the button below and wait for the ZIP file to finish downloading.</p>
                </div>
              </li>
              <li>
                <span>2</span>
                <div>
                  <strong>Open or extract it</strong>
                  <p>Double-click the ZIP file, then choose Extract all if your computer asks.</p>
                </div>
              </li>
              <li>
                <span>3</span>
                <div>
                  <strong>Open your videos</strong>
                  <p>Your MP4 video files and a short README will be waiting inside.</p>
                </div>
              </li>
            </ol>
            {downloadError && <p className="download-error">{downloadError}</p>}
            <button
              className="button button-primary dialog-download"
              onClick={confirmDownload}
            >
              <FolderOpen size={17} /> Download archive
            </button>
            <small>ZIP archive · Contains MP4 video files</small>
          </section>
        </div>
      )}
    </div>
  );
}

export function Dashboard() {
  const [projects, setProjects] = useState<Project[]>([]);

  useEffect(() => {
    const timer = window.setTimeout(() => {
      const storedProjects =
        localStorage.getItem("moved-projects") ||
        localStorage.getItem("nuvid-projects") ||
        "[]";
      localStorage.setItem("moved-projects", storedProjects);
      setProjects(JSON.parse(storedProjects));
    }, 0);
    return () => window.clearTimeout(timer);
  }, []);

  return (
    <div className="dashboard-shell">
      <div className="dashboard-head">
        <div>
          <p className="eyebrow">Your workspace</p>
          <h1>My videos</h1>
        </div>
        <a className="button button-primary" href="/app/create/">
          New project <Sparkles size={15} />
        </a>
      </div>
      {projects.length ? (
        <div className="project-grid">
          {projects.map((project) => (
            <article key={project.id}>
              <div>
                <Image src={project.image} alt="" fill sizes="320px" />
                <Play fill="currentColor" />
              </div>
              <h2>{project.title}</h2>
              <p>
                {new Date(project.date).toLocaleDateString("en", {
                  month: "short",
                  day: "numeric",
                  year: "numeric",
                })}
              </p>
            </article>
          ))}
        </div>
      ) : (
        <div className="empty-state">
          <Film size={34} />
          <h2>Your next story starts here.</h2>
          <p>Projects created with the video workflow will appear in this browser.</p>
          <a className="button button-primary" href="/app/create/">
            Create your first video
          </a>
        </div>
      )}
    </div>
  );
}
