"use client";

import { useState, useMemo, useCallback } from "react";
import { useQuery } from "@tanstack/react-query";
import {
  LayoutGrid,
  Maximize2,
  Printer,
  Loader2,
  Film,
  ChevronDown,
  ChevronRight,
  Star,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils";

// ─── Types ────────────────────────────────────────────────────────────────────

interface Project {
  id: string;
  name: string;
  code: string;
  projectType: string;
}

interface Shot {
  id: string;
  shotCode: string;
  scene: string;
  episode: string | null;
  shotNumber: number;
  sequence: string | null;
  description: string | null;
  notes: string | null;
  status: string;
  thumbnailUrl: string | null;
  frameStart: number | null;
  frameEnd: number | null;
  fps: number;
  isKeyShot: boolean;
  shotVersion: string;
  shotGroup: { id: string; name: string } | null;
}

type Layout = "standard" | "fullscreen";
type GroupBy = "episode" | "scene" | "group" | "none";

interface ShotGroup {
  label: string;
  shots: Shot[];
}

interface DisplayOptions {
  includeDescription: boolean;
  includeNotes: boolean;
  includeFrameRange: boolean;
  includeStatus: boolean;
  includeVersion: boolean;
  layout: Layout;
  columns: number;
}

// ─── Status config ────────────────────────────────────────────────────────────

const STATUS_LABEL: Record<string, string> = {
  WAITING: "Waiting",
  IN_PROGRESS: "In Progress",
  INTERNAL_REVIEW: "Internal Review",
  READY_FOR_CLIENT: "Ready for Client",
  CLIENT_REVIEW: "Client Review",
  REVISIONS: "Revisions",
  COMPLETE: "Complete",
};

// ─── Standard layout shot card ─────────────────────────────────────────────────

function ShotCard({ shot, opts }: { shot: Shot; opts: DisplayOptions }) {
  const frameCount =
    shot.frameStart != null && shot.frameEnd != null
      ? shot.frameEnd - shot.frameStart + 1
      : null;

  return (
    <div
      className={cn(
        "sb-avoid-break rounded-sm overflow-hidden border border-zinc-700 bg-zinc-900",
        "print:border-zinc-300 print:bg-white print:rounded-none"
      )}
    >
      {/* Thumbnail */}
      <div className="relative w-full aspect-[2.39] bg-zinc-950 print:bg-zinc-100">
        {shot.thumbnailUrl ? (
          // eslint-disable-next-line @next/next/no-img-element
          <img
            src={shot.thumbnailUrl}
            alt={shot.shotCode}
            loading="lazy"
            className="w-full h-full object-cover"
          />
        ) : (
          <div className="flex items-center justify-center w-full h-full sb-no-thumb">
            <Film className="h-6 w-6 text-zinc-700 print:text-zinc-400" />
          </div>
        )}
        {shot.isKeyShot && (
          <div className="absolute top-1 right-1 bg-amber-500/90 rounded-sm p-0.5">
            <Star className="h-2.5 w-2.5 text-white" fill="white" />
          </div>
        )}
      </div>

      {/* Info */}
      <div className="p-2 space-y-0.5">
        <div className="flex items-baseline justify-between gap-1">
          <span className="font-mono text-[10px] font-bold text-white print:text-black leading-tight truncate">
            {shot.shotCode}
          </span>
          {opts.includeVersion && (
            <span className="font-mono text-[9px] text-zinc-500 print:text-zinc-400 shrink-0">
              {shot.shotVersion}
            </span>
          )}
        </div>

        {opts.includeFrameRange && frameCount != null && (
          <div className="text-[9px] text-zinc-500 print:text-zinc-500">
            {shot.frameStart}–{shot.frameEnd} ({frameCount}fr)
          </div>
        )}

        {opts.includeDescription && shot.description && (
          <p className="text-[10px] text-zinc-400 print:text-zinc-700 leading-tight line-clamp-3">
            {shot.description}
          </p>
        )}

        {opts.includeNotes && shot.notes && (
          <p className="text-[10px] text-zinc-500 print:text-zinc-500 italic leading-tight line-clamp-2">
            {shot.notes}
          </p>
        )}

        {opts.includeStatus && (
          <div className="text-[9px] text-zinc-600 print:text-zinc-400 uppercase tracking-wide">
            {STATUS_LABEL[shot.status] ?? shot.status}
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Standard layout ──────────────────────────────────────────────────────────

function StandardLayout({
  groups,
  opts,
  projectName,
  pageBreakBetweenGroups,
}: {
  groups: ShotGroup[];
  opts: DisplayOptions;
  projectName: string;
  pageBreakBetweenGroups: boolean;
}) {
  const colClass: Record<number, string> = {
    2: "grid-cols-2",
    3: "grid-cols-3",
    4: "grid-cols-4",
  };

  return (
    <div className="space-y-8 print:space-y-6">
      {groups.map((group, gi) => (
        <div
          key={group.label || "all"}
          className={cn(pageBreakBetweenGroups && gi > 0 && "sb-force-break print:mt-0")}
        >
          {/* Group header */}
          {group.label && (
            <div className="sb-avoid-break mb-4 print:mb-3">
              <div className="flex items-center gap-3">
                <div className="flex-1 h-px bg-zinc-700 print:bg-zinc-300 sb-group-header-line" />
                <span className="text-xs font-bold uppercase tracking-widest text-zinc-400 print:text-zinc-600 px-2">
                  {group.label}
                </span>
                <div className="flex-1 h-px bg-zinc-700 print:bg-zinc-300" />
              </div>
              <p className="text-[10px] text-zinc-600 print:text-zinc-400 mt-1 text-center">
                {projectName} &nbsp;·&nbsp; {group.shots.length} shot{group.shots.length !== 1 ? "s" : ""}
              </p>
            </div>
          )}

          {/* Shot grid */}
          <div className={cn("grid gap-3 print:gap-2", colClass[opts.columns] ?? "grid-cols-3")}>
            {group.shots.map((shot) => (
              <ShotCard key={shot.id} shot={shot} opts={opts} />
            ))}
          </div>
        </div>
      ))}
    </div>
  );
}

// ─── Fullscreen layout ────────────────────────────────────────────────────────

function FullscreenLayout({
  groups,
  opts,
  projectName,
}: {
  groups: ShotGroup[];
  opts: DisplayOptions;
  projectName: string;
}) {
  const allShots = groups.flatMap((g) => g.shots);

  return (
    <div>
      {allShots.map((shot, idx) => {
        const frameCount =
          shot.frameStart != null && shot.frameEnd != null
            ? shot.frameEnd - shot.frameStart + 1
            : null;
        const isLast = idx === allShots.length - 1;

        return (
          <div
            key={shot.id}
            className={cn(
              "relative flex flex-col overflow-hidden",
              "bg-zinc-950 print:bg-black",
              "min-h-[70vh] print:h-screen",
              !isLast && "sb-page-break mb-2 print:mb-0"
            )}
          >
            {/* Full-bleed image */}
            <div className="relative flex-1 bg-zinc-900 print:bg-black overflow-hidden sb-fs-image-area">
              {shot.thumbnailUrl ? (
                // eslint-disable-next-line @next/next/no-img-element
                <img
                  src={shot.thumbnailUrl}
                  alt={shot.shotCode}
                  loading="lazy"
                  className="w-full h-full object-contain"
                />
              ) : (
                <div className="flex items-center justify-center h-full min-h-[40vh]">
                  <div className="text-center space-y-3">
                    <Film className="h-16 w-16 text-zinc-800 mx-auto" />
                    <p className="text-zinc-700 text-sm">No thumbnail</p>
                  </div>
                </div>
              )}

              {/* Project watermark — top left */}
              <div className="absolute top-4 left-4 text-[10px] font-mono text-white/30 print:text-white/40 tracking-widest uppercase">
                {projectName}
              </div>

              {/* Shot number — top right */}
              <div className="absolute top-4 right-4 text-[10px] font-mono text-white/30 print:text-white/40 tracking-widest">
                {idx + 1} / {allShots.length}
              </div>
            </div>

            {/* Info bar */}
            <div className="bg-zinc-900 print:bg-zinc-950 border-t border-zinc-800 print:border-zinc-700 px-8 py-5 print:py-4 shrink-0 sb-fs-infobar">
              <div className="flex items-start gap-8">
                <div className="space-y-1 min-w-0 flex-1">
                  <div className="flex items-center gap-3 flex-wrap">
                    <span className="font-mono text-2xl print:text-xl font-bold text-white tracking-tight">
                      {shot.shotCode}
                    </span>
                    {shot.isKeyShot && (
                      <span className="flex items-center gap-1 text-amber-400 text-xs font-semibold">
                        <Star className="h-3 w-3" fill="currentColor" /> Key Shot
                      </span>
                    )}
                    {opts.includeVersion && (
                      <span className="font-mono text-sm text-zinc-500 print:text-zinc-400">
                        {shot.shotVersion}
                      </span>
                    )}
                  </div>

                  <div className="flex items-center gap-4 text-xs text-zinc-500 print:text-zinc-400 flex-wrap">
                    {shot.episode && <span>Ep&nbsp;{shot.episode}</span>}
                    <span>Scene&nbsp;{shot.scene}</span>
                    {shot.shotGroup && <span>{shot.shotGroup.name}</span>}
                    {opts.includeFrameRange && frameCount != null && (
                      <span>
                        {shot.frameStart}–{shot.frameEnd} &nbsp;({frameCount}&nbsp;fr)
                      </span>
                    )}
                    {opts.includeStatus && (
                      <span className="uppercase tracking-wide">
                        {STATUS_LABEL[shot.status] ?? shot.status}
                      </span>
                    )}
                  </div>

                  {opts.includeDescription && shot.description && (
                    <p className="text-sm text-zinc-300 print:text-zinc-200 mt-2 leading-relaxed max-w-3xl">
                      {shot.description}
                    </p>
                  )}

                  {opts.includeNotes && shot.notes && (
                    <p className="text-xs text-zinc-500 print:text-zinc-400 italic mt-1 max-w-3xl">
                      {shot.notes}
                    </p>
                  )}
                </div>
              </div>
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ─── Toggle button ─────────────────────────────────────────────────────────────

function ToggleBtn({
  active,
  onClick,
  children,
  className,
}: {
  active: boolean;
  onClick: () => void;
  children: React.ReactNode;
  className?: string;
}) {
  return (
    <button
      onClick={onClick}
      className={cn(
        "flex items-center gap-2 rounded-lg px-3 py-2 text-xs font-medium transition-all border",
        active
          ? "bg-amber-500/15 border-amber-500/40 text-amber-400"
          : "bg-zinc-800/60 border-zinc-700 text-zinc-400 hover:text-zinc-200 hover:border-zinc-600",
        className
      )}
    >
      {children}
    </button>
  );
}

// ─── Collapsible section ───────────────────────────────────────────────────────

function Section({
  title,
  children,
  defaultOpen = true,
}: {
  title: string;
  children: React.ReactNode;
  defaultOpen?: boolean;
}) {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <div className="border-b border-zinc-800 pb-4">
      <button
        onClick={() => setOpen((o) => !o)}
        className="flex items-center justify-between w-full py-2 text-xs font-bold uppercase tracking-widest text-zinc-500 hover:text-zinc-300 transition-colors"
      >
        {title}
        {open ? <ChevronDown className="h-3 w-3" /> : <ChevronRight className="h-3 w-3" />}
      </button>
      {open && <div className="pt-2 space-y-2">{children}</div>}
    </div>
  );
}

// ─── Checkbox row ─────────────────────────────────────────────────────────────

function CheckRow({
  label,
  checked,
  onChange,
}: {
  label: string;
  checked: boolean;
  onChange: (v: boolean) => void;
}) {
  return (
    <label className="flex items-center gap-2 cursor-pointer group">
      <input
        type="checkbox"
        checked={checked}
        onChange={(e) => onChange(e.target.checked)}
        className="accent-amber-500 h-3.5 w-3.5"
      />
      <span className="text-xs text-zinc-400 group-hover:text-zinc-200 transition-colors">
        {label}
      </span>
    </label>
  );
}

// ─── Main component ───────────────────────────────────────────────────────────

interface Props {
  projects: Project[];
}

export function StoryboardGenerator({ projects }: Props) {
  const [projectId, setProjectId] = useState(projects[0]?.id ?? "");
  const [layout, setLayout] = useState<Layout>("standard");
  const [columns, setColumns] = useState(3);
  const [groupBy, setGroupBy] = useState<GroupBy>("episode");
  const [pageBreakBetweenGroups, setPageBreakBetweenGroups] = useState(true);
  const [showOnlyWithThumbnails, setShowOnlyWithThumbnails] = useState(false);

  // Filter state — sets of episode/group keys; empty = all
  const [selectedEpisodes, setSelectedEpisodes] = useState<Set<string>>(new Set());
  const [selectedGroups, setSelectedGroups] = useState<Set<string>>(new Set());

  // Display options
  const [includeDescription, setIncludeDescription] = useState(true);
  const [includeNotes, setIncludeNotes] = useState(false);
  const [includeFrameRange, setIncludeFrameRange] = useState(true);
  const [includeStatus, setIncludeStatus] = useState(false);
  const [includeVersion, setIncludeVersion] = useState(false);

  // ── Fetch shots ─────────────────────────────────────────────────────────────
  const { data, isLoading, error } = useQuery<{ shots: Shot[] }>({
    queryKey: ["storyboard-shots", projectId],
    queryFn: async () => {
      const res = await fetch(`/api/storyboard/shots?projectId=${projectId}`);
      if (!res.ok) throw new Error("Failed to load shots");
      return res.json();
    },
    enabled: !!projectId,
    staleTime: 60_000,
  });

  const allShots = data?.shots ?? [];

  // ── Derived filter options ─────────────────────────────────────────────────
  const episodes = useMemo(
    () => [...new Set(allShots.map((s) => s.episode).filter(Boolean) as string[])].sort(),
    [allShots]
  );

  const shotGroups = useMemo(() => {
    const seen = new Map<string, string>();
    allShots.forEach((s) => {
      if (s.shotGroup) seen.set(s.shotGroup.id, s.shotGroup.name);
    });
    return [...seen.entries()].map(([id, name]) => ({ id, name }));
  }, [allShots]);

  // Reset filters when project changes
  useEffect(() => {
    setSelectedEpisodes(new Set());
    setSelectedGroups(new Set());
  }, [projectId]);

  // ── Filtered shots ─────────────────────────────────────────────────────────
  const filteredShots = useMemo(() => {
    return allShots.filter((shot) => {
      if (showOnlyWithThumbnails && !shot.thumbnailUrl) return false;
      if (selectedEpisodes.size > 0) {
        const ep = shot.episode ?? "";
        if (!selectedEpisodes.has(ep)) return false;
      }
      if (selectedGroups.size > 0) {
        const gid = shot.shotGroup?.id ?? "";
        if (!selectedGroups.has(gid)) return false;
      }
      return true;
    });
  }, [allShots, selectedEpisodes, selectedGroups, showOnlyWithThumbnails]);

  // ── Group filtered shots ────────────────────────────────────────────────────
  const groupedShots = useMemo((): ShotGroup[] => {
    if (groupBy === "none") return [{ label: "", shots: filteredShots }];

    const map = new Map<string, Shot[]>();
    for (const shot of filteredShots) {
      let key = "";
      if (groupBy === "episode") key = shot.episode ? `Episode ${shot.episode}` : "No Episode";
      else if (groupBy === "scene") key = `Scene ${shot.scene}`;
      else if (groupBy === "group") key = shot.shotGroup?.name ?? "No Group";
      if (!map.has(key)) map.set(key, []);
      map.get(key)!.push(shot);
    }

    return [...map.entries()].map(([label, shots]) => ({ label, shots }));
  }, [filteredShots, groupBy]);

  const project = projects.find((p) => p.id === projectId);

  const opts: DisplayOptions = {
    includeDescription,
    includeNotes,
    includeFrameRange,
    includeStatus,
    includeVersion,
    layout,
    columns,
  };

  // ── Toggle helpers ─────────────────────────────────────────────────────────
  const toggleEpisode = useCallback((ep: string) => {
    setSelectedEpisodes((prev) => {
      const next = new Set(prev);
      next.has(ep) ? next.delete(ep) : next.add(ep);
      return next;
    });
  }, []);

  const toggleGroup = useCallback((id: string) => {
    setSelectedGroups((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });
  }, []);

  // ── PDF URL (opens in new tab → auto-triggers browser print dialog) ─────────────────────
  const pdfUrl = useMemo(() => {
    const params = new URLSearchParams({
      projectId,
      layout,
      columns: String(columns),
      groupBy,
      desc:       includeDescription      ? "1" : "0",
      notes:      includeNotes            ? "1" : "0",
      frameRange: includeFrameRange       ? "1" : "0",
      status:     includeStatus           ? "1" : "0",
      version:    includeVersion          ? "1" : "0",
      pageBreaks: pageBreakBetweenGroups  ? "1" : "0",
      onlyThumbs: showOnlyWithThumbnails  ? "1" : "0",
    });
    if (selectedEpisodes.size > 0) params.set("episodes", [...selectedEpisodes].join(","));
    if (selectedGroups.size > 0)   params.set("groups",   [...selectedGroups].join(","));
    return `/api/storyboard/pdf?${params}`;
  }, [
    projectId, layout, columns, groupBy,
    includeDescription, includeNotes, includeFrameRange, includeStatus, includeVersion,
    pageBreakBetweenGroups, showOnlyWithThumbnails, selectedEpisodes, selectedGroups,
  ]);

  // ─── Render ──────────────────────────────────────────────────────────────────
  return (
    <div className="flex h-full overflow-hidden bg-zinc-950">
        {/* ── Controls sidebar ── */}
        <div className="no-print w-64 shrink-0 border-r border-zinc-800 overflow-y-auto flex flex-col bg-zinc-900">
          {/* Header */}
          <div className="px-4 pt-4 pb-3 border-b border-zinc-800 shrink-0">
            <h1 className="text-sm font-bold text-white flex items-center gap-2">
              <LayoutGrid className="h-4 w-4 text-amber-400" />
              Storyboard Generator
            </h1>
            <p className="text-[11px] text-zinc-500 mt-0.5">
              {filteredShots.length} shot{filteredShots.length !== 1 ? "s" : ""} selected
            </p>
          </div>

          <div className="flex-1 overflow-y-auto px-4 py-4 space-y-5">
            {/* Project */}
            <Section title="Project">
              <select
                value={projectId}
                onChange={(e) => setProjectId(e.target.value)}
                className="w-full bg-zinc-800 border border-zinc-700 rounded-lg text-xs text-white px-3 py-2 focus:outline-none focus:border-amber-600"
              >
                {projects.map((p) => (
                  <option key={p.id} value={p.id}>
                    {p.code} — {p.name}
                  </option>
                ))}
              </select>
            </Section>

            {/* Layout */}
            <Section title="Layout">
              <div className="flex gap-2">
                <ToggleBtn active={layout === "standard"} onClick={() => setLayout("standard")} className="flex-1 justify-center">
                  <LayoutGrid className="h-3.5 w-3.5" />
                  Standard
                </ToggleBtn>
                <ToggleBtn active={layout === "fullscreen"} onClick={() => setLayout("fullscreen")} className="flex-1 justify-center">
                  <Maximize2 className="h-3.5 w-3.5" />
                  Fullscreen
                </ToggleBtn>
              </div>

              {layout === "standard" && (
                <div className="space-y-1.5 pt-1">
                  <Label className="text-[10px] text-zinc-500 uppercase tracking-wider">
                    Columns
                  </Label>
                  <div className="flex gap-1.5">
                    {([2, 3, 4] as const).map((c) => (
                      <button
                        key={c}
                        onClick={() => setColumns(c)}
                        className={cn(
                          "flex-1 py-1.5 rounded text-xs font-semibold border transition-all",
                          columns === c
                            ? "bg-amber-500/15 border-amber-500/40 text-amber-400"
                            : "bg-zinc-800 border-zinc-700 text-zinc-500 hover:text-zinc-300"
                        )}
                      >
                        {c}
                      </button>
                    ))}
                  </div>
                </div>
              )}
            </Section>

            {/* Group by */}
            <Section title="Group By">
              {(["episode", "scene", "group", "none"] as GroupBy[]).map((g) => (
                <label key={g} className="flex items-center gap-2 cursor-pointer">
                  <input
                    type="radio"
                    name="groupBy"
                    value={g}
                    checked={groupBy === g}
                    onChange={() => setGroupBy(g)}
                    className="accent-amber-500"
                  />
                  <span className="text-xs text-zinc-400 capitalize">
                    {g === "none" ? "No grouping" : g === "group" ? "Shot Group" : g.charAt(0).toUpperCase() + g.slice(1)}
                  </span>
                </label>
              ))}
              {groupBy !== "none" && (
                <CheckRow
                  label="Page break between groups"
                  checked={pageBreakBetweenGroups}
                  onChange={setPageBreakBetweenGroups}
                />
              )}
            </Section>

            {/* Filter by episode */}
            {episodes.length > 0 && (
              <Section title="Episodes" defaultOpen={false}>
                <div className="flex gap-2 mb-2">
                  <button
                    onClick={() => setSelectedEpisodes(new Set())}
                    className="text-[10px] text-amber-400 hover:text-amber-300"
                  >
                    All
                  </button>
                  <button
                    onClick={() => setSelectedEpisodes(new Set(episodes))}
                    className="text-[10px] text-zinc-500 hover:text-zinc-300"
                  >
                    None
                  </button>
                </div>
                <div className="space-y-1.5 max-h-40 overflow-y-auto">
                  {episodes.map((ep) => (
                    <label key={ep} className="flex items-center gap-2 cursor-pointer">
                      <input
                        type="checkbox"
                        checked={selectedEpisodes.size === 0 || selectedEpisodes.has(ep)}
                        onChange={() => toggleEpisode(ep)}
                        className="accent-amber-500 h-3.5 w-3.5"
                      />
                      <span className="text-xs text-zinc-400 font-mono">{ep}</span>
                    </label>
                  ))}
                </div>
              </Section>
            )}

            {/* Filter by shot group */}
            {shotGroups.length > 0 && (
              <Section title="Shot Groups" defaultOpen={false}>
                <div className="flex gap-2 mb-2">
                  <button
                    onClick={() => setSelectedGroups(new Set())}
                    className="text-[10px] text-amber-400 hover:text-amber-300"
                  >
                    All
                  </button>
                  <button
                    onClick={() => setSelectedGroups(new Set(shotGroups.map((g) => g.id)))}
                    className="text-[10px] text-zinc-500 hover:text-zinc-300"
                  >
                    None
                  </button>
                </div>
                <div className="space-y-1.5 max-h-40 overflow-y-auto">
                  {shotGroups.map((g) => (
                    <label key={g.id} className="flex items-center gap-2 cursor-pointer">
                      <input
                        type="checkbox"
                        checked={selectedGroups.size === 0 || selectedGroups.has(g.id)}
                        onChange={() => toggleGroup(g.id)}
                        className="accent-amber-500 h-3.5 w-3.5"
                      />
                      <span className="text-xs text-zinc-400">{g.name}</span>
                    </label>
                  ))}
                </div>
              </Section>
            )}

            {/* Content options */}
            <Section title="Show Fields">
              <CheckRow label="Description" checked={includeDescription} onChange={setIncludeDescription} />
              <CheckRow label="Notes" checked={includeNotes} onChange={setIncludeNotes} />
              <CheckRow label="Frame range" checked={includeFrameRange} onChange={setIncludeFrameRange} />
              <CheckRow label="Version" checked={includeVersion} onChange={setIncludeVersion} />
              <CheckRow label="Status" checked={includeStatus} onChange={setIncludeStatus} />
              <CheckRow
                label="Only shots with thumbnails"
                checked={showOnlyWithThumbnails}
                onChange={setShowOnlyWithThumbnails}
              />
            </Section>
          </div>

          {/* Generate button */}
          <div className="shrink-0 p-4 border-t border-zinc-800 space-y-2">
          {layout === "fullscreen" && (
              <p className="text-[10px] text-zinc-600 text-center leading-tight">
                Tip: choose Landscape in the print dialog
              </p>
            )}
            {filteredShots.length > 0 ? (
              <a href={pdfUrl} target="_blank" rel="noopener noreferrer" className="block">
                <Button className="w-full bg-amber-600 hover:bg-amber-500 text-white font-semibold">
                  <Printer className="h-4 w-4 mr-2" />
                  Generate PDF
                </Button>
              </a>
            ) : (
              <Button className="w-full bg-amber-600/40 text-white/40 font-semibold" disabled>
                <Printer className="h-4 w-4 mr-2" />
                Generate PDF
              </Button>
            )}
          </div>
        </div>

        {/* ── Preview area ── */}
        <div className="flex-1 overflow-y-auto bg-zinc-950">
          {/* Preview toolbar */}
          <div className="no-print sticky top-0 z-10 flex items-center gap-3 px-6 py-3 bg-zinc-900/80 backdrop-blur border-b border-zinc-800">
            <span className="text-xs text-zinc-500">Preview</span>
            <div className="flex-1" />
            <span className="text-[11px] text-zinc-600">
              {layout === "standard" ? `${columns} cols` : "1 per page"} ·{" "}
              {filteredShots.length} shots ·{" "}
              {layout === "fullscreen" ? "Landscape PDF" : "Portrait PDF"}
            </span>
          </div>

          {/* Storyboard content */}
          <div className={cn("print-area p-6 print:p-0", layout === "standard" ? "sb-standard-print" : "sb-fullscreen-print")}>
            {isLoading ? (
              <div className="flex items-center justify-center py-24 no-print">
                <Loader2 className="h-8 w-8 animate-spin text-zinc-600" />
              </div>
            ) : error ? (
              <div className="flex items-center justify-center py-24 no-print text-red-400 text-sm">
                Failed to load shots
              </div>
            ) : filteredShots.length === 0 ? (
              <div className="flex flex-col items-center justify-center py-24 no-print gap-3 text-zinc-600">
                <Film className="h-12 w-12 text-zinc-800" />
                <p className="text-sm">No shots to display</p>
                {showOnlyWithThumbnails && (
                  <p className="text-xs text-zinc-700">Try unchecking "Only shots with thumbnails"</p>
                )}
              </div>
            ) : layout === "standard" ? (
              <StandardLayout
                groups={groupedShots}
                opts={opts}
                projectName={project?.name ?? ""}
                pageBreakBetweenGroups={pageBreakBetweenGroups}
              />
            ) : (
              <FullscreenLayout
                groups={groupedShots}
                opts={opts}
                projectName={project?.name ?? ""}
              />
            )}
        </div>
      </div>
    </div>
  );
}
