import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useState, useCallback, useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Upload, FileText, X, CheckCircle2, Loader2 } from "lucide-react";
import { PageHeader } from "@/components/common/PageBits";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import { documentsService } from "@/services";
import { toast } from "sonner";
import { cn } from "@/lib/utils";

export const Route = createFileRoute("/_app/documents/upload")({
  head: () => ({ meta: [{ title: "Upload — Study Unique" }] }),
  component: UploadPage,
});

interface UploadItem {
  id: string;
  name: string;
  sizeKb: number;
  type: string;
  progress: number;
  status: "uploading" | "done" | "error";
}

function UploadPage() {
  const qc = useQueryClient();
  const navigate = useNavigate();
  const [dragOver, setDragOver] = useState(false);
  const [items, setItems] = useState<UploadItem[]>([]);
  const inputRef = useRef<HTMLInputElement>(null);

  const upload = useMutation({
    mutationFn: documentsService.upload,
    onSuccess: () => qc.invalidateQueries({ queryKey: ["documents"] }),
  });

  const handleFiles = useCallback(
    (files: FileList | File[]) => {
      const arr = Array.from(files);
      arr.forEach((f) => {
        const id = Math.random().toString(36).slice(2);
        const ext = f.name.split(".").pop()?.toLowerCase() ?? "pdf";
        const item: UploadItem = {
          id,
          name: f.name,
          sizeKb: Math.max(1, Math.round(f.size / 1024)),
          type: ext,
          progress: 0,
          status: "uploading",
        };
        setItems((prev) => [item, ...prev]);

        // Simulate progress
        const interval = setInterval(() => {
          setItems((prev) =>
            prev.map((it) => {
              if (it.id !== id) return it;
              const next = Math.min(100, it.progress + 8 + Math.random() * 12);
              return { ...it, progress: next };
            }),
          );
        }, 180);

        upload.mutate(
          { name: f.name, sizeKb: item.sizeKb, type: ext },
          {
            onSettled: () => {
              clearInterval(interval);
              setItems((prev) =>
                prev.map((it) =>
                  it.id === id ? { ...it, progress: 100, status: "done" } : it,
                ),
              );
              toast.success(`${f.name} uploaded`);
            },
          },
        );
      });
    },
    [upload],
  );

  return (
    <div className="mx-auto w-full max-w-4xl space-y-6 p-4 md:p-6">
      <PageHeader
        title="Upload documents"
        description="PDF, DOCX, PPTX, TXT or Markdown — up to 50 MB each."
      />

      <div
        onDragOver={(e) => {
          e.preventDefault();
          setDragOver(true);
        }}
        onDragLeave={() => setDragOver(false)}
        onDrop={(e) => {
          e.preventDefault();
          setDragOver(false);
          if (e.dataTransfer.files.length) handleFiles(e.dataTransfer.files);
        }}
        onClick={() => inputRef.current?.click()}
        className={cn(
          "relative flex cursor-pointer flex-col items-center justify-center rounded-3xl border-2 border-dashed bg-card/40 p-12 text-center transition-all",
          dragOver
            ? "border-primary bg-primary/5"
            : "border-border hover:border-primary/40 hover:bg-card/70",
        )}
      >
        <div className="absolute inset-0 -z-10 gradient-mesh opacity-30" aria-hidden />
        <div className="flex h-16 w-16 items-center justify-center rounded-2xl gradient-brand shadow-2xl shadow-primary/40">
          <Upload className="h-7 w-7 text-primary-foreground" />
        </div>
        <p className="mt-5 text-base font-semibold">Drag & drop files here</p>
        <p className="mt-1 text-sm text-muted-foreground">
          or click to browse from your device
        </p>
        <input
          ref={inputRef}
          type="file"
          multiple
          accept=".pdf,.docx,.pptx,.txt,.md"
          className="hidden"
          onChange={(e) => e.target.files && handleFiles(e.target.files)}
        />
        <div className="mt-6 flex flex-wrap items-center justify-center gap-2 text-[11px] text-muted-foreground">
          {["PDF", "DOCX", "PPTX", "TXT", "MD"].map((t) => (
            <span key={t} className="rounded-md border border-border bg-background px-2 py-1">
              {t}
            </span>
          ))}
        </div>
      </div>

      <AnimatePresence>
        {items.length > 0 && (
          <motion.div
            initial={{ opacity: 0, y: 6 }}
            animate={{ opacity: 1, y: 0 }}
            className="rounded-2xl border border-border bg-card"
          >
            <div className="border-b border-border p-4">
              <p className="text-sm font-semibold">Uploads</p>
            </div>
            <ul className="divide-y divide-border">
              {items.map((it) => (
                <li key={it.id} className="flex items-center gap-3 p-4">
                  <div className="flex h-10 w-10 items-center justify-center rounded-md bg-muted">
                    <FileText className="h-4 w-4" />
                  </div>
                  <div className="min-w-0 flex-1">
                    <div className="flex items-center justify-between gap-3">
                      <p className="truncate text-sm font-medium">{it.name}</p>
                      <span className="text-xs text-muted-foreground">
                        {(it.sizeKb / 1024).toFixed(2)} MB
                      </span>
                    </div>
                    <Progress value={it.progress} className="mt-2 h-1" />
                  </div>
                  {it.status === "uploading" ? (
                    <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
                  ) : (
                    <CheckCircle2 className="h-4 w-4 text-success" />
                  )}
                  <Button
                    size="icon"
                    variant="ghost"
                    className="h-7 w-7"
                    onClick={() => setItems((prev) => prev.filter((p) => p.id !== it.id))}
                  >
                    <X className="h-4 w-4" />
                  </Button>
                </li>
              ))}
            </ul>
            <div className="flex justify-end gap-2 p-4">
              <Button variant="outline" onClick={() => setItems([])}>
                Clear
              </Button>
              <Button
                className="gradient-brand text-primary-foreground"
                onClick={() => navigate({ to: "/documents" })}
                disabled={items.some((i) => i.status === "uploading")}
              >
                Go to library
              </Button>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}
