"use client";

import { useEffect, useMemo, useState } from "react";
import useSWR, { useSWRConfig } from "swr";
import {
  AlertCircle,
  ChevronLeft,
  ChevronRight,
  ClipboardList,
  Layers,
  Pencil,
  Plus,
  Search,
  ShieldCheck,
  Trash2,
} from "lucide-react";
import { toast } from "sonner";
import type { Paginated, SyaratDokumen } from "@/lib/types";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import { useSession } from "@/lib/use-session";
import { StatCard } from "@/components/page-header";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select } from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { cn } from "@/lib/utils";

export function DokumenPersyaratan() {
  const { user } = useSession();
  const isAdmin = user?.role === "ADMIN";

  const [page, setPage] = useState(1);
  const [limit, setLimit] = useState(10);
  const [search, setSearch] = useState("");
  const [q, setQ] = useState("");
  const [selected, setSelected] = useState<number[]>([]);

  const [formOpen, setFormOpen] = useState(false);
  const [editing, setEditing] = useState<SyaratDokumen | null>(null);
  const [nama, setNama] = useState("");
  const [saving, setSaving] = useState(false);

  const [deleteTarget, setDeleteTarget] = useState<SyaratDokumen | null>(null);
  const [batchIds, setBatchIds] = useState<number[] | null>(null);
  const [deleting, setDeleting] = useState(false);

  const { mutate: mutateGlobal } = useSWRConfig();

  const { data: all } = useSWR<Paginated<SyaratDokumen>>(
    "/surat/syarat?limit=200",
    fetcher,
  );

  const query = new URLSearchParams({ page: String(page), limit: String(limit) });
  if (q) query.set("q", q);
  const { data, isLoading } = useSWR<Paginated<SyaratDokumen>>(
    `/surat/syarat?${query.toString()}`,
    fetcher,
  );

  async function refresh() {
    await mutateGlobal(
      (key) =>
        typeof key === "string" &&
        (key.startsWith("/surat/syarat") || key.startsWith("/surat/jenis")),
      undefined,
      { revalidate: true },
    );
  }

  const dokumen = data?.data ?? [];
  const meta = data?.meta;
  const total = meta?.total ?? 0;

  const semuaDokumen = all?.data ?? [];
  const stats = useMemo(() => {
    const dipakai = semuaDokumen.filter((item) => item.dipakai > 0).length;
    const pemakaian = semuaDokumen.reduce((jumlah, item) => jumlah + item.dipakai, 0);
    return {
      total: all?.meta.total ?? 0,
      dipakai,
      belum: (all?.meta.total ?? 0) - dipakai,
      pemakaian,
    };
  }, [semuaDokumen, all?.meta.total]);

  useEffect(() => {
    setPage(1);
  }, [q, limit]);

  useEffect(() => {
    setSelected([]);
  }, [page, limit, q]);

  useEffect(() => {
    const totalPages = meta?.totalPages;
    if (totalPages && page > totalPages) setPage(totalPages);
  }, [meta?.totalPages, page]);

  const semuaDipilih = dokumen.length > 0 && dokumen.every((item) => selected.includes(item.id));

  function toggle(id: number) {
    setSelected((current) =>
      current.includes(id) ? current.filter((value) => value !== id) : [...current, id],
    );
  }

  function toggleSemua() {
    setSelected(semuaDipilih ? [] : dokumen.map((item) => item.id));
  }

  function openTambah() {
    setEditing(null);
    setNama("");
    setFormOpen(true);
  }

  function openEdit(item: SyaratDokumen) {
    setEditing(item);
    setNama(item.nama);
    setFormOpen(true);
  }

  async function simpan(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const value = nama.trim();
    if (!value) return;
    setSaving(true);
    try {
      if (editing) {
        await apiSend(`/surat/syarat/${editing.id}`, "PATCH", { nama: value });
        toast.success("Dokumen persyaratan diperbarui");
      } else {
        await apiSend("/surat/syarat", "POST", { nama: value });
        toast.success("Dokumen persyaratan ditambahkan");
      }
      setFormOpen(false);
      setEditing(null);
      setNama("");
      await refresh();
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal menyimpan dokumen persyaratan",
      );
    } finally {
      setSaving(false);
    }
  }

  async function hapusSatu() {
    if (!deleteTarget) return;
    setDeleting(true);
    try {
      await apiSend(`/surat/syarat/${deleteTarget.id}`, "DELETE");
      toast.success("Dokumen persyaratan dihapus");
      setDeleteTarget(null);
      await refresh();
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal menghapus dokumen persyaratan",
      );
    } finally {
      setDeleting(false);
    }
  }

  function bukaHapusMassal() {
    if (!selected.length) return;
    const terpakai = dokumen.filter(
      (item) => selected.includes(item.id) && item.dipakai > 0,
    );
    if (terpakai.length) {
      toast.error(
        `Tidak dapat menghapus: ${terpakai.map((item) => item.nama).join(", ")} masih dipakai`,
      );
      return;
    }
    setBatchIds([...selected]);
  }

  async function hapusMassal() {
    if (!batchIds?.length) return;
    setDeleting(true);
    try {
      await apiSend("/surat/syarat/hapus", "POST", { ids: batchIds });
      toast.success(`${batchIds.length} dokumen persyaratan dihapus`);
      setBatchIds(null);
      setSelected([]);
      await refresh();
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal menghapus dokumen persyaratan",
      );
    } finally {
      setDeleting(false);
    }
  }

  const dari = total === 0 ? 0 : (page - 1) * limit + 1;
  const sampai = Math.min(total, page * limit);
  const totalPages = meta?.totalPages ?? 1;

  return (
    <div className="space-y-6">
      <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
        <StatCard
          title="Dokumen persyaratan"
          value={stats.total}
          hint="Katalog dokumen surat desa"
          icon={ClipboardList}
          tone="emerald"
        />
        <StatCard
          title="Dipakai layanan"
          value={stats.dipakai}
          hint="Dokumen aktif pada minimal satu layanan"
          icon={ShieldCheck}
          tone="sky"
        />
        <StatCard
          title="Belum dipakai"
          value={stats.belum}
          hint="Siap dihubungkan ke layanan"
          icon={AlertCircle}
          tone="amber"
        />
        <StatCard
          title="Total pemakaian"
          value={stats.pemakaian}
          hint="Butir syarat di seluruh layanan surat"
          icon={Layers}
          tone="violet"
        />
      </div>

      <Card>
        <CardContent className="p-0">
          <div className="flex flex-col gap-3 border-b p-4 lg:flex-row lg:items-center lg:justify-between">
            <div className="flex flex-wrap gap-2">
              {isAdmin && (
                <>
                  <Button onClick={openTambah}>
                    <Plus className="h-4 w-4" />
                    Tambah Dokumen
                  </Button>
                  <Button
                    variant="outline"
                    disabled={!selected.length}
                    onClick={bukaHapusMassal}
                    className={cn(selected.length > 0 && "text-destructive hover:text-destructive")}
                  >
                    <Trash2 className="h-4 w-4" />
                    Hapus{selected.length ? ` (${selected.length})` : ""}
                  </Button>
                </>
              )}
              <span className="self-center text-xs text-muted-foreground">
                {total} dokumen terdaftar
              </span>
            </div>
            <form
              onSubmit={(event) => {
                event.preventDefault();
                setQ(search.trim());
              }}
              className="relative w-full lg:max-w-sm"
            >
              <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Input
                value={search}
                onChange={(event) => setSearch(event.target.value)}
                placeholder="Cari nama dokumen persyaratan…"
                className="pl-9"
              />
            </form>
          </div>

          {isLoading ? (
            <div className="space-y-2 p-4">
              {Array.from({ length: 6 }).map((_, index) => (
                <div key={index} className="h-14 animate-pulse rounded-lg bg-muted" />
              ))}
            </div>
          ) : dokumen.length ? (
            <Table>
              <TableHeader>
                <TableRow>
                  {isAdmin && (
                    <TableHead className="w-10">
                      <input
                        type="checkbox"
                        checked={semuaDipilih}
                        onChange={toggleSemua}
                        aria-label="Pilih semua dokumen pada halaman ini"
                        className="h-4 w-4 accent-emerald-600"
                      />
                    </TableHead>
                  )}
                  <TableHead className="w-16">No</TableHead>
                  <TableHead className="w-24">Aksi</TableHead>
                  <TableHead>Nama Dokumen</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {dokumen.map((item, index) => (
                  <TableRow
                    key={item.id}
                    className={cn(selected.includes(item.id) && "bg-primary/5")}
                  >
                    {isAdmin && (
                      <TableCell>
                        <input
                          type="checkbox"
                          checked={selected.includes(item.id)}
                          onChange={() => toggle(item.id)}
                          aria-label={`Pilih ${item.nama}`}
                          className="h-4 w-4 accent-emerald-600"
                        />
                      </TableCell>
                    )}
                    <TableCell className="text-muted-foreground">
                      {(page - 1) * limit + index + 1}
                    </TableCell>
                    <TableCell>
                      {isAdmin ? (
                        <div className="flex gap-1">
                          <Button
                            variant="ghost"
                            size="icon"
                            className="h-8 w-8"
                            onClick={() => openEdit(item)}
                            title="Ubah dokumen"
                            aria-label={`Ubah ${item.nama}`}
                          >
                            <Pencil className="h-4 w-4" />
                          </Button>
                          <Button
                            variant="ghost"
                            size="icon"
                            className="h-8 w-8 text-destructive hover:text-destructive disabled:text-muted-foreground"
                            disabled={item.dipakai > 0}
                            onClick={() => setDeleteTarget(item)}
                            title={
                              item.dipakai > 0
                                ? `Masih dipakai pada ${item.dipakai} layanan surat`
                                : "Hapus dokumen"
                            }
                            aria-label={`Hapus ${item.nama}`}
                          >
                            <Trash2 className="h-4 w-4" />
                          </Button>
                        </div>
                      ) : (
                        <span className="text-xs text-muted-foreground">—</span>
                      )}
                    </TableCell>
                    <TableCell>
                      <div className="font-medium">{item.nama}</div>
                      <div className="mt-0.5 text-xs text-muted-foreground">
                        {item.dipakai > 0
                          ? `Dipakai pada ${item.dipakai} layanan surat`
                          : "Belum dipakai pada layanan mana pun"}
                      </div>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          ) : (
            <div className="py-16 text-center">
              <p className="font-semibold">
                {q ? "Dokumen tidak ditemukan" : "Belum ada dokumen persyaratan"}
              </p>
              <p className="mt-1 text-sm text-muted-foreground">
                {q
                  ? "Ubah kata pencarian untuk menemukan dokumen lain."
                  : "Tambahkan dokumen persyaratan agar bisa dipakai pada layanan surat."}
              </p>
            </div>
          )}

          <div className="flex flex-col gap-3 border-t px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
            <p className="text-xs text-muted-foreground">
              Menampilkan {dari} sampai {sampai} dari {total} entri
            </p>
            <div className="flex flex-wrap items-center gap-2">
              <Select
                value={String(limit)}
                onChange={(event) => setLimit(Number(event.target.value))}
                aria-label="Jumlah baris per halaman"
                className="h-9 w-24"
              >
                <option value="10">10 entri</option>
                <option value="25">25 entri</option>
                <option value="50">50 entri</option>
              </Select>
              <Button
                variant="outline"
                size="sm"
                disabled={page <= 1}
                onClick={() => setPage((current) => current - 1)}
              >
                <ChevronLeft className="h-4 w-4" />
                Sebelumnya
              </Button>
              <Button
                variant="outline"
                size="sm"
                disabled={page >= totalPages}
                onClick={() => setPage((current) => current + 1)}
              >
                Berikutnya
                <ChevronRight className="h-4 w-4" />
              </Button>
            </div>
          </div>
        </CardContent>
      </Card>

      <Dialog
        open={formOpen}
        onOpenChange={(open) => {
          if (!open) {
            setFormOpen(false);
            setEditing(null);
            setNama("");
          }
        }}
      >
        <DialogContent className="max-w-lg">
          <form onSubmit={simpan}>
            <DialogHeader>
              <DialogTitle>
                {editing ? "Ubah Dokumen Persyaratan" : "Tambah Dokumen Persyaratan"}
              </DialogTitle>
              <DialogDescription>
                {editing
                  ? "Perubahan nama otomatis memperbarui daftar syarat pada semua layanan surat yang memakainya."
                  : "Dokumen ini akan masuk ke katalog dan dapat dipakai sebagai syarat layanan surat."}
              </DialogDescription>
            </DialogHeader>
            <div className="space-y-1.5 py-4">
              <Label htmlFor="nama-dokumen">Nama dokumen</Label>
              <Input
                id="nama-dokumen"
                value={nama}
                onChange={(event) => setNama(event.target.value)}
                placeholder="Contoh: Fotokopi buku tabungan"
                maxLength={200}
                autoFocus
              />
            </div>
            <DialogFooter>
              <Button
                type="button"
                variant="outline"
                onClick={() => {
                  setFormOpen(false);
                  setEditing(null);
                  setNama("");
                }}
              >
                Batal
              </Button>
              <Button type="submit" disabled={saving || !nama.trim()}>
                {saving ? "Menyimpan…" : editing ? "Simpan Perubahan" : "Tambah"}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <Dialog
        open={!!deleteTarget}
        onOpenChange={(open) => !open && setDeleteTarget(null)}
      >
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus Dokumen Persyaratan</DialogTitle>
            <DialogDescription>
              Dokumen &ldquo;{deleteTarget?.nama}&rdquo; akan dihapus dari katalog.
              Tindakan ini tidak dapat dibatalkan.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDeleteTarget(null)}>
              Batal
            </Button>
            <Button variant="destructive" onClick={hapusSatu} disabled={deleting}>
              {deleting ? "Menghapus…" : "Hapus"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog
        open={!!batchIds}
        onOpenChange={(open) => !open && setBatchIds(null)}
      >
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus Dokumen Terpilih</DialogTitle>
            <DialogDescription>
              Sebanyak {batchIds?.length ?? 0} dokumen akan dihapus dari katalog.
              Tindakan ini tidak dapat dibatalkan.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setBatchIds(null)}>
              Batal
            </Button>
            <Button variant="destructive" onClick={hapusMassal} disabled={deleting}>
              {deleting ? "Menghapus…" : "Hapus Semua"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
