"use client";

import Link from "next/link";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useMemo, useState } from "react";
import { Activity, Combine, FileText, HardDrive, Merge, Search, Star } from "lucide-react";
import { toast } from "sonner";
import type { FileDto, ListFilesResponseDto, UsageDto } from "@use2pdf/shared-types";
import { FileList } from "@/components/file-list";
import { FileUploadDropzone } from "@/components/file-upload-dropzone";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Spinner } from "@/components/ui/spinner";
import { apiFetch, ApiRequestError } from "@/lib/api-client";
import { formatBytes } from "@/lib/format";

const QUICK_ACTIONS = [
  { href: "/editor", label: "✏️ Edit PDF" },
  { href: "/tools/merge-pdf", label: "Merge" },
  { href: "/tools/split-pdf", label: "Split" },
  { href: "/tools/compress-pdf", label: "Compress" },
  { href: "/tools/pdf-to-jpg", label: "PDF → JPG" },
  { href: "/tools/protect-pdf", label: "Protect" },
  { href: "/tools/ocr", label: "OCR" },
];

export default function DashboardPage() {
  const router = useRouter();
  const [files, setFiles] = useState<FileDto[]>([]);
  const [usage, setUsage] = useState<UsageDto | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [selectedIds, setSelectedIds] = useState<string[]>([]);
  const [search, setSearch] = useState("");
  const [sortBy, setSortBy] = useState<"createdAt" | "name" | "size">("createdAt");
  const [sortDir, setSortDir] = useState<"asc" | "desc">("desc");
  const [favoritesOnly, setFavoritesOnly] = useState(false);

  const loadFiles = useCallback(async () => {
    try {
      const params = new URLSearchParams({
        page: "1",
        pageSize: "100",
        sortBy,
        sortDir,
      });
      if (search.trim()) params.set("search", search.trim());
      if (favoritesOnly) params.set("favorites", "true");
      const data = await apiFetch<ListFilesResponseDto>(`/files?${params.toString()}`);
      setFiles(data.files);
    } catch (err) {
      toast.error(err instanceof ApiRequestError ? err.message : "Could not load your files");
    } finally {
      setIsLoading(false);
    }
  }, [search, sortBy, sortDir, favoritesOnly]);

  useEffect(() => {
    const timer = setTimeout(loadFiles, search ? 300 : 0);
    return () => clearTimeout(timer);
  }, [loadFiles, search]);

  useEffect(() => {
    apiFetch<UsageDto>("/me/usage").then(setUsage).catch(() => undefined);
  }, [files.length]);

  const stats = useMemo(
    () => [
      { icon: FileText, label: "Files", value: usage ? String(usage.fileCount) : "—" },
      { icon: HardDrive, label: "Storage used", value: usage ? formatBytes(usage.storageUsedBytes) : "—" },
      { icon: Activity, label: "Operations this month", value: usage ? String(usage.operationsThisMonth) : "—" },
      { icon: Combine, label: "Operations total", value: usage ? String(usage.operationsTotal) : "—" },
    ],
    [usage],
  );

  function handleUploaded(newFiles: FileDto[]) {
    setFiles((prev) => [...newFiles, ...prev]);
  }

  function handleDeleted(fileId: string) {
    setFiles((prev) => prev.filter((f) => f.id !== fileId));
    setSelectedIds((prev) => prev.filter((id) => id !== fileId));
  }

  function handleUpdated(updated: FileDto) {
    setFiles((prev) => prev.map((f) => (f.id === updated.id ? updated : f)));
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-wrap items-center justify-between gap-4">
        <div>
          <h1 className="text-2xl font-bold text-slate-900 dark:text-slate-100">Your files</h1>
          <p className="mt-1 text-sm text-slate-500 dark:text-slate-400">
            Upload, organize and run any tool on your documents.
          </p>
        </div>
        <div className="flex flex-wrap gap-2">
          {QUICK_ACTIONS.map((action) => (
            <Link
              key={action.href}
              href={action.href}
              className="rounded-md border border-slate-200 bg-white px-3 py-1.5 text-sm text-slate-700 transition-colors hover:border-brand-300 hover:text-brand-700 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300 dark:hover:border-brand-600"
            >
              {action.label}
            </Link>
          ))}
        </div>
      </div>

      <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
        {stats.map((stat) => (
          <Card key={stat.label}>
            <CardContent className="flex items-center gap-3 py-4">
              <stat.icon className="h-8 w-8 text-brand-600" />
              <div>
                <p className="text-xl font-bold text-slate-900 dark:text-slate-100">{stat.value}</p>
                <p className="text-xs text-slate-500 dark:text-slate-400">{stat.label}</p>
              </div>
            </CardContent>
          </Card>
        ))}
      </div>

      <FileUploadDropzone onUploaded={handleUploaded} accept="any" />

      <Card>
        <CardHeader className="space-y-3">
          <div className="flex flex-wrap items-center justify-between gap-3">
            <CardTitle>Files ({files.length})</CardTitle>
            <Button
              size="sm"
              disabled={selectedIds.length < 2}
              onClick={() => router.push(`/tools/merge-pdf?files=${selectedIds.join(",")}`)}
              title={selectedIds.length < 2 ? "Select at least 2 PDF files to merge" : undefined}
            >
              <Merge className="h-4 w-4" />
              Merge selected ({selectedIds.length})
            </Button>
          </div>
          <div className="flex flex-wrap items-center gap-2">
            <div className="relative min-w-48 flex-1">
              <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400" />
              <input
                type="search"
                placeholder="Search files…"
                aria-label="Search files"
                className="h-9 w-full rounded-md border border-slate-300 bg-white pl-9 pr-3 text-sm text-slate-900 focus:border-brand-500 focus:outline-none focus:ring-1 focus:ring-brand-500 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-100"
                value={search}
                onChange={(e) => setSearch(e.target.value)}
              />
            </div>
            <select
              aria-label="Sort by"
              className="h-9 rounded-md border border-slate-300 bg-white px-2 text-sm text-slate-700 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-300"
              value={`${sortBy}:${sortDir}`}
              onChange={(e) => {
                const [by, dir] = e.target.value.split(":") as [typeof sortBy, typeof sortDir];
                setSortBy(by);
                setSortDir(dir);
              }}
            >
              <option value="createdAt:desc">Newest first</option>
              <option value="createdAt:asc">Oldest first</option>
              <option value="name:asc">Name A–Z</option>
              <option value="name:desc">Name Z–A</option>
              <option value="size:desc">Largest first</option>
              <option value="size:asc">Smallest first</option>
            </select>
            <button
              type="button"
              aria-pressed={favoritesOnly}
              onClick={() => setFavoritesOnly((v) => !v)}
              className={`flex h-9 items-center gap-1.5 rounded-md border px-3 text-sm transition-colors ${
                favoritesOnly
                  ? "border-amber-300 bg-amber-50 text-amber-700 dark:border-amber-700 dark:bg-amber-950 dark:text-amber-300"
                  : "border-slate-300 bg-white text-slate-600 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-300"
              }`}
            >
              <Star className={favoritesOnly ? "h-4 w-4 fill-amber-400 text-amber-400" : "h-4 w-4"} />
              Favorites
            </button>
          </div>
        </CardHeader>
        <CardContent>
          {isLoading ? (
            <div className="flex justify-center py-12">
              <Spinner className="h-8 w-8 text-brand-600" />
            </div>
          ) : (
            <FileList
              files={files}
              onDeleted={handleDeleted}
              onUpdated={handleUpdated}
              selectable
              selectedIds={selectedIds}
              onSelectionChange={setSelectedIds}
            />
          )}
        </CardContent>
      </Card>
    </div>
  );
}
