import { createFileRoute, Link } from "@tanstack/react-router";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useState, useMemo } from "react";
import { motion } from "framer-motion";
import {
  Search,
  Star,
  Upload,
  Trash2,
  Filter,
  MoreVertical,
  FileText,
  SlidersHorizontal,
} from "lucide-react";
import { PageHeader, EmptyState } from "@/components/common/PageBits";
import { documentsService } from "@/services";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Skeleton } from "@/components/ui/skeleton";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination";
import { toast } from "sonner";
import { formatDistanceToNow } from "date-fns";
import type { StudyDocument } from "@/types";

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

const PAGE_SIZE = 6;

function DocumentsPage() {
  const qc = useQueryClient();
  const { data, isLoading } = useQuery({
    queryKey: ["documents"],
    queryFn: documentsService.list,
  });

  const [q, setQ] = useState("");
  const [tag, setTag] = useState<string>("all");
  const [sort, setSort] = useState<"recent" | "name" | "size">("recent");
  const [tab, setTab] = useState<"all" | "favorites">("all");
  const [page, setPage] = useState(1);
  const [toDelete, setToDelete] = useState<StudyDocument | null>(null);

  const allTags = useMemo(() => {
    const s = new Set<string>();
    (data ?? []).forEach((d) => d.tags.forEach((t) => s.add(t)));
    return Array.from(s);
  }, [data]);

  const filtered = useMemo(() => {
    let list = data ?? [];
    if (tab === "favorites") list = list.filter((d) => d.favorite);
    if (tag !== "all") list = list.filter((d) => d.tags.includes(tag));
    if (q.trim()) {
      const k = q.toLowerCase();
      list = list.filter(
        (d) => d.title.toLowerCase().includes(k) || d.excerpt.toLowerCase().includes(k),
      );
    }
    list = [...list].sort((a, b) => {
      if (sort === "name") return a.title.localeCompare(b.title);
      if (sort === "size") return b.sizeKb - a.sizeKb;
      return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();
    });
    return list;
  }, [data, q, tag, sort, tab]);

  const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
  const pageItems = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);

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

  const removeMutation = useMutation({
    mutationFn: documentsService.remove,
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["documents"] });
      toast.success("Document deleted");
    },
  });

  return (
    <div className="mx-auto w-full max-w-7xl space-y-5 p-4 md:p-6">
      <PageHeader
        title="Documents"
        description="All your uploaded study materials in one place."
        actions={
          <Link to="/documents/upload">
            <Button className="gradient-brand text-primary-foreground">
              <Upload className="mr-1.5 h-4 w-4" /> Upload
            </Button>
          </Link>
        }
      />

      <div className="flex flex-col gap-3 md:flex-row md:items-center">
        <div className="relative flex-1">
          <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
          <Input
            value={q}
            onChange={(e) => {
              setQ(e.target.value);
              setPage(1);
            }}
            placeholder="Search documents…"
            className="pl-9"
          />
        </div>
        <div className="flex items-center gap-2">
          <Select value={tag} onValueChange={(v) => { setTag(v); setPage(1); }}>
            <SelectTrigger className="w-[150px]">
              <Filter className="mr-1.5 h-3.5 w-3.5" />
              <SelectValue placeholder="Tag" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">All tags</SelectItem>
              {allTags.map((t) => (
                <SelectItem key={t} value={t}>
                  {t}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Select value={sort} onValueChange={(v) => setSort(v as "recent" | "name" | "size")}>
            <SelectTrigger className="w-[150px]">
              <SlidersHorizontal className="mr-1.5 h-3.5 w-3.5" />
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="recent">Most recent</SelectItem>
              <SelectItem value="name">Name (A→Z)</SelectItem>
              <SelectItem value="size">Largest first</SelectItem>
            </SelectContent>
          </Select>
        </div>
      </div>

      <Tabs value={tab} onValueChange={(v) => setTab(v as "all" | "favorites")}>
        <TabsList>
          <TabsTrigger value="all">All ({data?.length ?? 0})</TabsTrigger>
          <TabsTrigger value="favorites">
            <Star className="mr-1.5 h-3.5 w-3.5" /> Favorites ({(data ?? []).filter((d) => d.favorite).length})
          </TabsTrigger>
        </TabsList>
      </Tabs>

      {isLoading ? (
        <div className="grid gap-3 md:grid-cols-2 lg:grid-cols-3">
          {Array.from({ length: 6 }).map((_, i) => (
            <Skeleton key={i} className="h-44 rounded-2xl" />
          ))}
        </div>
      ) : filtered.length === 0 ? (
        <EmptyState
          icon={FileText}
          title="No documents found"
          description="Try a different search or upload a new document to get started."
          action={
            <Link to="/documents/upload">
              <Button className="gradient-brand text-primary-foreground">
                <Upload className="mr-1.5 h-4 w-4" /> Upload your first
              </Button>
            </Link>
          }
        />
      ) : (
        <>
          <div className="grid gap-3 md:grid-cols-2 lg:grid-cols-3">
            {pageItems.map((d, i) => (
              <motion.div
                key={d.id}
                initial={{ opacity: 0, y: 6 }}
                animate={{ opacity: 1, y: 0 }}
                transition={{ delay: i * 0.03 }}
                className="group relative flex flex-col rounded-2xl border border-border bg-card p-4 transition-all hover:border-primary/40 hover:shadow-lg hover:shadow-primary/5"
              >
                <div className="flex items-start gap-3">
                  <Link
                    to="/documents/$id"
                    params={{ id: d.id }}
                    className="flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-primary/20 to-accent/20 text-[10px] font-bold uppercase text-foreground/80"
                  >
                    {d.type}
                  </Link>
                  <div className="min-w-0 flex-1">
                    <Link
                      to="/documents/$id"
                      params={{ id: d.id }}
                      className="line-clamp-1 text-sm font-semibold hover:text-primary"
                    >
                      {d.title}
                    </Link>
                    <p className="mt-0.5 text-xs text-muted-foreground">
                      {d.pages} pages • {(d.sizeKb / 1024).toFixed(1)} MB
                    </p>
                  </div>
                  <DropdownMenu>
                    <DropdownMenuTrigger asChild>
                      <Button size="icon" variant="ghost" className="h-7 w-7">
                        <MoreVertical className="h-4 w-4" />
                      </Button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent align="end">
                      <DropdownMenuItem onClick={() => favMutation.mutate(d.id)}>
                        <Star className="mr-2 h-4 w-4" /> {d.favorite ? "Unfavorite" : "Favorite"}
                      </DropdownMenuItem>
                      <DropdownMenuItem asChild>
                        <Link to="/documents/$id" params={{ id: d.id }}>
                          Open
                        </Link>
                      </DropdownMenuItem>
                      <DropdownMenuItem
                        className="text-destructive focus:text-destructive"
                        onClick={() => setToDelete(d)}
                      >
                        <Trash2 className="mr-2 h-4 w-4" /> Delete
                      </DropdownMenuItem>
                    </DropdownMenuContent>
                  </DropdownMenu>
                </div>
                <p className="mt-3 line-clamp-2 flex-1 text-xs text-muted-foreground">
                  {d.excerpt}
                </p>
                <div className="mt-3 flex flex-wrap items-center gap-1.5">
                  {d.tags.map((t) => (
                    <Badge key={t} variant="secondary" className="text-[10px]">
                      {t}
                    </Badge>
                  ))}
                  {d.favorite && (
                    <Star className="ml-auto h-3.5 w-3.5 fill-warning text-warning" />
                  )}
                </div>
                <p className="mt-2 text-[11px] text-muted-foreground">
                  Updated {formatDistanceToNow(new Date(d.updatedAt), { addSuffix: true })}
                </p>
              </motion.div>
            ))}
          </div>

          <Pagination>
            <PaginationContent>
              <PaginationItem>
                <PaginationPrevious
                  onClick={() => setPage((p) => Math.max(1, p - 1))}
                  className={page === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}
                />
              </PaginationItem>
              {Array.from({ length: totalPages }).map((_, i) => (
                <PaginationItem key={i}>
                  <PaginationLink
                    isActive={page === i + 1}
                    onClick={() => setPage(i + 1)}
                    className="cursor-pointer"
                  >
                    {i + 1}
                  </PaginationLink>
                </PaginationItem>
              ))}
              <PaginationItem>
                <PaginationNext
                  onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                  className={
                    page === totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"
                  }
                />
              </PaginationItem>
            </PaginationContent>
          </Pagination>
        </>
      )}

      <AlertDialog open={!!toDelete} onOpenChange={(o) => !o && setToDelete(null)}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete this document?</AlertDialogTitle>
            <AlertDialogDescription>
              "{toDelete?.title}" will be permanently removed along with its summary, flashcards
              and quiz attempts.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
              onClick={() => {
                if (toDelete) removeMutation.mutate(toDelete.id);
                setToDelete(null);
              }}
            >
              Delete
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
