"use client";

import { useState, useCallback } from "react";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from "@/components/ui/dialog";
import { useToast } from "@/components/ui/use-toast";
import { Upload, FileVideo, X, CheckCircle2, Trash2 } from "lucide-react";
import { formatFileSize } from "@/lib/utils";
import { cn } from "@/lib/utils";

interface HighResUploadDialogProps {
  shotId: string;
  shotCode: string;
  currentFilename: string | null;
  open: boolean;
  onClose: () => void;
  onSuccess?: () => void;
}

export function HighResUploadDialog({
  shotId,
  shotCode,
  currentFilename,
  open,
  onClose,
  onSuccess,
}: HighResUploadDialogProps) {
  const [file, setFile] = useState<File | null>(null);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [uploadState, setUploadState] = useState<"idle" | "uploading" | "done" | "error">("idle");
  const [isDragOver, setIsDragOver] = useState(false);
  const [isRemoving, setIsRemoving] = useState(false);
  const { toast } = useToast();

  const handleFileSelect = (selected: File) => {
    if (!selected.type.startsWith("video/")) {
      toast({ title: "Please select a video file (.mov, .mp4, etc.)", variant: "destructive" });
      return;
    }
    if (selected.size > 50 * 1024 * 1024 * 1024) {
      // 50 GB sanity cap
      toast({ title: "File too large (max 50 GB)", variant: "destructive" });
      return;
    }
    setFile(selected);
  };

  const handleDrop = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    setIsDragOver(false);
    const dropped = e.dataTransfer.files[0];
    if (dropped) handleFileSelect(dropped);
  }, []);

  const handleUpload = async () => {
    if (!file) return;
    setUploadState("uploading");
    setUploadProgress(0);

    try {
      await uploadViaXhr(
        `/api/shots/${shotId}/highres`,
        file,
        (p) => setUploadProgress(Math.round(p * 100))
      );

      setUploadProgress(100);
      setUploadState("done");
      toast({ title: `High-res uploaded: ${file.name}` });
      setTimeout(() => {
        onSuccess?.();
        handleClose();
      }, 800);
    } catch (err) {
      setUploadState("error");
      toast({
        title: "Upload failed",
        description: (err as Error).message,
        variant: "destructive",
      });
    }
  };

  const handleRemove = async () => {
    setIsRemoving(true);
    try {
      const res = await fetch(`/api/shots/${shotId}/highres`, { method: "DELETE" });
      if (!res.ok) throw new Error("Remove failed");
      toast({ title: "High-res file removed" });
      onSuccess?.();
      handleClose();
    } catch (err) {
      toast({
        title: "Failed to remove",
        description: (err as Error).message,
        variant: "destructive",
      });
    } finally {
      setIsRemoving(false);
    }
  };

  const resetState = () => {
    setFile(null);
    setUploadProgress(0);
    setUploadState("idle");
  };

  const handleClose = () => {
    if (uploadState === "uploading") return;
    resetState();
    onClose();
  };

  return (
    <Dialog open={open} onOpenChange={(o) => !o && handleClose()}>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <FileVideo className="h-5 w-5 text-amber-500" />
            High Res File — {shotCode}
          </DialogTitle>
        </DialogHeader>

        <div className="space-y-4">
          {/* Current file info */}
          {currentFilename && !file && (
            <div className="flex items-center gap-3 rounded-lg border border-zinc-700 bg-zinc-800/50 px-4 py-3">
              <CheckCircle2 className="h-4 w-4 text-emerald-400 shrink-0" />
              <span className="flex-1 truncate font-mono text-sm text-zinc-200" title={currentFilename}>
                {currentFilename}
              </span>
              <Button
                variant="ghost"
                size="sm"
                className="h-7 text-xs text-red-400 hover:text-red-300 hover:bg-red-950/30 gap-1"
                disabled={isRemoving}
                onClick={handleRemove}
              >
                <Trash2 className="h-3.5 w-3.5" />
                {isRemoving ? "Removing…" : "Remove"}
              </Button>
            </div>
          )}

          {/* Drop zone */}
          {!file ? (
            <div
              onDragOver={(e) => { e.preventDefault(); setIsDragOver(true); }}
              onDragLeave={() => setIsDragOver(false)}
              onDrop={handleDrop}
              className={cn(
                "relative flex flex-col items-center justify-center rounded-lg border-2 border-dashed p-10 transition-colors cursor-pointer",
                isDragOver
                  ? "border-amber-500 bg-amber-500/10"
                  : "border-zinc-700 hover:border-amber-500/50 hover:bg-zinc-800/50"
              )}
              onClick={() => document.getElementById("highres-file-input")?.click()}
            >
              <input
                id="highres-file-input"
                type="file"
                accept="video/*,.mov"
                className="hidden"
                onChange={(e) => e.target.files?.[0] && handleFileSelect(e.target.files[0])}
              />
              <Upload className="h-8 w-8 text-zinc-500 mb-3" />
              <p className="text-sm font-medium text-white">
                {currentFilename ? "Drop replacement file here or click to browse" : "Drop high-res file here or click to browse"}
              </p>
              <p className="text-xs text-zinc-400 mt-1">MOV, MP4 or any video format</p>
            </div>
          ) : (
            <div className="flex items-center gap-3 rounded-lg border border-zinc-700 p-3 bg-zinc-800/50">
              <FileVideo className="h-8 w-8 text-amber-500 shrink-0" />
              <div className="flex-1 min-w-0">
                <p className="text-sm font-medium truncate text-white">{file.name}</p>
                <p className="text-xs text-zinc-400">{formatFileSize(file.size)}</p>
              </div>
              {uploadState === "idle" && (
                <Button variant="ghost" size="icon" onClick={() => setFile(null)} className="h-8 w-8">
                  <X className="h-4 w-4" />
                </Button>
              )}
              {uploadState === "done" && (
                <CheckCircle2 className="h-5 w-5 text-emerald-400" />
              )}
            </div>
          )}

          {/* Upload progress */}
          {(uploadState === "uploading" || uploadState === "done") && (
            <div className="space-y-2">
              <div className="flex items-center justify-between text-xs">
                <span className="text-zinc-400">
                  {uploadState === "uploading" ? "Uploading…" : "Complete!"}
                </span>
                <span className="text-amber-400 font-mono">{uploadProgress}%</span>
              </div>
              <Progress value={uploadProgress} />
            </div>
          )}
        </div>

        <DialogFooter>
          <Button variant="outline" onClick={handleClose} disabled={uploadState === "uploading" || isRemoving}>
            Cancel
          </Button>
          <Button
            onClick={handleUpload}
            disabled={!file || uploadState !== "idle"}
            className="gap-2"
          >
            <Upload className="h-4 w-4" />
            Upload
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

/** Upload a file via XHR so we get progress events. */
function uploadViaXhr(
  url: string,
  file: File,
  onProgress: (fraction: number) => void
): Promise<void> {
  return new Promise((resolve, reject) => {
    const formData = new FormData();
    formData.append("file", file);

    const xhr = new XMLHttpRequest();
    xhr.open("POST", url);

    xhr.upload.addEventListener("progress", (e) => {
      if (e.lengthComputable) onProgress(e.loaded / e.total);
    });

    xhr.addEventListener("load", () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve();
      } else {
        try {
          const json = JSON.parse(xhr.responseText);
          reject(new Error(json.error ?? `HTTP ${xhr.status}`));
        } catch {
          reject(new Error(`HTTP ${xhr.status}`));
        }
      }
    });

    xhr.addEventListener("error", () => reject(new Error("Network error")));
    xhr.addEventListener("abort", () => reject(new Error("Upload cancelled")));

    xhr.send(formData);
  });
}
