"use client";

import { useState, useCallback, useRef } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { useToast } from "@/components/ui/use-toast";
import { cn } from "@/lib/utils";
import {
  ArrowLeft,
  Upload,
  AlertCircle,
  CheckCircle2,
  RefreshCw,
  SkipForward,
  FilePlus2,
  Pencil,
  Film,
  FileSpreadsheet,
} from "lucide-react";
import { parseEdlCsv, parsePictureTrackerCsv, parseSimpleCsv, parseGroupAssignCsv } from "@/lib/edl-utils";
import type { EdlImportRow, PictureTrackerRow, SimpleCsvRow, GroupAssignRow } from "@/lib/edl-utils";
import { importShotsFromEdl, updateShotsSeqTimecodes, importShotsFromSimpleCsv, assignShotGroups } from "@/actions/shots";

interface EdlImportClientProps {
  projectId: string;
  projectName: string;
  existingShotCodes: Set<string>;
}

type Step = "input" | "preview" | "result";

const ACTION_STYLES = {
  create: "bg-emerald-500/10 text-emerald-400 border-emerald-500/20",
  update: "bg-blue-500/10 text-blue-400 border-blue-500/20",
  skip:   "bg-zinc-500/10 text-zinc-400 border-zinc-500/20",
};

const ACTION_ICONS = {
  create: FilePlus2,
  update: Pencil,
  skip:   SkipForward,
};

export function EdlImportClient({ projectId, projectName, existingShotCodes }: EdlImportClientProps) {
  const router = useRouter();
  const { toast } = useToast();
  const fileInputRef = useRef<HTMLInputElement>(null);

  const [step, setStep] = useState<Step>("input");
  const [csvText, setCsvText] = useState("");
  const [rows, setRows] = useState<EdlImportRow[]>([]);
  const [parseErrors, setParseErrors] = useState<string[]>([]);
  const [importing, setImporting] = useState(false);
  const [result, setResult] = useState<{ created: string[]; updated: string[]; skipped: string[]; errors: string[] } | null>(null);

  // ── Simple CSV state ────────────────────────────────────────────────────────
  const scFileInputRef = useRef<HTMLInputElement>(null);
  const [scStep, setScStep] = useState<"input" | "preview" | "result">("input");
  const [scCsvText, setScCsvText] = useState("");
  const [scRows, setScRows] = useState<SimpleCsvRow[]>([]);
  const [scErrors, setScErrors] = useState<string[]>([]);
  const [scImporting, setScImporting] = useState(false);
  const [scResult, setScResult] = useState<{ created: string[]; updated: string[]; skipped: string[]; errors: string[] } | null>(null);

  // ── Group Assignment state ───────────────────────────────────────────────
  const gaFileInputRef = useRef<HTMLInputElement>(null);
  const [gaStep, setGaStep] = useState<"input" | "preview" | "result">("input");
  const [gaCsvText, setGaCsvText] = useState("");
  const [gaRows, setGaRows] = useState<GroupAssignRow[]>([]);
  const [gaErrors, setGaErrors] = useState<string[]>([]);
  const [gaAssigning, setGaAssigning] = useState(false);
  const [gaResult, setGaResult] = useState<{ assigned: string[]; skipped: string[]; errors: string[] } | null>(null);

  // ── Picture Tracker state ─────────────────────────────────────────────────
  const ptFileInputRef = useRef<HTMLInputElement>(null);
  const [ptStep, setPtStep] = useState<"input" | "preview" | "result">("input");
  const [ptCsvText, setPtCsvText] = useState("");
  const [ptRows, setPtRows] = useState<PictureTrackerRow[]>([]);
  const [ptErrors, setPtErrors] = useState<string[]>([]);
  const [ptImporting, setPtImporting] = useState(false);
  const [ptResult, setPtResult] = useState<{ updated: string[]; skipped: string[]; errors: string[] } | null>(null);

  const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (ev) => setCsvText(ev.target?.result as string ?? "");
    reader.readAsText(file);
    e.target.value = "";
  };

  const handleParse = useCallback(() => {
    const { rows: parsed, errors } = parseEdlCsv(csvText);
    setParseErrors(errors);

    // Determine action for each row based on existing shots
    const withActions: EdlImportRow[] = parsed.map((row) => ({
      ...row,
      action: existingShotCodes.has(row.shotCode) ? "update" : "create",
    }));

    setRows(withActions);
    if (withActions.length > 0) setStep("preview");
  }, [csvText, existingShotCodes]);

  const toggleAction = (idx: number) => {
    setRows((prev) =>
      prev.map((r, i) => {
        if (i !== idx) return r;
        const cycle: EdlImportRow["action"][] = ["create", "update", "skip"];
        const next = cycle[(cycle.indexOf(r.action) + 1) % cycle.length];
        return { ...r, action: next };
      })
    );
  };

  const setAllAction = (action: EdlImportRow["action"]) => {
    setRows((prev) => prev.map((r) => ({ ...r, action })));
  };

  const handleImport = async () => {
    setImporting(true);
    try {
      const res = await importShotsFromEdl(projectId, rows);
      setResult(res);
      setStep("result");
      if (res.created.length + res.updated.length > 0) {
        toast({
          title: `Import complete`,
          description: `${res.created.length} created, ${res.updated.length} updated`,
        });
      }
    } catch (e) {
      toast({ title: "Import failed", description: e instanceof Error ? e.message : undefined, variant: "destructive" });
    } finally {
      setImporting(false);
    }
  };

  const handleReset = () => {
    setStep("input");
    setCsvText("");
    setRows([]);
    setParseErrors([]);
    setResult(null);
  };

  // ── Simple CSV handlers ─────────────────────────────────────────────────────
  const handleScFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (ev) => setScCsvText(ev.target?.result as string ?? "");
    reader.readAsText(file);
    e.target.value = "";
  };

  const handleScParse = useCallback(() => {
    const { rows: parsed, errors } = parseSimpleCsv(scCsvText, existingShotCodes);
    setScErrors(errors);
    setScRows(parsed);
    if (parsed.length > 0) setScStep("preview");
  }, [scCsvText, existingShotCodes]);

  const toggleScAction = (idx: number) => {
    setScRows((prev) =>
      prev.map((r, i) => {
        if (i !== idx) return r;
        const cycle: SimpleCsvRow["action"][] = ["create", "update", "skip"];
        const next = cycle[(cycle.indexOf(r.action) + 1) % cycle.length];
        return { ...r, action: next };
      })
    );
  };

  const handleScImport = async () => {
    setScImporting(true);
    try {
      const res = await importShotsFromSimpleCsv(projectId, scRows);
      setScResult(res);
      setScStep("result");
      if (res.created.length + res.updated.length > 0) {
        toast({
          title: "Import complete",
          description: `${res.created.length} created, ${res.updated.length} updated`,
        });
      }
    } catch (e) {
      toast({ title: "Import failed", description: e instanceof Error ? e.message : undefined, variant: "destructive" });
    } finally {
      setScImporting(false);
    }
  };

  const handleScReset = () => {
    setScStep("input");
    setScCsvText("");
    setScRows([]);
    setScErrors([]);
    setScResult(null);
  };

  // ── Group Assignment handlers ────────────────────────────────────────────
  const handleGaFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (ev) => setGaCsvText(ev.target?.result as string ?? "");
    reader.readAsText(file);
    e.target.value = "";
  };

  const handleGaParse = useCallback(() => {
    const { rows: parsed, errors } = parseGroupAssignCsv(gaCsvText, existingShotCodes);
    setGaErrors(errors);
    setGaRows(parsed);
    if (parsed.length > 0) setGaStep("preview");
  }, [gaCsvText, existingShotCodes]);

  const handleGaAssign = async () => {
    setGaAssigning(true);
    try {
      const res = await assignShotGroups(projectId, gaRows);
      setGaResult(res);
      setGaStep("result");
      if (res.assigned.length > 0) {
        toast({ title: "Groups assigned", description: `${res.assigned.length} shot${res.assigned.length !== 1 ? "s" : ""} updated` });
      }
    } catch (e) {
      toast({ title: "Assignment failed", description: e instanceof Error ? e.message : undefined, variant: "destructive" });
    } finally {
      setGaAssigning(false);
    }
  };

  const handleGaReset = () => {
    setGaStep("input");
    setGaCsvText("");
    setGaRows([]);
    setGaErrors([]);
    setGaResult(null);
  };

  // ── Picture Tracker handlers ──────────────────────────────────────────────
  const handlePtFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (ev) => setPtCsvText(ev.target?.result as string ?? "");
    reader.readAsText(file);
    e.target.value = "";
  };

  const handlePtParse = useCallback(() => {
    const { rows: parsed, errors } = parsePictureTrackerCsv(ptCsvText, existingShotCodes);
    setPtErrors(errors);
    setPtRows(parsed);
    if (parsed.length > 0) setPtStep("preview");
  }, [ptCsvText, existingShotCodes]);

  const handlePtImport = async () => {
    setPtImporting(true);
    try {
      const toUpdate = ptRows.filter((r) => r.exists);
      const res = await updateShotsSeqTimecodes(projectId, toUpdate);
      // Rows that parsed but didn't exist are also skipped
      const notFound = ptRows.filter((r) => !r.exists).map((r) => r.shotCode);
      const combined = { ...res, skipped: [...notFound, ...res.skipped] };
      setPtResult(combined);
      setPtStep("result");
      if (res.updated.length > 0) {
        toast({
          title: "Timecodes updated",
          description: `${res.updated.length} shot${res.updated.length !== 1 ? "s" : ""} updated`,
        });
      }
    } catch (e) {
      toast({ title: "Update failed", description: e instanceof Error ? e.message : undefined, variant: "destructive" });
    } finally {
      setPtImporting(false);
    }
  };

  const handlePtReset = () => {
    setPtStep("input");
    setPtCsvText("");
    setPtRows([]);
    setPtErrors([]);
    setPtResult(null);
  };

  const counts = {
    create: rows.filter((r) => r.action === "create").length,
    update: rows.filter((r) => r.action === "update").length,
    skip:   rows.filter((r) => r.action === "skip").length,
  };

  return (
    <div className="min-h-screen bg-background">
      <div className="max-w-5xl mx-auto p-6 space-y-6">
        {/* Breadcrumb */}
        <div className="flex items-center gap-2 text-sm text-zinc-500">
          <Link href="/projects" className="hover:text-white transition-colors">Projects</Link>
          <span>/</span>
          <Link href={`/projects/${projectId}`} className="hover:text-white transition-colors">{projectName}</Link>
          <span>/</span>
          <span className="text-zinc-300">Import VFX Pull</span>
        </div>

        {/* Header */}
        <div className="flex items-center gap-3">
          <Button variant="ghost" size="icon" className="h-8 w-8 -ml-2" asChild>
            <Link href={`/projects/${projectId}`}><ArrowLeft className="h-4 w-4" /></Link>
          </Button>
          <div>
            <h1 className="text-xl font-bold text-white">Import VFX Pull CSV</h1>
            <p className="text-sm text-zinc-500 mt-0.5">Paste or upload a Colorfront VFX pull CSV to create or update shots</p>
          </div>
        </div>

        {/* ── STEP 1: Input ─────────────────────────────────────────────────── */}
        {step === "input" && (
          <div className="space-y-4">
            <div className="rounded-xl border border-zinc-800 bg-zinc-900 p-5 space-y-4">
              <div className="flex items-center justify-between">
                <p className="text-sm font-medium text-zinc-300">Paste CSV or upload file</p>
                <div className="flex items-center gap-2">
                  <input
                    ref={fileInputRef}
                    type="file"
                    accept=".csv,text/csv"
                    className="hidden"
                    onChange={handleFileUpload}
                  />
                  <Button
                    variant="outline"
                    size="sm"
                    className="gap-1.5 h-7"
                    onClick={() => fileInputRef.current?.click()}
                  >
                    <Upload className="h-3.5 w-3.5" />
                    Upload .csv
                  </Button>
                </div>
              </div>

              <Textarea
                value={csvText}
                onChange={(e) => setCsvText(e.target.value)}
                placeholder={`Events,"Deliverable Name","Output Name","Source Clip","Timecode Start","Timecode End",Duration,CDL,Status,Trimmed\n000001,VFX_Pull_Default_EXR,"UNG_108_001_010_BG01_TT_v001",A315C001_260313H1,...`}
                className="font-mono text-xs min-h-[280px] bg-zinc-950 border-zinc-700 resize-y"
                spellCheck={false}
              />

              <div className="rounded-lg bg-zinc-950 border border-zinc-800 p-3 text-xs text-zinc-400 space-y-1">
                <p className="font-medium text-zinc-300">Expected format</p>
                <p>Columns required: <span className="font-mono text-amber-400">Output Name</span>, <span className="font-mono text-amber-400">Source Clip</span></p>
                <p>Optional: <span className="font-mono text-zinc-400">Timecode Start, Timecode End, Duration</span></p>
                <p className="mt-1.5">Shot code is derived from the first 4 segments of Output Name, e.g. <span className="font-mono text-zinc-300">UNG_108_030_060_BG01_TT_v001</span> → <span className="font-mono text-emerald-400">UNG_108_030_060</span></p>
                <p>EXR Output = <span className="font-mono text-zinc-300">{"{shot_code}_{source_clip}"}</span></p>
              </div>
            </div>

            <div className="flex justify-end">
              <Button onClick={handleParse} disabled={!csvText.trim()} className="gap-2">
                <Film className="h-4 w-4" />
                Parse &amp; Preview
              </Button>
            </div>
          </div>
        )}

        {/* ── STEP 2: Preview ───────────────────────────────────────────────── */}
        {step === "preview" && (
          <div className="space-y-4">
            {/* Summary bar */}
            <div className="flex flex-wrap items-center gap-3">
              <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 text-sm">
                <FilePlus2 className="h-3.5 w-3.5" />
                {counts.create} to create
              </div>
              <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-blue-500/10 border border-blue-500/20 text-blue-400 text-sm">
                <Pencil className="h-3.5 w-3.5" />
                {counts.update} to update
              </div>
              {counts.skip > 0 && (
                <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-zinc-500/10 border border-zinc-500/20 text-zinc-400 text-sm">
                  <SkipForward className="h-3.5 w-3.5" />
                  {counts.skip} to skip
                </div>
              )}
              <div className="ml-auto flex items-center gap-2">
                <span className="text-xs text-zinc-500">Set all:</span>
                <Button variant="outline" size="sm" className="h-7 text-xs gap-1" onClick={() => setAllAction("create")}>Create</Button>
                <Button variant="outline" size="sm" className="h-7 text-xs gap-1" onClick={() => setAllAction("update")}>Update</Button>
                <Button variant="outline" size="sm" className="h-7 text-xs gap-1" onClick={() => setAllAction("skip")}>Skip</Button>
              </div>
            </div>

            {parseErrors.length > 0 && (
              <div className="rounded-lg bg-red-500/10 border border-red-500/20 p-3 space-y-1">
                <p className="text-xs font-medium text-red-400 flex items-center gap-1.5">
                  <AlertCircle className="h-3.5 w-3.5" /> {parseErrors.length} parse warning{parseErrors.length !== 1 ? "s" : ""}
                </p>
                {parseErrors.map((e, i) => <p key={i} className="text-xs text-red-300 pl-5">{e}</p>)}
              </div>
            )}

            {/* Table */}
            <div className="rounded-xl border border-zinc-800 overflow-hidden">
              <div className="grid grid-cols-[auto_1fr_1fr_1fr_1fr_auto] text-xs font-medium text-zinc-500 uppercase tracking-wider bg-zinc-900 px-4 py-2.5 gap-4 border-b border-zinc-800">
                <span>Action</span>
                <span>Shot Code</span>
                <span>EXR Output</span>
                <span>TC In → Out</span>
                <span>Duration</span>
                <span>Source Clip</span>
              </div>
              <div className="divide-y divide-zinc-800/60 bg-zinc-950/40 max-h-[480px] overflow-y-auto">
                {rows.map((row, i) => {
                  const ActionIcon = ACTION_ICONS[row.action];
                  return (
                    <div
                      key={i}
                      className="grid grid-cols-[auto_1fr_1fr_1fr_1fr_auto] items-center gap-4 px-4 py-3 text-sm"
                    >
                      {/* Action badge — click to cycle */}
                      <button
                        onClick={() => toggleAction(i)}
                        title="Click to cycle: create → update → skip"
                        className={cn(
                          "inline-flex items-center gap-1.5 px-2 py-0.5 rounded border text-xs font-medium transition-colors shrink-0",
                          ACTION_STYLES[row.action]
                        )}
                      >
                        <ActionIcon className="h-3 w-3" />
                        {row.action}
                      </button>

                      <span className="font-mono text-xs text-zinc-200 truncate">{row.shotCode}</span>
                      <span className="font-mono text-xs text-zinc-400 truncate">{row.exrOutput}</span>
                      <span className="font-mono text-xs text-zinc-500 truncate">
                        {row.timecodeStart && row.timecodeEnd
                          ? `${row.timecodeStart} → ${row.timecodeEnd}`
                          : "—"}
                      </span>
                      <span className="font-mono text-xs text-zinc-500">{row.clipDuration || "—"}</span>
                      <span className="font-mono text-xs text-zinc-500 truncate">{row.sourceClip || "—"}</span>
                    </div>
                  );
                })}
              </div>
            </div>

            <div className="flex items-center justify-between">
              <Button variant="outline" onClick={handleReset}>
                <ArrowLeft className="h-4 w-4 mr-1.5" /> Back
              </Button>
              <Button
                onClick={handleImport}
                disabled={importing || (counts.create + counts.update === 0)}
                className="gap-2"
              >
                {importing ? <RefreshCw className="h-4 w-4 animate-spin" /> : <Upload className="h-4 w-4" />}
                {importing ? "Importing…" : `Import ${counts.create + counts.update} shot${counts.create + counts.update !== 1 ? "s" : ""}`}
              </Button>
            </div>
          </div>
        )}

        {/* ── STEP 3: Result ───────────────────────────────────────────────── */}
        {step === "result" && result && (
          <div className="space-y-4">
            <div className="rounded-xl border border-zinc-800 bg-zinc-900 p-6 space-y-5">
              <h2 className="text-base font-semibold text-white flex items-center gap-2">
                <CheckCircle2 className="h-5 w-5 text-emerald-400" />
                Import complete
              </h2>

              {result.created.length > 0 && (
                <div className="space-y-2">
                  <p className="text-xs font-medium text-emerald-400 uppercase tracking-wide">
                    Created ({result.created.length})
                  </p>
                  <div className="flex flex-wrap gap-1.5">
                    {result.created.map((c) => (
                      <span key={c} className="font-mono text-xs px-2 py-0.5 rounded bg-emerald-500/10 border border-emerald-500/20 text-emerald-300">{c}</span>
                    ))}
                  </div>
                </div>
              )}

              {result.updated.length > 0 && (
                <div className="space-y-2">
                  <p className="text-xs font-medium text-blue-400 uppercase tracking-wide">
                    Updated ({result.updated.length})
                  </p>
                  <div className="flex flex-wrap gap-1.5">
                    {result.updated.map((c) => (
                      <span key={c} className="font-mono text-xs px-2 py-0.5 rounded bg-blue-500/10 border border-blue-500/20 text-blue-300">{c}</span>
                    ))}
                  </div>
                </div>
              )}

              {result.skipped.length > 0 && (
                <div className="space-y-2">
                  <p className="text-xs font-medium text-zinc-500 uppercase tracking-wide">
                    Skipped ({result.skipped.length})
                  </p>
                  <div className="flex flex-wrap gap-1.5">
                    {result.skipped.map((c) => (
                      <span key={c} className="font-mono text-xs px-2 py-0.5 rounded bg-zinc-800 border border-zinc-700 text-zinc-400">{c}</span>
                    ))}
                  </div>
                </div>
              )}

              {result.errors.length > 0 && (
                <div className="space-y-2">
                  <p className="text-xs font-medium text-red-400 uppercase tracking-wide flex items-center gap-1.5">
                    <AlertCircle className="h-3.5 w-3.5" /> Errors ({result.errors.length})
                  </p>
                  {result.errors.map((e, i) => (
                    <p key={i} className="text-xs text-red-300 pl-5">{e}</p>
                  ))}
                </div>
              )}
            </div>

            <div className="flex items-center gap-3">
              <Button variant="outline" onClick={handleReset}>
                Import Another
              </Button>
              <Button onClick={() => router.push(`/projects/${projectId}`)}>
                Back to Project
              </Button>
            </div>
          </div>
        )}

        {/* ── SIMPLE CSV PANEL ──────────────────────────────────────────── */}
        <div className="pt-6 border-t border-zinc-800 space-y-4">
          <div>
            <h2 className="text-base font-semibold text-white">Import Shots from Simple CSV</h2>
            <p className="text-sm text-zinc-500 mt-0.5">
              Create or update shots from a CSV with <span className="font-mono text-zinc-300">Shot Name</span>, <span className="font-mono text-zinc-300">Time Code In</span>, <span className="font-mono text-zinc-300">Time Code Out</span>, <span className="font-mono text-zinc-300">Description</span>.
            </p>
          </div>

          {scStep === "input" && (
            <div className="space-y-4">
              <div className="rounded-xl border border-zinc-800 bg-zinc-900 p-5 space-y-4">
                <div className="flex items-center justify-between">
                  <p className="text-sm font-medium text-zinc-300">Paste CSV or upload file</p>
                  <div className="flex items-center gap-2">
                    <input ref={scFileInputRef} type="file" accept=".csv,text/csv" className="hidden" onChange={handleScFileUpload} />
                    <Button variant="outline" size="sm" className="gap-1.5 h-7" onClick={() => scFileInputRef.current?.click()}>
                      <Upload className="h-3.5 w-3.5" />
                      Upload .csv
                    </Button>
                  </div>
                </div>

                <Textarea
                  value={scCsvText}
                  onChange={(e) => setScCsvText(e.target.value)}
                  placeholder={`Shot Name,Time Code In,Time Code Out,Description\nUNG_108_001_010,01:00:10:00,01:00:20:00,Hero wide shot`}
                  className="font-mono text-xs min-h-[200px] bg-zinc-950 border-zinc-700 resize-y"
                  spellCheck={false}
                />

                <div className="rounded-lg bg-zinc-950 border border-zinc-800 p-3 text-xs text-zinc-400 space-y-1">
                  <p className="font-medium text-zinc-300">Expected format</p>
                  <p>Required: <span className="font-mono text-amber-400">Shot Name</span></p>
                  <p>Optional: <span className="font-mono text-zinc-400">Time Code In, Time Code Out, Description</span></p>
                  <p>Existing shots will be set to <span className="font-mono text-blue-400">update</span>; new shots to <span className="font-mono text-emerald-400">create</span>. Toggle per row in the preview.</p>
                </div>
              </div>

              <div className="flex justify-end">
                <Button onClick={handleScParse} disabled={!scCsvText.trim()} className="gap-2">
                  <FileSpreadsheet className="h-4 w-4" />
                  Parse &amp; Preview
                </Button>
              </div>
            </div>
          )}

          {scStep === "preview" && (() => {
            const scCreate = scRows.filter((r) => r.action === "create").length;
            const scUpdate = scRows.filter((r) => r.action === "update").length;
            const scSkip   = scRows.filter((r) => r.action === "skip").length;
            return (
              <div className="space-y-4">
                <div className="flex flex-wrap items-center gap-3">
                  <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 text-sm">
                    <FilePlus2 className="h-3.5 w-3.5" />
                    {scCreate} to create
                  </div>
                  <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-blue-500/10 border border-blue-500/20 text-blue-400 text-sm">
                    <Pencil className="h-3.5 w-3.5" />
                    {scUpdate} to update
                  </div>
                  {scSkip > 0 && (
                    <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-zinc-500/10 border border-zinc-500/20 text-zinc-400 text-sm">
                      <SkipForward className="h-3.5 w-3.5" />
                      {scSkip} to skip
                    </div>
                  )}
                </div>

                {scErrors.length > 0 && (
                  <div className="rounded-lg bg-red-500/10 border border-red-500/20 p-3 space-y-1">
                    <p className="text-xs font-medium text-red-400 flex items-center gap-1.5">
                      <AlertCircle className="h-3.5 w-3.5" /> {scErrors.length} parse warning{scErrors.length !== 1 ? "s" : ""}
                    </p>
                    {scErrors.map((e, i) => <p key={i} className="text-xs text-red-300 pl-5">{e}</p>)}
                  </div>
                )}

                <div className="rounded-xl border border-zinc-800 overflow-hidden">
                  <div className="grid grid-cols-[auto_1fr_1fr_1fr_1fr_1fr] text-xs font-medium text-zinc-500 uppercase tracking-wider bg-zinc-900 px-4 py-2.5 gap-4 border-b border-zinc-800">
                    <span>Action</span>
                    <span>Shot Code</span>
                    <span>Seq TC In</span>
                    <span>Seq TC Out</span>
                    <span>Group</span>
                    <span>Description</span>
                  </div>
                  <div className="divide-y divide-zinc-800/60 bg-zinc-950/40 max-h-[400px] overflow-y-auto">
                    {scRows.map((row, i) => {
                      const ActionIcon = ACTION_ICONS[row.action];
                      return (
                        <div key={i} className="grid grid-cols-[auto_1fr_1fr_1fr_1fr_1fr] items-center gap-4 px-4 py-3 text-sm">
                          <button
                            onClick={() => toggleScAction(i)}
                            title="Click to cycle: create → update → skip"
                            className={cn(
                              "inline-flex items-center gap-1.5 px-2 py-0.5 rounded border text-xs font-medium transition-colors shrink-0",
                              ACTION_STYLES[row.action]
                            )}
                          >
                            <ActionIcon className="h-3 w-3" />
                            {row.action}
                          </button>
                          <span className="font-mono text-xs text-zinc-200 truncate">{row.shotCode}</span>
                          <span className="font-mono text-xs text-zinc-400">{row.seqTimecodeStart || "—"}</span>
                          <span className="font-mono text-xs text-zinc-400">{row.seqTimecodeEnd || "—"}</span>
                          <span className="text-xs text-zinc-300 truncate">{row.group || <span className="text-zinc-600">none</span>}</span>
                          <span className="text-xs text-zinc-500 truncate">{row.description || "—"}</span>
                        </div>
                      );
                    })}
                  </div>
                </div>

                <div className="flex items-center justify-between">
                  <Button variant="outline" onClick={handleScReset}>
                    <ArrowLeft className="h-4 w-4 mr-1.5" /> Back
                  </Button>
                  <Button
                    onClick={handleScImport}
                    disabled={scImporting || (scCreate + scUpdate === 0)}
                    className="gap-2"
                  >
                    {scImporting ? <RefreshCw className="h-4 w-4 animate-spin" /> : <Upload className="h-4 w-4" />}
                    {scImporting ? "Importing…" : `Import ${scCreate + scUpdate} shot${scCreate + scUpdate !== 1 ? "s" : ""}`}
                  </Button>
                </div>
              </div>
            );
          })()}

          {scStep === "result" && scResult && (
            <div className="space-y-4">
              <div className="rounded-xl border border-zinc-800 bg-zinc-900 p-6 space-y-5">
                <h2 className="text-base font-semibold text-white flex items-center gap-2">
                  <CheckCircle2 className="h-5 w-5 text-emerald-400" />
                  Import complete
                </h2>
                {scResult.created.length > 0 && (
                  <div className="space-y-2">
                    <p className="text-xs font-medium text-emerald-400 uppercase tracking-wide">Created ({scResult.created.length})</p>
                    <div className="flex flex-wrap gap-1.5">
                      {scResult.created.map((c) => (
                        <span key={c} className="font-mono text-xs px-2 py-0.5 rounded bg-emerald-500/10 border border-emerald-500/20 text-emerald-300">{c}</span>
                      ))}
                    </div>
                  </div>
                )}
                {scResult.updated.length > 0 && (
                  <div className="space-y-2">
                    <p className="text-xs font-medium text-blue-400 uppercase tracking-wide">Updated ({scResult.updated.length})</p>
                    <div className="flex flex-wrap gap-1.5">
                      {scResult.updated.map((c) => (
                        <span key={c} className="font-mono text-xs px-2 py-0.5 rounded bg-blue-500/10 border border-blue-500/20 text-blue-300">{c}</span>
                      ))}
                    </div>
                  </div>
                )}
                {scResult.skipped.length > 0 && (
                  <div className="space-y-2">
                    <p className="text-xs font-medium text-zinc-500 uppercase tracking-wide">Skipped ({scResult.skipped.length})</p>
                    <div className="flex flex-wrap gap-1.5">
                      {scResult.skipped.map((c) => (
                        <span key={c} className="font-mono text-xs px-2 py-0.5 rounded bg-zinc-800 border border-zinc-700 text-zinc-400">{c}</span>
                      ))}
                    </div>
                  </div>
                )}
                {scResult.errors.length > 0 && (
                  <div className="space-y-2">
                    <p className="text-xs font-medium text-red-400 uppercase tracking-wide flex items-center gap-1.5">
                      <AlertCircle className="h-3.5 w-3.5" /> Errors ({scResult.errors.length})
                    </p>
                    {scResult.errors.map((e, i) => (
                      <p key={i} className="text-xs text-red-300 pl-5">{e}</p>
                    ))}
                  </div>
                )}
              </div>
              <div className="flex items-center gap-3">
                <Button variant="outline" onClick={handleScReset}>Import Another</Button>
                <Button onClick={() => router.push(`/projects/${projectId}`)}>Back to Project</Button>
              </div>
            </div>
          )}
        </div>

        {/* ── GROUP ASSIGNMENT PANEL ─────────────────────────────────────── */}
        <div className="pt-6 border-t border-zinc-800 space-y-4">
          <div>
            <h2 className="text-base font-semibold text-white">Assign Shots to Groups</h2>
            <p className="text-sm text-zinc-500 mt-0.5">
              Bulk-assign existing shots to groups from a CSV with <span className="font-mono text-zinc-300">Shot Name</span> and <span className="font-mono text-zinc-300">Group</span> columns. Groups are created automatically if they don’t exist.
            </p>
          </div>

          {gaStep === "input" && (
            <div className="space-y-4">
              <div className="rounded-xl border border-zinc-800 bg-zinc-900 p-5 space-y-4">
                <div className="flex items-center justify-between">
                  <p className="text-sm font-medium text-zinc-300">Paste CSV or upload file</p>
                  <div className="flex items-center gap-2">
                    <input ref={gaFileInputRef} type="file" accept=".csv,text/csv" className="hidden" onChange={handleGaFileUpload} />
                    <Button variant="outline" size="sm" className="gap-1.5 h-7" onClick={() => gaFileInputRef.current?.click()}>
                      <Upload className="h-3.5 w-3.5" />
                      Upload .csv
                    </Button>
                  </div>
                </div>

                <Textarea
                  value={gaCsvText}
                  onChange={(e) => setGaCsvText(e.target.value)}
                  placeholder={`Shot Name,Group\nUNG_108_001_010,Action Sequences\nUNG_108_002_020,Compositing`}
                  className="font-mono text-xs min-h-[180px] bg-zinc-950 border-zinc-700 resize-y"
                  spellCheck={false}
                />

                <div className="rounded-lg bg-zinc-950 border border-zinc-800 p-3 text-xs text-zinc-400 space-y-1">
                  <p className="font-medium text-zinc-300">Expected format</p>
                  <p>Required: <span className="font-mono text-amber-400">Shot Name</span>, <span className="font-mono text-amber-400">Group</span></p>
                  <p>Only shots that already exist in this project are updated. Unknown shots are skipped.</p>
                </div>
              </div>

              <div className="flex justify-end">
                <Button onClick={handleGaParse} disabled={!gaCsvText.trim()} className="gap-2">
                  <Film className="h-4 w-4" />
                  Parse &amp; Preview
                </Button>
              </div>
            </div>
          )}

          {gaStep === "preview" && (
            <div className="space-y-4">
              <div className="flex flex-wrap items-center gap-3">
                <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-blue-500/10 border border-blue-500/20 text-blue-400 text-sm">
                  <Pencil className="h-3.5 w-3.5" />
                  {gaRows.filter((r) => r.exists).length} to assign
                </div>
                {gaRows.filter((r) => !r.exists).length > 0 && (
                  <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-zinc-500/10 border border-zinc-500/20 text-zinc-400 text-sm">
                    <SkipForward className="h-3.5 w-3.5" />
                    {gaRows.filter((r) => !r.exists).length} not found (will skip)
                  </div>
                )}
              </div>

              {gaErrors.length > 0 && (
                <div className="rounded-lg bg-red-500/10 border border-red-500/20 p-3 space-y-1">
                  <p className="text-xs font-medium text-red-400 flex items-center gap-1.5">
                    <AlertCircle className="h-3.5 w-3.5" /> {gaErrors.length} parse warning{gaErrors.length !== 1 ? "s" : ""}
                  </p>
                  {gaErrors.map((e, i) => <p key={i} className="text-xs text-red-300 pl-5">{e}</p>)}
                </div>
              )}

              <div className="rounded-xl border border-zinc-800 overflow-hidden">
                <div className="grid grid-cols-[1fr_1fr_auto] text-xs font-medium text-zinc-500 uppercase tracking-wider bg-zinc-900 px-4 py-2.5 gap-4 border-b border-zinc-800">
                  <span>Shot Code</span>
                  <span>Group</span>
                  <span>Status</span>
                </div>
                <div className="divide-y divide-zinc-800/60 bg-zinc-950/40 max-h-[400px] overflow-y-auto">
                  {gaRows.map((row, i) => (
                    <div key={i} className="grid grid-cols-[1fr_1fr_auto] items-center gap-4 px-4 py-3 text-sm">
                      <span className="font-mono text-xs text-zinc-200">{row.shotCode}</span>
                      <span className="text-xs text-zinc-300">{row.groupName}</span>
                      {row.exists ? (
                        <span className="inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded border bg-blue-500/10 text-blue-400 border-blue-500/20">
                          <Pencil className="h-3 w-3" /> assign
                        </span>
                      ) : (
                        <span className="inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded border bg-zinc-500/10 text-zinc-400 border-zinc-500/20">
                          <SkipForward className="h-3 w-3" /> skip
                        </span>
                      )}
                    </div>
                  ))}
                </div>
              </div>

              <div className="flex items-center justify-between">
                <Button variant="outline" onClick={handleGaReset}>
                  <ArrowLeft className="h-4 w-4 mr-1.5" /> Back
                </Button>
                <Button
                  onClick={handleGaAssign}
                  disabled={gaAssigning || gaRows.filter((r) => r.exists).length === 0}
                  className="gap-2"
                >
                  {gaAssigning ? <RefreshCw className="h-4 w-4 animate-spin" /> : <Upload className="h-4 w-4" />}
                  {gaAssigning
                    ? "Assigning…"
                    : `Assign ${gaRows.filter((r) => r.exists).length} shot${gaRows.filter((r) => r.exists).length !== 1 ? "s" : ""}`}
                </Button>
              </div>
            </div>
          )}

          {gaStep === "result" && gaResult && (
            <div className="space-y-4">
              <div className="rounded-xl border border-zinc-800 bg-zinc-900 p-6 space-y-5">
                <h2 className="text-base font-semibold text-white flex items-center gap-2">
                  <CheckCircle2 className="h-5 w-5 text-emerald-400" />
                  Group assignment complete
                </h2>
                {gaResult.assigned.length > 0 && (
                  <div className="space-y-2">
                    <p className="text-xs font-medium text-blue-400 uppercase tracking-wide">Assigned ({gaResult.assigned.length})</p>
                    <div className="flex flex-wrap gap-1.5">
                      {gaResult.assigned.map((c) => (
                        <span key={c} className="font-mono text-xs px-2 py-0.5 rounded bg-blue-500/10 border border-blue-500/20 text-blue-300">{c}</span>
                      ))}
                    </div>
                  </div>
                )}
                {gaResult.skipped.length > 0 && (
                  <div className="space-y-2">
                    <p className="text-xs font-medium text-zinc-500 uppercase tracking-wide">Skipped / not found ({gaResult.skipped.length})</p>
                    <div className="flex flex-wrap gap-1.5">
                      {gaResult.skipped.map((c) => (
                        <span key={c} className="font-mono text-xs px-2 py-0.5 rounded bg-zinc-800 border border-zinc-700 text-zinc-400">{c}</span>
                      ))}
                    </div>
                  </div>
                )}
                {gaResult.errors.length > 0 && (
                  <div className="space-y-2">
                    <p className="text-xs font-medium text-red-400 uppercase tracking-wide flex items-center gap-1.5">
                      <AlertCircle className="h-3.5 w-3.5" /> Errors ({gaResult.errors.length})
                    </p>
                    {gaResult.errors.map((e, i) => (
                      <p key={i} className="text-xs text-red-300 pl-5">{e}</p>
                    ))}
                  </div>
                )}
              </div>
              <div className="flex items-center gap-3">
                <Button variant="outline" onClick={handleGaReset}>Import Another</Button>
                <Button onClick={() => router.push(`/projects/${projectId}`)}>Back to Project</Button>
              </div>
            </div>
          )}
        </div>

        {/* ── PICTURE TRACKER PANEL ─────────────────────────────────────── */}
        <div className="pt-6 border-t border-zinc-800 space-y-4">
          <div>
            <h2 className="text-base font-semibold text-white">Import Picture Tracker Timecodes</h2>
            <p className="text-sm text-zinc-500 mt-0.5">
              Paste a picture tracker CSV to update <span className="font-mono text-zinc-300">seqTimecodeStart</span> / <span className="font-mono text-zinc-300">seqTimecodeEnd</span> on existing shots only.
            </p>
          </div>

          {/* PT STEP 1: Input */}
          {ptStep === "input" && (
            <div className="space-y-4">
              <div className="rounded-xl border border-zinc-800 bg-zinc-900 p-5 space-y-4">
                <div className="flex items-center justify-between">
                  <p className="text-sm font-medium text-zinc-300">Paste CSV or upload file</p>
                  <div className="flex items-center gap-2">
                    <input
                      ref={ptFileInputRef}
                      type="file"
                      accept=".csv,text/csv"
                      className="hidden"
                      onChange={handlePtFileUpload}
                    />
                    <Button
                      variant="outline"
                      size="sm"
                      className="gap-1.5 h-7"
                      onClick={() => ptFileInputRef.current?.click()}
                    >
                      <Upload className="h-3.5 w-3.5" />
                      Upload .csv
                    </Button>
                  </div>
                </div>

                <Textarea
                  value={ptCsvText}
                  onChange={(e) => setPtCsvText(e.target.value)}
                  placeholder={`#,Thumbnail,Shot Name,TC In,TC Out,Duration,...\n1,,UNG_106_004_010,01:00:37:16,01:00:53:01,00:00:15:09,...`}
                  className="font-mono text-xs min-h-[200px] bg-zinc-950 border-zinc-700 resize-y"
                  spellCheck={false}
                />

                <div className="rounded-lg bg-zinc-950 border border-zinc-800 p-3 text-xs text-zinc-400 space-y-1">
                  <p className="font-medium text-zinc-300">Expected format</p>
                  <p>Columns required: <span className="font-mono text-amber-400">Shot Name</span>, <span className="font-mono text-amber-400">TC In</span>, <span className="font-mono text-amber-400">TC Out</span></p>
                  <p>Only shots that already exist in this project will be updated. Duplicate shot rows are ignored (first TC In/Out wins).</p>
                </div>
              </div>

              <div className="flex justify-end">
                <Button onClick={handlePtParse} disabled={!ptCsvText.trim()} className="gap-2">
                  <Film className="h-4 w-4" />
                  Parse &amp; Preview
                </Button>
              </div>
            </div>
          )}

          {/* PT STEP 2: Preview */}
          {ptStep === "preview" && (
            <div className="space-y-4">
              <div className="flex flex-wrap items-center gap-3">
                <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-blue-500/10 border border-blue-500/20 text-blue-400 text-sm">
                  <Pencil className="h-3.5 w-3.5" />
                  {ptRows.filter((r) => r.exists).length} to update
                </div>
                {ptRows.filter((r) => !r.exists).length > 0 && (
                  <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-zinc-500/10 border border-zinc-500/20 text-zinc-400 text-sm">
                    <SkipForward className="h-3.5 w-3.5" />
                    {ptRows.filter((r) => !r.exists).length} not found (will skip)
                  </div>
                )}
              </div>

              {ptErrors.length > 0 && (
                <div className="rounded-lg bg-red-500/10 border border-red-500/20 p-3 space-y-1">
                  <p className="text-xs font-medium text-red-400 flex items-center gap-1.5">
                    <AlertCircle className="h-3.5 w-3.5" /> {ptErrors.length} parse warning{ptErrors.length !== 1 ? "s" : ""}
                  </p>
                  {ptErrors.map((e, i) => <p key={i} className="text-xs text-red-300 pl-5">{e}</p>)}
                </div>
              )}

              <div className="rounded-xl border border-zinc-800 overflow-hidden">
                <div className="grid grid-cols-[1fr_1fr_1fr_auto] text-xs font-medium text-zinc-500 uppercase tracking-wider bg-zinc-900 px-4 py-2.5 gap-4 border-b border-zinc-800">
                  <span>Shot Code</span>
                  <span>Seq TC In</span>
                  <span>Seq TC Out</span>
                  <span>Status</span>
                </div>
                <div className="divide-y divide-zinc-800/60 bg-zinc-950/40 max-h-[400px] overflow-y-auto">
                  {ptRows.map((row, i) => (
                    <div key={i} className="grid grid-cols-[1fr_1fr_1fr_auto] items-center gap-4 px-4 py-3 text-sm">
                      <span className="font-mono text-xs text-zinc-200">{row.shotCode}</span>
                      <span className="font-mono text-xs text-zinc-300">{row.seqTimecodeStart}</span>
                      <span className="font-mono text-xs text-zinc-300">{row.seqTimecodeEnd}</span>
                      {row.exists ? (
                        <span className="inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded border bg-blue-500/10 text-blue-400 border-blue-500/20">
                          <Pencil className="h-3 w-3" /> update
                        </span>
                      ) : (
                        <span className="inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded border bg-zinc-500/10 text-zinc-400 border-zinc-500/20">
                          <SkipForward className="h-3 w-3" /> skip
                        </span>
                      )}
                    </div>
                  ))}
                </div>
              </div>

              <div className="flex items-center justify-between">
                <Button variant="outline" onClick={handlePtReset}>
                  <ArrowLeft className="h-4 w-4 mr-1.5" /> Back
                </Button>
                <Button
                  onClick={handlePtImport}
                  disabled={ptImporting || ptRows.filter((r) => r.exists).length === 0}
                  className="gap-2"
                >
                  {ptImporting ? <RefreshCw className="h-4 w-4 animate-spin" /> : <Upload className="h-4 w-4" />}
                  {ptImporting
                    ? "Updating…"
                    : `Update ${ptRows.filter((r) => r.exists).length} shot${ptRows.filter((r) => r.exists).length !== 1 ? "s" : ""}`}
                </Button>
              </div>
            </div>
          )}

          {/* PT STEP 3: Result */}
          {ptStep === "result" && ptResult && (
            <div className="space-y-4">
              <div className="rounded-xl border border-zinc-800 bg-zinc-900 p-6 space-y-5">
                <h2 className="text-base font-semibold text-white flex items-center gap-2">
                  <CheckCircle2 className="h-5 w-5 text-emerald-400" />
                  Timecode update complete
                </h2>

                {ptResult.updated.length > 0 && (
                  <div className="space-y-2">
                    <p className="text-xs font-medium text-blue-400 uppercase tracking-wide">
                      Updated ({ptResult.updated.length})
                    </p>
                    <div className="flex flex-wrap gap-1.5">
                      {ptResult.updated.map((c) => (
                        <span key={c} className="font-mono text-xs px-2 py-0.5 rounded bg-blue-500/10 border border-blue-500/20 text-blue-300">{c}</span>
                      ))}
                    </div>
                  </div>
                )}

                {ptResult.skipped.length > 0 && (
                  <div className="space-y-2">
                    <p className="text-xs font-medium text-zinc-500 uppercase tracking-wide">
                      Skipped / not found ({ptResult.skipped.length})
                    </p>
                    <div className="flex flex-wrap gap-1.5">
                      {ptResult.skipped.map((c) => (
                        <span key={c} className="font-mono text-xs px-2 py-0.5 rounded bg-zinc-800 border border-zinc-700 text-zinc-400">{c}</span>
                      ))}
                    </div>
                  </div>
                )}

                {ptResult.errors.length > 0 && (
                  <div className="space-y-2">
                    <p className="text-xs font-medium text-red-400 uppercase tracking-wide flex items-center gap-1.5">
                      <AlertCircle className="h-3.5 w-3.5" /> Errors ({ptResult.errors.length})
                    </p>
                    {ptResult.errors.map((e, i) => (
                      <p key={i} className="text-xs text-red-300 pl-5">{e}</p>
                    ))}
                  </div>
                )}
              </div>

              <div className="flex items-center gap-3">
                <Button variant="outline" onClick={handlePtReset}>
                  Import Another
                </Button>
                <Button onClick={() => router.push(`/projects/${projectId}`)}>
                  Back to Project
                </Button>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
