"use client";

import { useState } from "react";
import useSWR from "swr";
import {
  Download,
  FilePenLine,
  Handshake,
  Landmark,
  Plus,
  Printer,
  Settings2,
  Trash2,
  UserPlus,
  Users,
} from "lucide-react";
import { toast } from "sonner";
import type {
  JenisLembaga,
  Lembaga,
  LembagaAnggota,
  LembagaKategori,
  Penduduk,
} from "@/lib/types";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import { unduhCsv } from "@/lib/sekretariat";
import { useSession } from "@/lib/use-session";
import { PageHeader, StatCard } from "@/components/page-header";
import { Badge } from "@/components/ui/badge";
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 { Textarea } from "@/components/ui/textarea";

const JENIS_OPTIONS: { value: JenisLembaga; label: string }[] = [
  { value: "PKK", label: "PKK" },
  { value: "KARANG_TARUNA", label: "Karang Taruna" },
  { value: "BPD", label: "BPD" },
  { value: "LPM", label: "LPM" },
  { value: "POSYANDU", label: "Posyandu" },
  { value: "RT_RW", label: "RT / RW" },
  { value: "LAINNYA", label: "Lainnya" },
];

type FormState = {
  kode: string;
  nama: string;
  jenis: JenisLembaga;
  kategoriId: string;
  ketuaId: string;
  ketua: string;
  sekretaris: string;
  anggota: string;
  noSkPendirian: string;
  logo: string;
  alamat: string;
  keterangan: string;
  aktif: boolean;
};

const emptyForm: FormState = {
  kode: "",
  nama: "",
  jenis: "PKK",
  kategoriId: "",
  ketuaId: "",
  ketua: "",
  sekretaris: "",
  anggota: "0",
  noSkPendirian: "",
  logo: "",
  alamat: "",
  keterangan: "",
  aktif: true,
};

type PendudukPage = { data: Penduduk[] };

function labelJenis(jenis: JenisLembaga) {
  return JENIS_OPTIONS.find((option) => option.value === jenis)?.label ?? jenis;
}

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

  const { data, isLoading, mutate } = useSWR<Lembaga[]>("/lembaga", fetcher);
  const { data: kategoriList, mutate: mutateKategori } = useSWR<LembagaKategori[]>(
    "/lembaga/kategori",
    fetcher,
  );
  const { data: pendudukPage } = useSWR<PendudukPage>(
    "/penduduk?limit=200&status=HIDUP",
    fetcher,
  );
  const penduduk = pendudukPage?.data ?? [];
  const daftar = data ?? [];

  const [formOpen, setFormOpen] = useState(false);
  const [editing, setEditing] = useState<Lembaga | null>(null);
  const [form, setForm] = useState<FormState>(emptyForm);
  const [saving, setSaving] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<Lembaga | null>(null);
  const [deleting, setDeleting] = useState(false);

  const [kategoriOpen, setKategoriOpen] = useState(false);
  const [kategoriForm, setKategoriForm] = useState({ id: 0, nama: "", deskripsi: "" });
  const [kategoriSaving, setKategoriSaving] = useState(false);

  const [anggotaTarget, setAnggotaTarget] = useState<Lembaga | null>(null);

  const [cari, setCari] = useState("");
  const [statusDasar, setStatusDasar] = useState("");
  const [dipilih, setDipilih] = useState<number[]>([]);
  const [menghapus, setMenghapus] = useState(false);
  const [konfirmasiHapus, setKonfirmasiHapus] = useState(false);

  const tersaring = daftar.filter((item) => {
    if (statusDasar === "1" && !item.aktif) return false;
    if (statusDasar === "0" && item.aktif) return false;
    const kata = cari.trim().toLowerCase();
    if (!kata) return true;
    return [item.kode, item.nama, item.kategori?.nama, item.ketua]
      .filter(Boolean)
      .some((nilai) => String(nilai).toLowerCase().includes(kata));
  });

  const semuaDipilih = tersaring.length > 0 && tersaring.every((item) => dipilih.includes(item.id));

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

  function toggleDipilih(id: number) {
    setDipilih((current) =>
      current.includes(id) ? current.filter((item) => item !== id) : [...current, id],
    );
  }

  async function hapusTerpilih() {
    setMenghapus(true);
    try {
      const hasil = await apiSend<{ ok: boolean; terhapus: number }>("/lembaga/hapus", "POST", {
        ids: dipilih,
      });
      toast.success(`${hasil.terhapus} lembaga dihapus`);
      setDipilih([]);
      setKonfirmasiHapus(false);
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menghapus lembaga");
    } finally {
      setMenghapus(false);
    }
  }

  function unduhDaftar() {
    unduhCsv(
      `lembaga-desa-${new Date().toISOString().slice(0, 10)}.csv`,
      [
        "No",
        "Kode Lembaga",
        "Nama Lembaga",
        "Ketua Lembaga",
        "Kategori Lembaga",
        "Jumlah Anggota Lembaga",
        "Status",
      ],
      tersaring.map((item, index) => [
        index + 1,
        item.kode ?? "",
        item.nama,
        item.ketua ?? "",
        item.kategori?.nama ?? "",
        item.anggota ?? item.jumlahAnggota ?? 0,
        item.aktif ? "Aktif" : "Nonaktif",
      ]),
    );
    toast.success("Daftar lembaga diunduh");
  }

  const { data: anggotaList, mutate: mutateAnggota } = useSWR<LembagaAnggota[]>(
    anggotaTarget ? `/lembaga/${anggotaTarget.id}/anggota` : null,
    fetcher,
  );
  const [anggotaForm, setAnggotaForm] = useState({
    pendudukId: "",
    noAnggota: "0",
    keterangan: "",
  });

  function openCreate() {
    setEditing(null);
    setForm(emptyForm);
    setFormOpen(true);
  }

  function openEdit(item: Lembaga) {
    setEditing(item);
    setForm({
      kode: item.kode ?? "",
      nama: item.nama,
      jenis: item.jenis,
      kategoriId: item.kategoriId ? String(item.kategoriId) : "",
      ketuaId: item.ketuaId ? String(item.ketuaId) : "",
      ketua: item.ketua ?? "",
      sekretaris: item.sekretaris ?? "",
      anggota: String(item.anggota ?? 0),
      noSkPendirian: item.noSkPendirian ?? "",
      logo: item.logo ?? "",
      alamat: item.alamat ?? "",
      keterangan: item.keterangan ?? "",
      aktif: item.aktif,
    });
    setFormOpen(true);
  }

  async function save(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSaving(true);
    try {
      const payload: Record<string, unknown> = {
        kode: form.kode || null,
        nama: form.nama,
        jenis: form.jenis,
        kategoriId: form.kategoriId ? Number(form.kategoriId) : null,
        ketuaId: form.ketuaId ? Number(form.ketuaId) : null,
        ketua: form.ketua || null,
        sekretaris: form.sekretaris || null,
        anggota: Number(form.anggota) || 0,
        noSkPendirian: form.noSkPendirian || null,
        logo: form.logo || null,
        alamat: form.alamat || null,
        keterangan: form.keterangan || null,
        aktif: form.aktif,
      };
      if (editing) {
        await apiSend(`/lembaga/${editing.id}`, "PATCH", payload);
        toast.success("Data lembaga diperbarui");
      } else {
        await apiSend("/lembaga", "POST", payload);
        toast.success("Lembaga ditambahkan");
      }
      setFormOpen(false);
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyimpan data");
    } finally {
      setSaving(false);
    }
  }

  async function remove() {
    if (!deleteTarget) return;
    setDeleting(true);
    try {
      await apiSend(`/lembaga/${deleteTarget.id}`, "DELETE");
      toast.success("Lembaga dihapus");
      setDeleteTarget(null);
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menghapus data");
    } finally {
      setDeleting(false);
    }
  }

  async function saveKategori(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setKategoriSaving(true);
    try {
      const payload = {
        nama: kategoriForm.nama,
        deskripsi: kategoriForm.deskripsi || null,
      };
      if (kategoriForm.id) {
        await apiSend(`/lembaga/kategori/${kategoriForm.id}`, "PATCH", payload);
        toast.success("Kategori diperbarui");
      } else {
        await apiSend("/lembaga/kategori", "POST", payload);
        toast.success("Kategori ditambahkan");
      }
      setKategoriForm({ id: 0, nama: "", deskripsi: "" });
      await Promise.all([mutateKategori(), mutate()]);
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal menyimpan kategori",
      );
    } finally {
      setKategoriSaving(false);
    }
  }

  async function removeKategori(item: LembagaKategori) {
    setKategoriSaving(true);
    try {
      await apiSend(`/lembaga/kategori/${item.id}`, "DELETE");
      toast.success(`Kategori ${item.nama} dihapus`);
      if (kategoriForm.id === item.id) {
        setKategoriForm({ id: 0, nama: "", deskripsi: "" });
      }
      await Promise.all([mutateKategori(), mutate()]);
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal menghapus kategori",
      );
    } finally {
      setKategoriSaving(false);
    }
  }

  async function addAnggota(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!anggotaTarget || !anggotaForm.pendudukId) return;
    setKategoriSaving(true);
    try {
      await apiSend(`/lembaga/${anggotaTarget.id}/anggota`, "POST", {
        pendudukId: Number(anggotaForm.pendudukId),
        noAnggota: Number(anggotaForm.noAnggota) || 0,
        keterangan: anggotaForm.keterangan || null,
      });
      toast.success("Anggota ditambahkan");
      setAnggotaForm({ pendudukId: "", noAnggota: "0", keterangan: "" });
      await Promise.all([mutateAnggota(), mutate()]);
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menambah anggota");
    } finally {
      setKategoriSaving(false);
    }
  }

  async function removeAnggota(item: LembagaAnggota) {
    if (!anggotaTarget) return;
    setKategoriSaving(true);
    try {
      await apiSend(`/lembaga/${anggotaTarget.id}/anggota/${item.id}`, "DELETE");
      toast.success("Anggota dihapus");
      await Promise.all([mutateAnggota(), mutate()]);
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menghapus anggota");
    } finally {
      setKategoriSaving(false);
    }
  }

  return (
    <div className="animate-fade-in space-y-6">
      <PageHeader
        title="Lembaga Desa"
        description="Lembaga kemasyarakatan dan mitra pemerintah desa seperti PKK, Karang Taruna, BPD, LPM, dan Posyandu."
        action={
          <div className="flex flex-wrap gap-2 print:hidden">
            <Button variant="outline" onClick={() => window.print()}>
              <Printer className="h-4 w-4" />
              Cetak
            </Button>
            <Button variant="outline" onClick={unduhDaftar}>
              <Download className="h-4 w-4" />
              Unduh
            </Button>
            {isAdmin && (
              <>
                <Button variant="outline" onClick={() => setKategoriOpen(true)}>
                  <Settings2 className="h-4 w-4" />
                  Kategori
                </Button>
                <Button
                  variant="outline"
                  className="text-destructive hover:text-destructive"
                  disabled={!dipilih.length}
                  onClick={() => setKonfirmasiHapus(true)}
                >
                  <Trash2 className="h-4 w-4" />
                  Hapus{dipilih.length ? ` (${dipilih.length})` : ""}
                </Button>
                <Button onClick={openCreate}>
                  <Plus className="h-4 w-4" />
                  Tambah Lembaga
                </Button>
              </>
            )}
          </div>
        }
      />

      <div className="grid gap-4 sm:grid-cols-3">
        <StatCard title="Total lembaga" value={daftar.length} icon={Landmark} />
        <StatCard
          title="Lembaga aktif"
          value={daftar.filter((item) => item.aktif).length}
          icon={Handshake}
          tone="sky"
        />
        <StatCard
          title="Total anggota"
          value={daftar.reduce(
            (total, item) => total + (item.anggota ?? item.jumlahAnggota ?? 0),
            0,
          )}
          icon={Users}
          tone="amber"
        />
      </div>

      <Card>
        <CardContent className="p-0">
          {isLoading ? (
            <div className="space-y-2 p-4">
              {Array.from({ length: 4 }).map((_, index) => (
                <div key={index} className="h-14 animate-pulse rounded-lg bg-muted" />
              ))}
            </div>
          ) : daftar.length ? (
            <>
              <div className="flex flex-wrap items-center gap-2 border-b px-4 py-3 print:hidden">
                <Input
                  value={cari}
                  onChange={(event) => setCari(event.target.value)}
                  placeholder="Cari kode, nama, kategori, atau ketua"
                  className="h-9 w-full max-w-xs"
                  aria-label="Cari lembaga"
                />
                <Select
                  value={statusDasar}
                  onChange={(event) => setStatusDasar(event.target.value)}
                  className="h-9 w-40"
                  aria-label="Status dasar"
                >
                  <option value="">Semua Status</option>
                  <option value="1">Aktif</option>
                  <option value="0">Nonaktif</option>
                </Select>
                {(cari || statusDasar) && (
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={() => {
                      setCari("");
                      setStatusDasar("");
                    }}
                  >
                    Bersihkan
                  </Button>
                )}
                <span className="text-xs text-muted-foreground">
                  {tersaring.length} dari {daftar.length} lembaga
                </span>
              </div>
              <Table>
                <TableHeader>
                  <TableRow>
                    {isAdmin && (
                      <TableHead className="w-12 print:hidden">
                        <input
                          type="checkbox"
                          checked={semuaDipilih}
                          onChange={toggleSemua}
                          aria-label="Pilih semua lembaga"
                          className="h-4 w-4 accent-emerald-600"
                        />
                      </TableHead>
                    )}
                    <TableHead className="w-14">No</TableHead>
                    <TableHead className="w-40 print:hidden">Aksi</TableHead>
                    <TableHead>Kode Lembaga</TableHead>
                    <TableHead>Nama Lembaga</TableHead>
                    <TableHead>Ketua Lembaga</TableHead>
                    <TableHead>Kategori Lembaga</TableHead>
                    <TableHead className="text-right">Jumlah Anggota Lembaga</TableHead>
                    <TableHead>Status</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {tersaring.map((item, index) => (
                    <TableRow key={item.id}>
                      {isAdmin && (
                        <TableCell className="print:hidden">
                          <input
                            type="checkbox"
                            checked={dipilih.includes(item.id)}
                            onChange={() => toggleDipilih(item.id)}
                            aria-label={`Pilih ${item.nama}`}
                            className="h-4 w-4 accent-emerald-600"
                          />
                        </TableCell>
                      )}
                      <TableCell className="text-muted-foreground">{index + 1}</TableCell>
                      <TableCell className="print:hidden">
                        <div className="flex gap-1">
                          <Button
                            variant="ghost"
                            size="sm"
                            className="h-8"
                            onClick={() => setAnggotaTarget(item)}
                          >
                            <Users className="h-4 w-4" />
                            Anggota
                          </Button>
                          {isAdmin && (
                            <>
                              <Button
                                variant="ghost"
                                size="icon"
                                className="h-8 w-8"
                                onClick={() => openEdit(item)}
                                aria-label="Ubah lembaga"
                              >
                                <FilePenLine className="h-4 w-4" />
                              </Button>
                              <Button
                                variant="ghost"
                                size="icon"
                                className="h-8 w-8 text-destructive hover:text-destructive"
                                onClick={() => setDeleteTarget(item)}
                                aria-label="Hapus lembaga"
                              >
                                <Trash2 className="h-4 w-4" />
                              </Button>
                            </>
                          )}
                        </div>
                      </TableCell>
                      <TableCell className="font-mono text-xs text-muted-foreground">
                        {item.kode || "-"}
                      </TableCell>
                      <TableCell>
                        <div className="font-medium">{item.nama}</div>
                        <Badge variant="secondary" className="mt-1">
                          {labelJenis(item.jenis)}
                        </Badge>
                      </TableCell>
                      <TableCell>{item.ketua ?? "-"}</TableCell>
                      <TableCell>{item.kategori?.nama ?? "-"}</TableCell>
                      <TableCell className="text-right">
                        {item.anggota ?? item.jumlahAnggota ?? 0}
                      </TableCell>
                      <TableCell>
                        <Badge variant={item.aktif ? "success" : "secondary"}>
                          {item.aktif ? "Aktif" : "Nonaktif"}
                        </Badge>
                      </TableCell>
                    </TableRow>
                  ))}
                  {!tersaring.length && (
                    <TableRow>
                      <TableCell
                        colSpan={isAdmin ? 9 : 8}
                        className="py-10 text-center text-sm text-muted-foreground"
                      >
                        Tidak ada lembaga yang cocok dengan filter.
                      </TableCell>
                    </TableRow>
                  )}
                </TableBody>
              </Table>
            </>
          ) : (
            <div className="py-16 text-center">
              <p className="font-semibold">Belum ada lembaga desa</p>
              <p className="mt-1 text-sm text-muted-foreground">
                Tambahkan PKK, Karang Taruna, BPD, LPM, atau Posyandu.
              </p>
            </div>
          )}
        </CardContent>
      </Card>

      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent className="max-h-[88vh] max-w-2xl overflow-y-auto">
          <DialogHeader>
            <DialogTitle>{editing ? "Ubah Lembaga" : "Tambah Lembaga"}</DialogTitle>
            <DialogDescription>
              Catat pengurus, kategori, dan jumlah anggota lembaga kemasyarakatan desa.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={save} className="space-y-4">
            <div className="grid gap-4 sm:grid-cols-2">
              <Field label="Kode lembaga">
                <Input
                  value={form.kode}
                  maxLength={20}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, kode: event.target.value }))
                  }
                  placeholder="PKK-01"
                />
              </Field>
              <Field label="Nama lembaga" required>
                <Input
                  required
                  value={form.nama}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, nama: event.target.value }))
                  }
                  placeholder="Posyandu Mawar"
                />
              </Field>
              <Field label="Jenis">
                <Select
                  value={form.jenis}
                  onChange={(event) =>
                    setForm((current) => ({
                      ...current,
                      jenis: event.target.value as JenisLembaga,
                    }))
                  }
                >
                  {JENIS_OPTIONS.map((option) => (
                    <option key={option.value} value={option.value}>
                      {option.label}
                    </option>
                  ))}
                </Select>
              </Field>
              <Field label="Kategori">
                <Select
                  value={form.kategoriId}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, kategoriId: event.target.value }))
                  }
                >
                  <option value="">Tanpa kategori</option>
                  {(kategoriList ?? []).map((item) => (
                    <option key={item.id} value={item.id}>
                      {item.nama}
                    </option>
                  ))}
                </Select>
              </Field>
              <Field label="Ketua (penduduk)">
                <Select
                  value={form.ketuaId}
                  onChange={(event) => {
                    const id = event.target.value;
                    const orang = penduduk.find((item) => String(item.id) === id);
                    setForm((current) => ({
                      ...current,
                      ketuaId: id,
                      ketua: orang?.nama ?? current.ketua,
                    }));
                  }}
                >
                  <option value="">Tidak ditautkan</option>
                  {penduduk.map((item) => (
                    <option key={item.id} value={item.id}>
                      {item.nama} — {item.nik}
                    </option>
                  ))}
                </Select>
              </Field>
              <Field label="Nama ketua">
                <Input
                  value={form.ketua}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, ketua: event.target.value }))
                  }
                />
              </Field>
              <Field label="Sekretaris">
                <Input
                  value={form.sekretaris}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, sekretaris: event.target.value }))
                  }
                />
              </Field>
              <Field label="Jumlah anggota">
                <Input
                  type="number"
                  min={0}
                  value={form.anggota}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, anggota: event.target.value }))
                  }
                />
              </Field>
              <Field label="No. SK pendirian">
                <Input
                  value={form.noSkPendirian}
                  onChange={(event) =>
                    setForm((current) => ({
                      ...current,
                      noSkPendirian: event.target.value,
                    }))
                  }
                />
              </Field>
              <Field label="Alamat">
                <Input
                  value={form.alamat}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, alamat: event.target.value }))
                  }
                />
              </Field>
              <div className="sm:col-span-2">
                <Field label="URL / data logo lembaga">
                  <Input
                    value={form.logo}
                    onChange={(event) =>
                      setForm((current) => ({ ...current, logo: event.target.value }))
                    }
                    placeholder="/logo-pkk.png"
                  />
                </Field>
              </div>
              <div className="sm:col-span-2">
                <Field label="Keterangan">
                  <Textarea
                    rows={3}
                    value={form.keterangan}
                    onChange={(event) =>
                      setForm((current) => ({ ...current, keterangan: event.target.value }))
                    }
                  />
                </Field>
              </div>
            </div>

            <label className="flex items-center gap-2 text-sm">
              <input
                type="checkbox"
                checked={form.aktif}
                onChange={(event) =>
                  setForm((current) => ({ ...current, aktif: event.target.checked }))
                }
                className="h-4 w-4 rounded border-input accent-emerald-600"
              />
              Lembaga aktif
            </label>

            <DialogFooter>
              <Button type="button" variant="outline" onClick={() => setFormOpen(false)}>
                Batal
              </Button>
              <Button type="submit" disabled={saving}>
                {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 lembaga?</DialogTitle>
            <DialogDescription>
              Lembaga <span className="font-semibold">{deleteTarget?.nama}</span> beserta
              daftar anggotanya akan dihapus permanen.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDeleteTarget(null)}>
              Batal
            </Button>
            <Button variant="destructive" onClick={remove} disabled={deleting}>
              {deleting ? "Menghapus…" : "Hapus"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={konfirmasiHapus} onOpenChange={setKonfirmasiHapus}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus data terpilih?</DialogTitle>
            <DialogDescription>
              {dipilih.length} lembaga beserta daftar anggotanya akan dihapus permanen.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setKonfirmasiHapus(false)}>
              Batal
            </Button>
            <Button variant="destructive" onClick={hapusTerpilih} disabled={menghapus}>
              {menghapus ? "Menghapus…" : "Hapus"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={kategoriOpen} onOpenChange={setKategoriOpen}>
        <DialogContent className="max-h-[88vh] max-w-xl overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Kategori Lembaga</DialogTitle>
            <DialogDescription>
              Kategori digunakan untuk mengelompokkan lembaga desa.
            </DialogDescription>
          </DialogHeader>

          <form
            onSubmit={saveKategori}
            className="grid gap-3 rounded-lg border bg-secondary/30 p-3 sm:grid-cols-[1fr_1.4fr_auto] sm:items-end"
          >
            <div className="space-y-1">
              <Label htmlFor="kategori-nama">Nama kategori</Label>
              <Input
                id="kategori-nama"
                required
                maxLength={80}
                value={kategoriForm.nama}
                onChange={(event) =>
                  setKategoriForm((current) => ({ ...current, nama: event.target.value }))
                }
                placeholder="Pemberdayaan Perempuan"
              />
            </div>
            <div className="space-y-1">
              <Label htmlFor="kategori-deskripsi">Deskripsi</Label>
              <Input
                id="kategori-deskripsi"
                value={kategoriForm.deskripsi}
                onChange={(event) =>
                  setKategoriForm((current) => ({
                    ...current,
                    deskripsi: event.target.value,
                  }))
                }
              />
            </div>
            <Button type="submit" disabled={kategoriSaving}>
              {kategoriForm.id ? "Simpan" : "Tambah"}
            </Button>
          </form>

          <div className="divide-y rounded-lg border">
            {(kategoriList ?? []).map((item) => (
              <div
                key={item.id}
                className="flex items-center justify-between gap-3 px-3 py-2"
              >
                <div className="min-w-0">
                  <div className="font-medium">{item.nama}</div>
                  {item.deskripsi && (
                    <div className="truncate text-xs text-muted-foreground">
                      {item.deskripsi}
                    </div>
                  )}
                </div>
                <div className="flex shrink-0 gap-1">
                  <Button
                    variant="ghost"
                    size="icon"
                    className="h-8 w-8"
                    onClick={() =>
                      setKategoriForm({
                        id: item.id,
                        nama: item.nama,
                        deskripsi: item.deskripsi ?? "",
                      })
                    }
                    aria-label="Ubah kategori"
                  >
                    <FilePenLine className="h-4 w-4" />
                  </Button>
                  <Button
                    variant="ghost"
                    size="icon"
                    className="h-8 w-8 text-destructive hover:text-destructive"
                    onClick={() => removeKategori(item)}
                    aria-label="Hapus kategori"
                  >
                    <Trash2 className="h-4 w-4" />
                  </Button>
                </div>
              </div>
            ))}
            {!(kategoriList ?? []).length && (
              <p className="px-3 py-6 text-center text-sm text-muted-foreground">
                Belum ada kategori.
              </p>
            )}
          </div>
        </DialogContent>
      </Dialog>

      <Dialog
        open={!!anggotaTarget}
        onOpenChange={(open) => {
          if (!open) {
            setAnggotaTarget(null);
            setAnggotaForm({ pendudukId: "", noAnggota: "0", keterangan: "" });
          }
        }}
      >
        <DialogContent className="max-h-[88vh] max-w-2xl overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Anggota {anggotaTarget?.nama}</DialogTitle>
            <DialogDescription>
              Daftar anggota lembaga yang tertaut dengan data penduduk desa.
            </DialogDescription>
          </DialogHeader>

          {isAdmin && (
            <form
              onSubmit={addAnggota}
              className="grid gap-3 rounded-lg border bg-secondary/30 p-3 sm:grid-cols-[1.4fr_90px_1fr_auto] sm:items-end"
            >
              <div className="space-y-1">
                <Label>Penduduk</Label>
                <Select
                  required
                  value={anggotaForm.pendudukId}
                  onChange={(event) =>
                    setAnggotaForm((current) => ({
                      ...current,
                      pendudukId: event.target.value,
                    }))
                  }
                >
                  <option value="">Pilih penduduk</option>
                  {penduduk.map((item) => (
                    <option key={item.id} value={item.id}>
                      {item.nama} — {item.nik}
                    </option>
                  ))}
                </Select>
              </div>
              <div className="space-y-1">
                <Label>No. anggota</Label>
                <Input
                  type="number"
                  min={0}
                  value={anggotaForm.noAnggota}
                  onChange={(event) =>
                    setAnggotaForm((current) => ({
                      ...current,
                      noAnggota: event.target.value,
                    }))
                  }
                />
              </div>
              <div className="space-y-1">
                <Label>Keterangan</Label>
                <Input
                  value={anggotaForm.keterangan}
                  onChange={(event) =>
                    setAnggotaForm((current) => ({
                      ...current,
                      keterangan: event.target.value,
                    }))
                  }
                  placeholder="Bendahara"
                />
              </div>
              <Button type="submit" disabled={kategoriSaving}>
                <UserPlus className="h-4 w-4" />
                Tambah
              </Button>
            </form>
          )}

          <div className="overflow-hidden rounded-lg border">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead className="w-16">No</TableHead>
                  <TableHead>Nama</TableHead>
                  <TableHead>NIK</TableHead>
                  <TableHead>Keterangan</TableHead>
                  {isAdmin && <TableHead className="w-12 print:hidden" />}
                </TableRow>
              </TableHeader>
              <TableBody>
                {(anggotaList ?? []).map((item) => (
                  <TableRow key={item.id}>
                    <TableCell>{item.noAnggota}</TableCell>
                    <TableCell className="font-medium">
                      {item.penduduk?.nama ?? "-"}
                    </TableCell>
                    <TableCell className="font-mono text-xs">
                      {item.penduduk?.nik ?? "-"}
                    </TableCell>
                    <TableCell className="text-sm text-muted-foreground">
                      {item.keterangan ?? "-"}
                    </TableCell>
                    {isAdmin && (
                      <TableCell className="print:hidden">
                        <Button
                          variant="ghost"
                          size="icon"
                          className="h-8 w-8 text-destructive hover:text-destructive"
                          onClick={() => removeAnggota(item)}
                          aria-label="Hapus anggota"
                        >
                          <Trash2 className="h-4 w-4" />
                        </Button>
                      </TableCell>
                    )}
                  </TableRow>
                ))}
                {!(anggotaList ?? []).length && (
                  <TableRow>
                    <TableCell
                      colSpan={isAdmin ? 5 : 4}
                      className="py-8 text-center text-sm text-muted-foreground"
                    >
                      Belum ada anggota.
                    </TableCell>
                  </TableRow>
                )}
              </TableBody>
            </Table>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}

function Field({
  label,
  required,
  children,
}: {
  label: string;
  required?: boolean;
  children: React.ReactNode;
}) {
  return (
    <div className="space-y-1.5">
      <Label>
        {label}
        {required && <span className="ml-0.5 text-destructive">*</span>}
      </Label>
      {children}
    </div>
  );
}
