"use client";

import { useCallback, useEffect, useState } from "react";
import { useTranslations } from "next-intl";
import { Download, Link2, Loader2, RefreshCw } from "lucide-react";

import { apiFetch } from "@/lib/api/fetch";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import type { RenderExportPreset } from "@/lib/render-presets";
import { RENDER_EXPORT_PRESETS } from "@/lib/render-presets";
import type { RenderSettings } from "@/lib/render-schemas";
import type { Scene } from "@/lib/studio-types";
import { cn } from "@/lib/utils";

interface RenderModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  projectId: string;
  scenes: Scene[];
  preset?: RenderExportPreset | null;
}

type JobStatus = "idle" | "submitting" | "polling" | "completed" | "failed";

interface StatusResponse {
  status: string;
  progress: number;
  outputUrl: string | null;
  progressMessage?: string | null;
  errorMessage?: string | null;
  /** Base64-encoded PNG preview frame from the node agent. */
  previewB64?: string | null;
}

const RESOLUTIONS: RenderSettings["resolution"][] = ["720p", "1080p", "4K"];
const FPS_OPTIONS: RenderSettings["fps"][] = [24, 30, 60];

export function RenderModal({
  open,
  onOpenChange,
  projectId,
  scenes,
  preset = null,
}: RenderModalProps) {
  const t = useTranslations("auto.componentsStudioRenderModal");
  const [resolution, setResolution] =
    useState<RenderSettings["resolution"]>("1080p");
  const [fps, setFps] = useState<RenderSettings["fps"]>(30);
  const [presetLabel, setPresetLabel] = useState<string | null>(null);
  const [jobStatus, setJobStatus] = useState<JobStatus>("idle");
  const [jobId, setJobId] = useState<string | null>(null);
  const [progress, setProgress] = useState(0);
  const [progressMessage, setProgressMessage] = useState("");
  const [outputUrl, setOutputUrl] = useState<string | null>(null);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [previewB64, setPreviewB64] = useState<string | null>(null);

  const reset = useCallback(() => {
    setJobStatus("idle");
    setJobId(null);
    setProgress(0);
    setProgressMessage("");
    setOutputUrl(null);
    setErrorMessage(null);
    setPreviewB64(null);
  }, []);

  useEffect(() => {
    if (!open) reset();
  }, [open, reset]);

  useEffect(() => {
    if (!open || !preset) return;
    const config = RENDER_EXPORT_PRESETS[preset];
    setResolution(config.settings.resolution);
    setFps(config.settings.fps);
    setPresetLabel(config.label);
  }, [open, preset]);

  useEffect(() => {
    if (jobStatus !== "polling" || !jobId) return;

    const poll = async () => {
      try {
        const response = await apiFetch(`/api/render/${jobId}/status`);
        const data = (await response.json()) as StatusResponse;

        if (!response.ok) {
          setJobStatus("failed");
          setErrorMessage(t("errorFetchStatus"));
          return;
        }

        setProgress(data.progress ?? 0);
        setProgressMessage(
          data.progressMessage ?? t("renderingProgress", { progress: data.progress })
        );
        if (data.previewB64) setPreviewB64(data.previewB64);

        if (data.status === "completed" && data.outputUrl) {
          setOutputUrl(data.outputUrl);
          setJobStatus("completed");
          setProgress(100);
          return;
        }

        if (data.status === "failed") {
          setJobStatus("failed");
          setErrorMessage(data.errorMessage ?? t("errorRenderFailed"));
        }
      } catch {
        setJobStatus("failed");
        setErrorMessage(t("errorNetworkPolling"));
      }
    };

    poll();
    const intervalId = window.setInterval(poll, 3000);
    return () => window.clearInterval(intervalId);
  }, [jobStatus, jobId, t]);

  const startRender = async () => {
    setJobStatus("submitting");
    setErrorMessage(null);

    try {
      const response = await apiFetch("/api/render", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          projectId,
          settings: {
            resolution,
            format: "mp4" as const,
            fps,
          },
        }),
      });

      const data = (await response.json()) as {
        jobId?: string;
        error?: string;
      };

      if (!response.ok || !data.jobId) {
        setJobStatus("failed");
        setErrorMessage(data.error ?? t("errorStartRender"));
        return;
      }

      setJobId(data.jobId);
      setJobStatus("polling");
      setProgress(0);
      setProgressMessage(t("queued"));
    } catch {
      setJobStatus("failed");
      setErrorMessage(t("errorReachApi"));
    }
  };

  const isBusy = jobStatus === "submitting" || jobStatus === "polling";

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-md">
        <DialogHeader>
          <DialogTitle>{presetLabel ?? t("dialogTitle")}</DialogTitle>
          <DialogDescription>
            {preset
              ? RENDER_EXPORT_PRESETS[preset].description
              : t("dialogDescription")}
          </DialogDescription>
        </DialogHeader>

        {jobStatus === "completed" && outputUrl ? (
          <div className="space-y-4">
            <p className="text-sm text-green-400">{t("videoReady")}</p>
            <div className="flex flex-col gap-2">
              <a
                href={outputUrl}
                download
                className="inline-flex items-center justify-center gap-2 rounded-lg bg-primary-600 px-4 py-2.5 text-sm font-medium text-white hover:bg-primary-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#4c6ef5]"
              >
                <Download className="h-4 w-4" />
                {t("downloadMp4")}
              </a>
              <a
                href={outputUrl}
                target="_blank"
                rel="noopener noreferrer"
                className="inline-flex items-center justify-center gap-2 rounded-lg border border-[#2a2d3e] px-4 py-2.5 text-sm text-gray-200 hover:bg-[#1f2234] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#4c6ef5]"
              >
                <Link2 className="h-4 w-4" />
                {t("shareLink")}
              </a>
            </div>
            <Button
              type="button"
              variant="outline"
              className="w-full border-[#2a2d3e]"
              onClick={() => onOpenChange(false)}
            >
              {t("close")}
            </Button>
          </div>
        ) : jobStatus === "failed" ? (
          <div className="space-y-4">
            <p className="rounded-lg border border-red-900/50 bg-red-950/40 px-3 py-2 text-sm text-red-300">
              {errorMessage ?? t("errorGeneric")}
            </p>
            <Button
              type="button"
              className="w-full bg-primary-600 hover:bg-primary-700"
              onClick={startRender}
            >
              <RefreshCw className="h-4 w-4" />
              {t("retry")}
            </Button>
          </div>
        ) : isBusy ? (
          <div className="space-y-4">
            {/* Live preview frame from node agent */}
            <div className="relative overflow-hidden rounded-lg bg-[#0f111e] aspect-video">
              {previewB64 ? (
                // eslint-disable-next-line @next/next/no-img-element
                <img
                  src={`data:image/png;base64,${previewB64}`}
                  alt={t("previewAlt")}
                  className="h-full w-full object-cover"
                />
              ) : (
                <div className="flex h-full w-full items-center justify-center">
                  <Loader2 className="h-6 w-6 animate-spin text-primary-400/40" />
                </div>
              )}
              {/* Step badge */}
              <div className="absolute bottom-2 right-2 rounded-md bg-black/60 px-2 py-0.5 text-[10px] font-medium text-gray-300 backdrop-blur-sm">
                {progressMessage || t("rendering")}
              </div>
            </div>
            <div>
              <div className="mb-1 flex justify-between text-xs text-gray-500">
                <span>{t("progress")}</span>
                <span>{progress}%</span>
              </div>
              <div className="h-2 overflow-hidden rounded-full bg-[#1a1d2e]">
                <div
                  className="h-full rounded-full bg-primary-600 transition-all duration-300"
                  style={{ width: `${progress}%` }}
                />
              </div>
            </div>
          </div>
        ) : (
          <div className="space-y-4">
            <div>
              <p className="mb-2 text-xs font-medium text-gray-400">
                {t("resolution")}
              </p>
              <div className="flex gap-2">
                {RESOLUTIONS.map((item) => (
                  <button
                    key={item}
                    type="button"
                    onClick={() => setResolution(item)}
                    className={cn(
                      "flex-1 rounded-lg border py-2 text-xs font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#4c6ef5]",
                      resolution === item
                        ? "border-primary-500 bg-primary-600/20 text-white"
                        : "border-[#2a2d3e] text-[#8b91a7] hover:border-[#3d4260]"
                    )}
                  >
                    {item}
                  </button>
                ))}
              </div>
            </div>
            <div>
              <p className="mb-2 text-xs font-medium text-gray-400">{t("format")}</p>
              <div className="rounded-lg border border-primary-500 bg-primary-600/20 px-3 py-2 text-center text-xs font-medium text-white">
                MP4
              </div>
            </div>
            <div>
              <p className="mb-2 text-xs font-medium text-gray-400">{t("fps")}</p>
              <div className="flex gap-2">
                {FPS_OPTIONS.map((item) => (
                  <button
                    key={item}
                    type="button"
                    onClick={() => setFps(item)}
                    className={cn(
                      "flex-1 rounded-lg border py-2 text-xs font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#4c6ef5]",
                      fps === item
                        ? "border-primary-500 bg-primary-600/20 text-white"
                        : "border-[#2a2d3e] text-[#8b91a7] hover:border-[#3d4260]"
                    )}
                  >
                    {item}
                  </button>
                ))}
              </div>
            </div>
            <Button
              type="button"
              className="w-full bg-primary-600 hover:bg-primary-700"
              onClick={startRender}
              disabled={scenes.length === 0}
            >
              {t("startRendering")}
            </Button>
          </div>
        )}
      </DialogContent>
    </Dialog>
  );
}
