"use client";

import { useEffect, useState } from "react";
import useSWR from "swr";
import {
  Download,
  Eye,
  FilePenLine,
  Plus,
  Printer,
  Search,
  SlidersHorizontal,
  Trash2,
  Users,
} from "lucide-react";
import { toast } from "sonner";
import type { Desa, Keluarga, Paginated, Penduduk, Wilayah } from "@/lib/types";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import { cetakHtml, escapeHtml, kopDesa } from "@/lib/cetak";
import { unduhCsv } from "@/lib/sekretariat";
import { PageHeader } from "@/components/page-header";
import { FotoPenduduk } from "@/components/admin/foto-penduduk";
import { Pagination } from "@/components/pagination";
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 { formatDateShort, hitungUmur, labelGender, labelHubungan } from "@/lib/utils";

type FormState = {
  noKk: string;
  alamat: string;
  rtId: string;
  kelasSosial: string;
  kepalaKeluargaId: string;
  tglCetak: string;
};

const emptyForm: FormState = {
  noKk: "",
  alamat: "",
  rtId: "",
  kelasSosial: "",
  kepalaKeluargaId: "",
  tglCetak: "",
};

const KOLOM_KELUARGA_CSV = [
  "Nomor KK",
  "Kepala Keluarga",
  "NIK",
  "Tag ID Card",
  "Jumlah Anggota",
  "Jenis Kelamin",
  "Alamat",
  "Dusun",
  "RW",
  "RT",
  "Kelas Sosial",
  "Tanggal Terdaftar",
  "Tanggal Cetak KK",
];

export default function KeluargaPage() {
  const [page, setPage] = useState(1);
  const [search, setSearch] = useState("");
  const [q, setQ] = useState("");
  const [rtId, setRtId] = useState("");
  const [rwId, setRwId] = useState("");
  const [dusunId, setDusunId] = useState("");
  const [kelasSosial, setKelasSosial] = useState("");

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

  const [detailId, setDetailId] = useState<number | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<Keluarga | null>(null);
  const [deleting, setDeleting] = useState(false);
  const [selected, setSelected] = useState<number[]>([]);
  const [aksiTerbuka, setAksiTerbuka] = useState(false);
  const [mengunduh, setMengunduh] = useState(false);
  const [saringAlamat, setSaringAlamat] = useState({ dusunId: "", rwId: "" });

  const query = new URLSearchParams({ page: String(page), limit: "10" });
  if (q) query.set("q", q);
  if (rtId) query.set("rtId", rtId);
  if (rwId) query.set("rwId", rwId);
  if (dusunId) query.set("dusunId", dusunId);
  if (kelasSosial) query.set("kelasSosial", kelasSosial);

  const { data, isLoading, mutate } = useSWR<Paginated<Keluarga>>(
    `/keluarga?${query.toString()}`,
    fetcher,
  );
  const { data: wilayah } = useSWR<Wilayah[]>("/wilayah", fetcher);
  const { data: desa } = useSWR<Desa>("/desa", fetcher);
  const { data: pendudukList } = useSWR<Paginated<Penduduk>>(
    "/penduduk?limit=200",
    fetcher,
  );
  const { data: detail, isLoading: detailLoading } = useSWR<Keluarga>(
    detailId ? `/keluarga/${detailId}` : null,
    fetcher,
  );

  const allRegional = wilayah ?? [];
  const rtOptions = allRegional.filter((item) => item.level === "RT");
  const dusunOptions = allRegional.filter((item) => item.level === "DUSUN");
  const rwOptions = dusunId
    ? allRegional.filter(
        (item) => item.level === "RW" && item.parentId === Number(dusunId),
      )
    : allRegional.filter((item) => item.level === "RW");
  const rtFiltered = rwId
    ? rtOptions.filter((item) => item.parentId === Number(rwId))
    : rtOptions;
  const daftar = data?.data ?? [];
  const wargaById = new Map((pendudukList?.data ?? []).map((warga) => [warga.id, warga]));
  const adaFilter = Boolean(q || rtId || rwId || dusunId || kelasSosial);

  function rantaiWilayah(rtId: number | null | undefined) {
    const rt = allRegional.find((item) => item.id === rtId);
    const rw = rt ? allRegional.find((item) => item.id === rt.parentId) : undefined;
    const dusun = rw ? allRegional.find((item) => item.id === rw.parentId) : undefined;
    return {
      dusunId: String(dusun?.id ?? ""),
      rwId: String(rw?.id ?? ""),
      dusun: dusun?.nama ?? "",
      rw: rw?.nama ?? "",
      rt: rt?.nama ?? "",
    };
  }

  const rwFormOptions = allRegional.filter(
    (item) =>
      item.level === "RW" &&
      (!saringAlamat.dusunId || item.parentId === Number(saringAlamat.dusunId)),
  );
  const rtFormOptions = rtOptions.filter(
    (item) => !saringAlamat.rwId || item.parentId === Number(saringAlamat.rwId),
  );

  useEffect(() => {
    setPage(1);
  }, [q, rtId, rwId, dusunId, kelasSosial]);

  function cetakKartu(keluarga: Keluarga) {
    const anggota = keluarga.anggota ?? [];
    const wilayah = rantaiWilayah(keluarga.rtId);
    const isi = `
      ${kopDesa(desa, "Kartu Keluarga")}
      <table class="info">
        <tr><td>Nomor Kartu Keluarga</td><td>:</td><td><strong>${escapeHtml(keluarga.noKk)}</strong></td></tr>
        <tr><td>Kepala Keluarga</td><td>:</td><td>${escapeHtml(keluarga.kepalaKeluarga?.nama ?? "-")}</td></tr>
        <tr><td>Alamat Sekarang</td><td>:</td><td>${escapeHtml(keluarga.alamat ?? "-")}</td></tr>
        <tr><td>Dusun</td><td>:</td><td>${escapeHtml(wilayah.dusun || "-")}</td></tr>
        <tr><td>RW</td><td>:</td><td>${escapeHtml(wilayah.rw || "-")}</td></tr>
        <tr><td>RT</td><td>:</td><td>${escapeHtml(wilayah.rt || "-")}</td></tr>
        <tr><td>Kelas Sosial</td><td>:</td><td>${escapeHtml(keluarga.kelasSosial ? `Kelas ${keluarga.kelasSosial}` : "-")}</td></tr>
        <tr><td>Tanggal Terdaftar</td><td>:</td><td>${escapeHtml(formatDateShort(keluarga.tglDaftar))}</td></tr>
      </table>
      <table>
        <thead><tr><th>No</th><th>Nama</th><th>NIK</th><th>L/P</th><th>Tempat, Tgl Lahir</th><th>Agama</th><th>Pendidikan</th><th>Pekerjaan</th><th>Status Kawin</th><th>Hubungan Dalam Keluarga</th></tr></thead>
        <tbody>
          ${anggota
            .map(
              (warga, index) =>
                `<tr><td class="num">${index + 1}</td><td>${escapeHtml(warga.nama)}</td><td>${escapeHtml(warga.nik)}</td><td>${warga.jenisKelamin === "L" ? "L" : "P"}</td><td>${escapeHtml(warga.tempatLahir ?? "-")}, ${escapeHtml(
                  warga.tanggalLahir
                    ? new Date(warga.tanggalLahir).toLocaleDateString("id-ID")
                    : "-",
                )}</td><td>${escapeHtml(warga.agama ?? "-")}</td><td>${escapeHtml(warga.pendidikan ?? "-")}</td><td>${escapeHtml(warga.pekerjaan ?? "-")}</td><td>${escapeHtml(warga.statusKawin ?? "-")}</td><td>${escapeHtml(labelHubungan(warga.hubunganKeluarga))}</td></tr>`,
            )
            .join("")}
        </tbody>
      </table>
      <div class="ttd">
        <div>
          <div>${escapeHtml((desa?.kecamatan ?? "Cipari").toUpperCase())}, ${new Date().toLocaleDateString("id-ID", { day: "2-digit", month: "long", year: "numeric" })}</div>
          <div>Kepala Desa ${escapeHtml((desa?.nama ?? "Mulyadadi").replace(/^Desa\s+/i, ""))}</div>
          <div class="ruang"></div>
          <div><strong>${escapeHtml(desa?.kepalaDesa ?? "-")}</strong></div>
        </div>
      </div>
    `;
    if (!cetakHtml(`Kartu Keluarga ${keluarga.noKk}`, isi)) {
      toast.error("Izinkan pop-up untuk mencetak kartu keluarga");
    }
  }

  function infoKepala(keluarga: Keluarga) {
    const warga = keluarga.kepalaKeluargaId
      ? wargaById.get(keluarga.kepalaKeluargaId)
      : undefined;
    const dasar = warga ?? keluarga.kepalaKeluarga;
    return {
      nama: dasar?.nama ?? "Belum ditentukan",
      nik: dasar?.nik ?? "-",
      tag: warga?.tagIdCard ?? "-",
      jk: warga ? labelGender(warga.jenisKelamin) : "-",
      pendudukId: dasar?.id ?? null,
      adaFoto: Boolean(dasar?.foto),
      versiFoto: dasar?.foto ?? null,
    };
  }

  function barisKeluargaCsv(keluarga: Keluarga) {
    const kepala = infoKepala(keluarga);
    const wilayah = rantaiWilayah(keluarga.rtId);
    return [
      keluarga.noKk,
      kepala.nama,
      kepala.nik,
      kepala.tag,
      String(keluarga._count?.anggota ?? 0),
      kepala.jk,
      keluarga.alamat ?? "",
      wilayah.dusun,
      wilayah.rw,
      wilayah.rt,
      keluarga.kelasSosial ? `Kelas ${keluarga.kelasSosial}` : "",
      formatDateShort(keluarga.tglDaftar),
      keluarga.tglCetak ? formatDateShort(keluarga.tglCetak) : "",
    ];
  }

  function cetakDaftar(rows: Keluarga[], judul = "Daftar Kartu Keluarga") {
    if (!rows.length) {
      toast.error("Belum ada data untuk dicetak");
      return;
    }
    const isi = `
      ${kopDesa(desa, judul)}
      <table><thead><tr><th>No</th><th>Nomor KK</th><th>Kepala Keluarga</th><th>NIK</th><th>Anggota</th><th>Alamat</th><th>Dusun</th><th>RW</th><th>RT</th></tr></thead>
      <tbody>${rows
        .map((keluarga, index) => {
          const kepala = infoKepala(keluarga);
          const wilayah = rantaiWilayah(keluarga.rtId);
          return `<tr><td class="num">${index + 1}</td><td>${escapeHtml(
            keluarga.noKk,
          )}</td><td>${escapeHtml(kepala.nama)}</td><td>${escapeHtml(
            kepala.nik,
          )}</td><td class="num">${keluarga._count?.anggota ?? 0}</td><td>${escapeHtml(
            keluarga.alamat ?? "-",
          )}</td><td>${escapeHtml(wilayah.dusun || "-")}</td><td>${escapeHtml(
            wilayah.rw || "-",
          )}</td><td>${escapeHtml(wilayah.rt || "-")}</td></tr>`;
        })
        .join("")}</tbody></table>`;
    if (!cetakHtml(judul, isi)) {
      toast.error("Izinkan pop-up untuk mencetak");
    }
  }

  async function unduh() {
    setMengunduh(true);
    try {
      const params = new URLSearchParams(query.toString());
      params.set("page", "1");
      params.set("limit", "200");
      const hasil = await fetcher<Paginated<Keluarga>>(`/keluarga?${params.toString()}`);
      const rows = hasil?.data ?? [];
      if (!rows.length) {
        toast.error("Belum ada data untuk diunduh");
        return;
      }
      unduhCsv(
        `data-keluarga-${new Date().toISOString().slice(0, 10)}.csv`,
        KOLOM_KELUARGA_CSV,
        rows.map(barisKeluargaCsv),
      );
      toast.success(`${rows.length} kartu keluarga diunduh`);
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal mengunduh data");
    } finally {
      setMengunduh(false);
    }
  }

  function toggleSemua() {
    const ids = daftar.map((keluarga) => keluarga.id);
    setSelected((current) =>
      ids.length && ids.every((id) => current.includes(id)) ? [] : ids,
    );
  }

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

  function dataTerpilih() {
    return daftar.filter((keluarga) => selected.includes(keluarga.id));
  }

  async function hapusTerpilih() {
    if (!selected.length) return;
    setAksiTerbuka(false);
    try {
      await Promise.all(selected.map((id) => apiSend(`/keluarga/${id}`, "DELETE")));
      toast.success(`${selected.length} kartu keluarga dihapus`);
      setSelected([]);
      await mutate();
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal menghapus data terpilih",
      );
    }
  }

  function nomorKkSementara() {
    const awilayah =
      daftar.find((keluarga) => /^\d{16}$/.test(keluarga.noKk))?.noKk.slice(0, 6) ??
      "330101";
    const acak = Array.from({ length: 10 }, () => Math.floor(Math.random() * 10)).join("");
    setForm((current) => ({ ...current, noKk: `${awilayah}${acak}` }));
    toast.success("Nomor KK sementara dibuat, silakan periksa kembali");
  }

  function pilihRt(id: string) {
    setForm((current) => ({ ...current, rtId: id }));
    const wilayah = rantaiWilayah(Number(id) || null);
    setSaringAlamat({ dusunId: wilayah.dusunId, rwId: wilayah.rwId });
  }

  function openCreate() {
    setEditing(null);
    setForm(emptyForm);
    setSaringAlamat({ dusunId: "", rwId: "" });
    setFormOpen(true);
  }

  function openEdit(keluarga: Keluarga) {
    setEditing(keluarga);
    setForm({
      noKk: keluarga.noKk,
      alamat: keluarga.alamat ?? "",
      rtId: keluarga.rtId ? String(keluarga.rtId) : "",
      kelasSosial: keluarga.kelasSosial ? String(keluarga.kelasSosial) : "",
      kepalaKeluargaId: keluarga.kepalaKeluargaId
        ? String(keluarga.kepalaKeluargaId)
        : "",
      tglCetak: keluarga.tglCetak ? keluarga.tglCetak.slice(0, 10) : "",
    });
    const wilayah = rantaiWilayah(keluarga.rtId);
    setSaringAlamat({ dusunId: wilayah.dusunId, rwId: wilayah.rwId });
    setFormOpen(true);
  }

  async function save(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSaving(true);

    const payload: Record<string, unknown> = { noKk: form.noKk };
    if (form.alamat) payload.alamat = form.alamat;
    if (form.rtId) payload.rtId = Number(form.rtId);
    if (form.kelasSosial) payload.kelasSosial = Number(form.kelasSosial);
    if (form.kepalaKeluargaId) payload.kepalaKeluargaId = Number(form.kepalaKeluargaId);
    payload.tglCetak = form.tglCetak || null;

    try {
      if (editing) {
        await apiSend(`/keluarga/${editing.id}`, "PATCH", payload);
        toast.success("Data keluarga diperbarui");
      } else {
        await apiSend("/keluarga", "POST", payload);
        toast.success("Kartu keluarga baru ditambahkan");
      }
      setFormOpen(false);
      setEditing(null);
      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(`/keluarga/${deleteTarget.id}`, "DELETE");
      toast.success("Kartu keluarga dihapus");
      setDeleteTarget(null);
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menghapus data");
    } finally {
      setDeleting(false);
    }
  }

  return (
    <div className="animate-fade-in space-y-6">
      <PageHeader
        title="Data Keluarga"
        description="Kelola kartu keluarga, kepala keluarga, dan anggota setiap KK."
        action={
          <div className="flex flex-wrap gap-2">
            <Button variant="outline" onClick={() => cetakDaftar(daftar)}>
              <Printer className="h-4 w-4" />
              Cetak Kartu Keluarga
            </Button>
            <Button variant="outline" onClick={unduh} disabled={mengunduh}>
              <Download className="h-4 w-4" />
              {mengunduh ? "Mengunduh…" : "Unduh Kartu Keluarga"}
            </Button>
            <div className="relative">
              <Button
                variant="outline"
                onClick={() => setAksiTerbuka((open) => !open)}
                disabled={!selected.length}
              >
                <SlidersHorizontal className="h-4 w-4" />
                Pilih Aksi Lainnya
                {selected.length > 0 && (
                  <span className="ml-1 rounded-full bg-white/25 px-1.5 text-xs">
                    {selected.length}
                  </span>
                )}
              </Button>
              {aksiTerbuka && (
                <div className="absolute right-0 z-20 mt-1 w-56 rounded-lg border bg-card p-1 shadow-lg">
                  <button
                    type="button"
                    className="block w-full rounded-md px-3 py-2 text-left text-sm hover:bg-muted"
                    onClick={() => {
                      setAksiTerbuka(false);
                      cetakDaftar(dataTerpilih(), "Daftar Kartu Keluarga Terpilih");
                    }}
                  >
                    Cetak Data Terpilih
                  </button>
                  <button
                    type="button"
                    className="block w-full rounded-md px-3 py-2 text-left text-sm hover:bg-muted"
                    onClick={() => {
                      setAksiTerbuka(false);
                      unduhCsv(
                        `keluarga-terpilih-${new Date().toISOString().slice(0, 10)}.csv`,
                        KOLOM_KELUARGA_CSV,
                        dataTerpilih().map(barisKeluargaCsv),
                      );
                    }}
                  >
                    Unduh Data Terpilih
                  </button>
                  <button
                    type="button"
                    className="block w-full rounded-md px-3 py-2 text-left text-sm text-destructive hover:bg-muted"
                    onClick={hapusTerpilih}
                  >
                    Hapus Data Terpilih
                  </button>
                </div>
              )}
            </div>
            <Button onClick={openCreate}>
              <Plus className="h-4 w-4" />
              Tambah KK Baru
            </Button>
          </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">
            <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 nomor KK, kepala keluarga, alamat…"
                className="pl-9"
              />
            </form>
            <div className="flex flex-wrap gap-2">
              <Select
                value={dusunId}
                onChange={(event) => {
                  setDusunId(event.target.value);
                  setRwId("");
                  setRtId("");
                }}
                aria-label="Filter dusun"
                className="w-full sm:w-40"
              >
                <option value="">Semua dusun</option>
                {dusunOptions.map((item) => (
                  <option key={item.id} value={item.id}>
                    {item.nama}
                  </option>
                ))}
              </Select>
              <Select
                value={rwId}
                onChange={(event) => {
                  setRwId(event.target.value);
                  setRtId("");
                }}
                aria-label="Filter RW"
                className="w-full sm:w-36"
              >
                <option value="">Semua RW</option>
                {rwOptions.map((item) => (
                  <option key={item.id} value={item.id}>
                    {item.nama}
                  </option>
                ))}
              </Select>
              <Select
                value={rtId}
                onChange={(event) => setRtId(event.target.value)}
                aria-label="Filter RT"
                className="w-full sm:w-36"
              >
                <option value="">Semua RT</option>
                {rtFiltered.map((rt) => (
                  <option key={rt.id} value={rt.id}>
                    {rt.nama}
                  </option>
                ))}
              </Select>
              <Select
                value={kelasSosial}
                onChange={(event) => setKelasSosial(event.target.value)}
                aria-label="Filter kelas sosial"
                className="w-full sm:w-36"
              >
                <option value="">Semua kelas</option>
                {[1, 2, 3, 4, 5].map((item) => (
                  <option key={item} value={item}>
                    Kelas {item}
                  </option>
                ))}
              </Select>
              {adaFilter && (
                <Button
                  type="button"
                  variant="ghost"
                  onClick={() => {
                    setSearch("");
                    setQ("");
                    setRtId("");
                    setRwId("");
                    setDusunId("");
                    setKelasSosial("");
                  }}
                >
                  Reset
                </Button>
              )}
            </div>
          </div>

          {isLoading ? (
            <div className="space-y-2 p-4">
              {Array.from({ length: 6 }).map((_, index) => (
                <div key={index} className="h-12 animate-pulse rounded-lg bg-muted" />
              ))}
            </div>
          ) : daftar.length ? (
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead className="w-16">
                    <div className="flex items-center gap-2">
                      <input
                        type="checkbox"
                        checked={
                          daftar.length > 0 && daftar.every((kk) => selected.includes(kk.id))
                        }
                        onChange={toggleSemua}
                        aria-label="Pilih semua keluarga"
                      />
                      <span>No</span>
                    </div>
                  </TableHead>
                  <TableHead>Aksi</TableHead>
                  <TableHead className="w-20">Foto</TableHead>
                  <TableHead>Nomor KK</TableHead>
                  <TableHead>Kepala Keluarga</TableHead>
                  <TableHead>NIK</TableHead>
                  <TableHead className="hidden xl:table-cell">Tag ID Card</TableHead>
                  <TableHead>Jumlah Anggota</TableHead>
                  <TableHead className="hidden lg:table-cell">Jenis Kelamin</TableHead>
                  <TableHead className="hidden lg:table-cell">Alamat</TableHead>
                  <TableHead className="hidden xl:table-cell">Dusun</TableHead>
                  <TableHead className="hidden xl:table-cell">RW</TableHead>
                  <TableHead>RT</TableHead>
                  <TableHead className="hidden xl:table-cell">Kelas Sosial</TableHead>
                  <TableHead>Tanggal Terdaftar</TableHead>
                  <TableHead className="hidden xl:table-cell">Tanggal Cetak KK</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {daftar.map((keluarga, index) => {
                  const kepala = infoKepala(keluarga);
                  const wilayah = rantaiWilayah(keluarga.rtId);
                  return (
                    <TableRow key={keluarga.id}>
                      <TableCell>
                        <div className="flex items-center gap-2">
                          <input
                            type="checkbox"
                            checked={selected.includes(keluarga.id)}
                            onChange={() => toggleSatu(keluarga.id)}
                            aria-label={`Pilih KK ${keluarga.noKk}`}
                          />
                          <span className="text-xs text-muted-foreground">{index + 1}</span>
                        </div>
                      </TableCell>
                      <TableCell>
                        <div className="flex gap-1">
                          <Button
                            variant="ghost"
                            size="icon"
                            className="h-8 w-8"
                            onClick={() => setDetailId(keluarga.id)}
                            aria-label="Lihat anggota"
                          >
                            <Eye className="h-4 w-4" />
                          </Button>
                          <Button
                            variant="ghost"
                            size="icon"
                            className="h-8 w-8"
                            onClick={() => openEdit(keluarga)}
                            aria-label="Ubah data"
                          >
                            <FilePenLine className="h-4 w-4" />
                          </Button>
                          <Button
                            variant="ghost"
                            size="icon"
                            className="h-8 w-8 text-destructive hover:text-destructive"
                            onClick={() => setDeleteTarget(keluarga)}
                            aria-label="Hapus data"
                          >
                            <Trash2 className="h-4 w-4" />
                          </Button>
                        </div>
                      </TableCell>
                      <TableCell>
                        <FotoPenduduk
                          pendudukId={kepala.pendudukId}
                          nama={kepala.nama}
                          adaFoto={kepala.adaFoto}
                          versi={kepala.versiFoto}
                        />
                      </TableCell>
                      <TableCell className="font-mono text-sm font-medium">
                        {keluarga.noKk}
                      </TableCell>
                      <TableCell>
                        <button
                          type="button"
                          onClick={() => setDetailId(keluarga.id)}
                          className="text-left font-medium hover:text-emerald-700 hover:underline"
                        >
                          {kepala.nama}
                        </button>
                      </TableCell>
                      <TableCell className="font-mono text-xs">{kepala.nik}</TableCell>
                      <TableCell className="hidden xl:table-cell font-mono text-xs text-muted-foreground">
                        {kepala.tag}
                      </TableCell>
                      <TableCell>
                        <Badge variant="secondary">
                          {keluarga._count?.anggota ?? 0} anggota
                        </Badge>
                      </TableCell>
                      <TableCell className="hidden lg:table-cell">{kepala.jk}</TableCell>
                      <TableCell className="hidden lg:table-cell max-w-[200px] truncate">
                        {keluarga.alamat ?? "-"}
                      </TableCell>
                      <TableCell className="hidden xl:table-cell">
                        {wilayah.dusun || "-"}
                      </TableCell>
                      <TableCell className="hidden xl:table-cell">{wilayah.rw || "-"}</TableCell>
                      <TableCell>{wilayah.rt || "-"}</TableCell>
                      <TableCell className="hidden xl:table-cell text-muted-foreground">
                        {keluarga.kelasSosial ? `Kelas ${keluarga.kelasSosial}` : "-"}
                      </TableCell>
                      <TableCell className="text-muted-foreground">
                        {formatDateShort(keluarga.tglDaftar)}
                      </TableCell>
                      <TableCell className="hidden xl:table-cell text-muted-foreground">
                        {keluarga.tglCetak ? formatDateShort(keluarga.tglCetak) : "-"}
                      </TableCell>
                    </TableRow>
                  );
                })}
              </TableBody>
            </Table>
          ) : (
            <div className="py-16 text-center">
              <p className="font-semibold">Belum ada kartu keluarga</p>
              <p className="mt-1 text-sm text-muted-foreground">
                Tambahkan kartu keluarga baru atau ubah filter pencarian.
              </p>
            </div>
          )}

          {data && data.data.length > 0 && (
            <Pagination
              page={data.meta.page}
              totalPages={data.meta.totalPages}
              total={data.meta.total}
              onChange={setPage}
            />
          )}
        </CardContent>
      </Card>

      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent className="max-w-xl">
          <DialogHeader>
            <DialogTitle>{editing ? "Ubah Kartu Keluarga" : "Tambah KK Baru"}</DialogTitle>
            <DialogDescription>
              Tentukan nomor KK, kepala keluarga, wilayah, dan kelas sosial.
            </DialogDescription>
          </DialogHeader>

          <form onSubmit={save} className="space-y-4">
            <div className="space-y-1.5">
              <Label>
                Nomor KK <span className="text-destructive">*</span>
              </Label>
              <div className="flex gap-2">
                <Input
                  required
                  inputMode="numeric"
                  maxLength={16}
                  pattern="\d{16}"
                  title="Nomor KK harus 16 digit angka"
                  value={form.noKk}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, noKk: event.target.value }))
                  }
                  placeholder="16 digit nomor KK"
                  className="flex-1"
                />
                <Button
                  type="button"
                  variant="outline"
                  className="shrink-0"
                  onClick={nomorKkSementara}
                >
                  No KK Sementara
                </Button>
              </div>
            </div>

            <div className="space-y-1.5">
              <Label>Kepala Keluarga</Label>
              <Select
                value={form.kepalaKeluargaId}
                onChange={(event) =>
                  setForm((current) => ({
                    ...current,
                    kepalaKeluargaId: event.target.value,
                  }))
                }
              >
                <option value="">Belum ditentukan</option>
                {(pendudukList?.data ?? []).map((warga) => (
                  <option key={warga.id} value={warga.id}>
                    {warga.nama} · {warga.nik}
                  </option>
                ))}
              </Select>
              <p className="text-xs text-muted-foreground">
                Penduduk yang dipilih otomatis ditandai sebagai kepala keluarga dan
                dihubungkan ke KK ini.
              </p>
            </div>

            <div className="grid gap-4 sm:grid-cols-3">
              <div className="space-y-1.5">
                <Label>Dusun</Label>
                <Select
                  value={saringAlamat.dusunId}
                  onChange={(event) => {
                    setSaringAlamat({ dusunId: event.target.value, rwId: "" });
                    setForm((current) => ({ ...current, rtId: "" }));
                  }}
                >
                  <option value="">Pilih dusun</option>
                  {dusunOptions.map((item) => (
                    <option key={item.id} value={item.id}>
                      {item.nama}
                    </option>
                  ))}
                </Select>
              </div>
              <div className="space-y-1.5">
                <Label>RW</Label>
                <Select
                  value={saringAlamat.rwId}
                  onChange={(event) => {
                    setSaringAlamat((current) => ({ ...current, rwId: event.target.value }));
                    setForm((current) => ({ ...current, rtId: "" }));
                  }}
                >
                  <option value="">Pilih RW</option>
                  {rwFormOptions.map((item) => (
                    <option key={item.id} value={item.id}>
                      {item.nama}
                    </option>
                  ))}
                </Select>
              </div>
              <div className="space-y-1.5">
                <Label>RT</Label>
                <Select value={form.rtId} onChange={(event) => pilihRt(event.target.value)}>
                  <option value="">Pilih RT</option>
                  {rtFormOptions.map((item) => (
                    <option key={item.id} value={item.id}>
                      {item.nama}
                    </option>
                  ))}
                </Select>
              </div>
            </div>

            <div className="grid gap-4 sm:grid-cols-2">
              <div className="space-y-1.5">
                <Label>Alamat Sekarang</Label>
                <Input
                  value={form.alamat}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, alamat: event.target.value }))
                  }
                  placeholder="Alamat rumah keluarga"
                />
              </div>

              <div className="space-y-1.5">
                <Label>Kelas Sosial</Label>
                <Input
                  type="number"
                  min={1}
                  max={5}
                  value={form.kelasSosial}
                  onChange={(event) =>
                    setForm((current) => ({
                      ...current,
                      kelasSosial: event.target.value,
                    }))
                  }
                  placeholder="1 - 5"
                />
              </div>

              <div className="space-y-1.5">
                <Label>Tanggal Cetak KK</Label>
                <Input
                  type="date"
                  value={form.tglCetak}
                  onChange={(event) =>
                    setForm((current) => ({
                      ...current,
                      tglCetak: event.target.value,
                    }))
                  }
                />
              </div>
            </div>

            <DialogFooter>
              <Button type="button" variant="outline" onClick={() => setFormOpen(false)}>
                Batal
              </Button>
              <Button type="submit" disabled={saving}>
                {saving ? "Menyimpan…" : "Simpan"}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <Dialog open={!!detailId} onOpenChange={(open) => !open && setDetailId(null)}>
        <DialogContent className="max-w-2xl">
          <DialogHeader>
            <DialogTitle>Anggota Keluarga</DialogTitle>
            <DialogDescription>
              {detail
                ? `KK ${detail.noKk} · ${detail.kepalaKeluarga?.nama ?? "Tanpa kepala keluarga"}`
                : "Memuat data keluarga…"}
            </DialogDescription>
          </DialogHeader>

          {detailLoading ? (
            <div className="space-y-2">
              {Array.from({ length: 4 }).map((_, index) => (
                <div key={index} className="h-10 animate-pulse rounded-lg bg-muted" />
              ))}
            </div>
          ) : detail?.anggota?.length ? (
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Nama</TableHead>
                  <TableHead>NIK</TableHead>
                  <TableHead>Jenis Kelamin</TableHead>
                  <TableHead>Umur</TableHead>
                  <TableHead>Hubungan Dalam Keluarga</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {detail.anggota.map((warga) => (
                  <TableRow key={warga.id}>
                    <TableCell className="font-medium">{warga.nama}</TableCell>
                    <TableCell className="font-mono text-xs">{warga.nik}</TableCell>
                    <TableCell>{labelGender(warga.jenisKelamin)}</TableCell>
                    <TableCell>{hitungUmur(warga.tanggalLahir)}</TableCell>
                    <TableCell className="text-muted-foreground">
                      {labelHubungan(warga.hubunganKeluarga)}
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          ) : (
            <div className="rounded-xl border border-dashed p-8 text-center">
              <Users className="mx-auto h-6 w-6 text-muted-foreground" />
              <p className="mt-2 text-sm font-medium">Belum ada anggota</p>
              <p className="text-xs text-muted-foreground">
                Hubungkan penduduk ke KK ini melalui menu Penduduk.
              </p>
            </div>
          )}

          <DialogFooter>
            <Button variant="outline" onClick={() => setDetailId(null)}>
              Kembali Ke Daftar Keluarga
            </Button>
            <Button
              variant="outline"
              disabled={!detail}
              onClick={() => {
                if (!detail) return;
                setDetailId(null);
                openEdit(detail);
              }}
            >
              <FilePenLine className="h-4 w-4" />
              Ubah
            </Button>
            <Button onClick={() => detail && cetakKartu(detail)} disabled={!detail}>
              <Printer className="h-4 w-4" />
              Cetak Kartu Keluarga
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={!!deleteTarget} onOpenChange={(open) => !open && setDeleteTarget(null)}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus kartu keluarga?</DialogTitle>
            <DialogDescription>
              KK <span className="font-semibold">{deleteTarget?.noKk}</span> akan dihapus.
              Seluruh anggota akan dilepas dari KK ini, tetapi data penduduk tetap tersimpan.
            </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>
    </div>
  );
}
