"use client";

import { useState } from "react";
import useSWR from "swr";
import {
  ClipboardList,
  Download,
  FilePenLine,
  Plus,
  Printer,
  SlidersHorizontal,
  Trash2,
  UserPlus,
  UsersRound,
} from "lucide-react";
import { toast } from "sonner";
import type {
  DataSuplemen,
  Desa,
  Keluarga,
  Paginated,
  Penduduk,
  PesertaSuplemen,
  SasaranSuplemen,
} from "@/lib/types";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import { cetakHtml, escapeHtml, kopDesa } from "@/lib/cetak";
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";

type FormState = {
  nama: string;
  sasaran: SasaranSuplemen;
  tahun: string;
  keterangan: string;
  aktif: boolean;
};

const emptyForm: FormState = {
  nama: "",
  sasaran: "PENDUDUK",
  tahun: String(new Date().getFullYear()),
  keterangan: "",
  aktif: true,
};

function labelSasaran(value: SasaranSuplemen) {
  return value === "PENDUDUK" ? "Penduduk" : "Keluarga";
}

const KOLOM_SUPLEMEN_CSV = [
  "Nama Data",
  "Jumlah Terdata",
  "Sasaran",
  "Tahun",
  "Status",
  "Keterangan",
];

export default function DataSuplemenPage() {
  const { user } = useSession();
  const canMutate = user?.role === "ADMIN" || user?.role === "OPERATOR";

  const { data, isLoading, mutate } = useSWR<DataSuplemen[]>(
    "/data-suplemen",
    fetcher,
  );
  const { data: desa } = useSWR<Desa>("/desa", fetcher);
  const daftar = data ?? [];

  const [sasaranFilter, setSasaranFilter] = useState("");
  const [tahunFilter, setTahunFilter] = useState("");
  const tersaring = daftar.filter((item) => {
    if (sasaranFilter && item.sasaran !== sasaranFilter) return false;
    if (tahunFilter && String(item.tahun ?? "") !== tahunFilter) return false;
    return true;
  });
  const tahunOptions = Array.from(
    new Set(daftar.map((item) => item.tahun).filter((value): value is number => !!value)),
  ).sort((a, b) => b - a);

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

  const [pesertaTarget, setPesertaTarget] = useState<DataSuplemen | null>(null);
  const [pilihanPeserta, setPilihanPeserta] = useState("");
  const [keteranganPeserta, setKeteranganPeserta] = useState("");
  const [adding, setAdding] = useState(false);
  const [removingId, setRemovingId] = useState<number | null>(null);

  const pesertaKey = pesertaTarget
    ? `/data-suplemen/${pesertaTarget.id}/peserta`
    : null;
  const { data: peserta, mutate: mutatePeserta } = useSWR<PesertaSuplemen[]>(
    pesertaKey,
    fetcher,
  );

  const { data: pendudukList } = useSWR<Paginated<Penduduk>>(
    "/penduduk?limit=200",
    fetcher,
  );
  const { data: keluargaList } = useSWR<Paginated<Keluarga>>(
    "/keluarga?limit=200",
    fetcher,
  );

  const pilihanOptions =
    pesertaTarget?.sasaran === "PENDUDUK"
      ? (pendudukList?.data ?? []).map((item) => ({
          value: String(item.id),
          label: `${item.nama} — ${item.nik}`,
        }))
      : (keluargaList?.data ?? []).map((item) => ({
          value: String(item.id),
          label: `${item.noKk} — ${item.kepalaKeluarga?.nama ?? "Tanpa kepala"}`,
        }));

  function barisSuplemenCsv(item: DataSuplemen) {
    return [
      item.nama,
      String(item._count?.peserta ?? 0),
      labelSasaran(item.sasaran),
      item.tahun ? String(item.tahun) : "",
      item.aktif ? "Aktif" : "Nonaktif",
      item.keterangan ?? "",
    ];
  }

  function cetakDaftar(rows: DataSuplemen[], judul = "Daftar Data Suplemen") {
    if (!rows.length) {
      toast.error("Belum ada data untuk dicetak");
      return;
    }
    const isi = `
      ${kopDesa(desa, judul)}
      <table><thead><tr><th>No</th><th>Nama Data</th><th>Jumlah Terdata</th><th>Sasaran</th><th>Tahun</th><th>Status</th></tr></thead>
      <tbody>${rows
        .map(
          (item, index) =>
            `<tr><td class="num">${index + 1}</td><td>${escapeHtml(item.nama)}</td><td class="num">${item._count?.peserta ?? 0}</td><td>${escapeHtml(labelSasaran(item.sasaran))}</td><td>${item.tahun ?? "-"}</td><td>${item.aktif ? "Aktif" : "Nonaktif"}</td></tr>`,
        )
        .join("")}</tbody></table>`;
    if (!cetakHtml(judul, isi)) {
      toast.error("Izinkan pop-up untuk mencetak");
    }
  }

  function unduh(rows: DataSuplemen[] = tersaring) {
    if (!rows.length) {
      toast.error("Belum ada data untuk diunduh");
      return;
    }
    unduhCsv(
      `data-suplemen-${new Date().toISOString().slice(0, 10)}.csv`,
      KOLOM_SUPLEMEN_CSV,
      rows.map(barisSuplemenCsv),
    );
    toast.success(`${rows.length} data suplemen diunduh`);
  }

  function toggleSemua() {
    const ids = tersaring.map((item) => item.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 tersaring.filter((item) => selected.includes(item.id));
  }

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

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

  function openEdit(item: DataSuplemen) {
    setEditing(item);
    setForm({
      nama: item.nama,
      sasaran: item.sasaran,
      tahun: item.tahun ? String(item.tahun) : "",
      keterangan: item.keterangan ?? "",
      aktif: item.aktif,
    });
    setFormOpen(true);
  }

  async function save(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSaving(true);
    try {
      const payload = {
        nama: form.nama,
        aktif: form.aktif,
        ...(editing ? {} : { sasaran: form.sasaran }),
        ...(form.tahun ? { tahun: Number(form.tahun) } : {}),
        ...(form.keterangan ? { keterangan: form.keterangan } : {}),
      };
      if (editing) {
        await apiSend(`/data-suplemen/${editing.id}`, "PATCH", payload);
        toast.success("Data suplemen diperbarui");
      } else {
        await apiSend("/data-suplemen", "POST", payload);
        toast.success("Data suplemen 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(`/data-suplemen/${deleteTarget.id}`, "DELETE");
      toast.success("Data suplemen dihapus");
      setDeleteTarget(null);
      await mutate();
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal menghapus data",
      );
    } finally {
      setDeleting(false);
    }
  }

  function openPeserta(item: DataSuplemen) {
    setPesertaTarget(item);
    setPilihanPeserta("");
    setKeteranganPeserta("");
  }

  async function addPeserta() {
    if (!pesertaTarget || !pilihanPeserta) {
      toast.error("Pilih peserta terlebih dahulu");
      return;
    }
    setAdding(true);
    try {
      await apiSend(`/data-suplemen/${pesertaTarget.id}/peserta`, "POST", {
        ...(pesertaTarget.sasaran === "PENDUDUK"
          ? { pendudukId: Number(pilihanPeserta) }
          : { keluargaId: Number(pilihanPeserta) }),
        ...(keteranganPeserta ? { keterangan: keteranganPeserta } : {}),
      });
      toast.success("Peserta ditambahkan");
      setPilihanPeserta("");
      setKeteranganPeserta("");
      await mutatePeserta();
      await mutate();
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal menambah peserta",
      );
    } finally {
      setAdding(false);
    }
  }

  async function removePeserta(pesertaId: number) {
    if (!pesertaTarget) return;
    setRemovingId(pesertaId);
    try {
      await apiSend(
        `/data-suplemen/${pesertaTarget.id}/peserta/${pesertaId}`,
        "DELETE",
      );
      toast.success("Peserta dihapus");
      await mutatePeserta();
      await mutate();
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal menghapus peserta",
      );
    } finally {
      setRemovingId(null);
    }
  }

  function cetakPeserta() {
    if (!pesertaTarget) return;
    const isi = `
      ${kopDesa(desa, "Daftar Peserta Data Suplemen")}
      <table class="info">
        <tr><td>Nama data suplemen</td><td>:</td><td><strong>${escapeHtml(pesertaTarget.nama)}</strong></td></tr>
        <tr><td>Sasaran</td><td>:</td><td>${escapeHtml(labelSasaran(pesertaTarget.sasaran))}</td></tr>
        <tr><td>Tahun</td><td>:</td><td>${escapeHtml(pesertaTarget.tahun ?? "-")}</td></tr>
        <tr><td>Jumlah peserta</td><td>:</td><td>${peserta?.length ?? 0}</td></tr>
      </table>
      <table>
        <thead><tr><th>No</th><th>Nama</th><th>Identitas</th><th>Keterangan</th></tr></thead>
        <tbody>
          ${(peserta ?? [])
            .map(
              (row, index) =>
                `<tr><td class="num">${index + 1}</td><td>${escapeHtml(
                  row.penduduk?.nama ??
                    row.keluarga?.kepalaKeluarga?.nama ??
                    "Tanpa nama",
                )}</td><td>${escapeHtml(row.penduduk?.nik ?? row.keluarga?.noKk ?? "-")}</td><td>${escapeHtml(row.keterangan ?? "-")}</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(`Peserta ${pesertaTarget.nama}`, isi)) {
      toast.error("Izinkan pop-up untuk mencetak daftar peserta");
    }
  }

  const totalPeserta = daftar.reduce(
    (total, item) => total + (item._count?.peserta ?? 0),
    0,
  );

  return (
    <div className="animate-fade-in space-y-6">
      <PageHeader
        title="Data Suplemen"
        description="Kumpulan data tambahan di luar data pokok penduduk, misalnya penerima bantuan atau program desa."
        action={
          <div className="flex flex-wrap gap-2">
            <Button variant="outline" onClick={() => cetakDaftar(tersaring)}>
              <Printer className="h-4 w-4" />
              Cetak
            </Button>
            <Button variant="outline" onClick={() => unduh()}>
              <Download className="h-4 w-4" />
              Unduh
            </Button>
            {canMutate && (
              <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 Data Suplemen 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);
                        unduh(dataTerpilih());
                      }}
                    >
                      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} disabled={!canMutate}>
              <Plus className="h-4 w-4" />
              Tambah Data Suplemen
            </Button>
          </div>
        }
      />

      <div className="grid gap-4 sm:grid-cols-3">
        <StatCard title="Total suplemen" value={daftar.length} icon={ClipboardList} />
        <StatCard
          title="Suplemen aktif"
          value={daftar.filter((item) => item.aktif).length}
          icon={ClipboardList}
          tone="sky"
        />
        <StatCard title="Total peserta" value={totalPeserta} icon={UsersRound} tone="amber" />
      </div>

      <div className="flex flex-wrap items-center gap-2">
        <Select
          value={sasaranFilter}
          onChange={(event) => setSasaranFilter(event.target.value)}
          aria-label="Filter sasaran"
          className="w-full sm:w-44"
        >
          <option value="">Semua sasaran</option>
          <option value="PENDUDUK">Penduduk</option>
          <option value="KELUARGA">Keluarga</option>
        </Select>
        <Select
          value={tahunFilter}
          onChange={(event) => setTahunFilter(event.target.value)}
          aria-label="Filter tahun"
          className="w-full sm:w-40"
        >
          <option value="">Semua tahun</option>
          {tahunOptions.map((tahun) => (
            <option key={tahun} value={tahun}>
              {tahun}
            </option>
          ))}
        </Select>
        {(sasaranFilter || tahunFilter) && (
          <Button
            type="button"
            variant="ghost"
            onClick={() => {
              setSasaranFilter("");
              setTahunFilter("");
            }}
          >
            Bersihkan
          </Button>
        )}
      </div>

      <Card>
        <CardContent className="p-5">
          <div className="overflow-x-auto">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead className="w-16">
                    <div className="flex items-center gap-2">
                      <input
                        type="checkbox"
                        checked={
                          tersaring.length > 0 &&
                          tersaring.every((item) => selected.includes(item.id))
                        }
                        onChange={toggleSemua}
                        disabled={!canMutate}
                        aria-label="Pilih semua data suplemen"
                      />
                      <span>No</span>
                    </div>
                  </TableHead>
                  <TableHead>Aksi</TableHead>
                  <TableHead>Nama Data</TableHead>
                  <TableHead>Jumlah Terdata</TableHead>
                  <TableHead>Sasaran</TableHead>
                  <TableHead>Tahun</TableHead>
                  <TableHead>Status</TableHead>
                  <TableHead className="hidden xl:table-cell">Keterangan</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {isLoading ? (
                  <TableRow>
                    <TableCell
                      colSpan={8}
                      className="py-10 text-center text-muted-foreground"
                    >
                      Memuat data…
                    </TableCell>
                  </TableRow>
                ) : tersaring.length ? (
                  tersaring.map((item, index) => (
                    <TableRow key={item.id}>
                      <TableCell>
                        <div className="flex items-center gap-2">
                          <input
                            type="checkbox"
                            checked={selected.includes(item.id)}
                            onChange={() => toggleSatu(item.id)}
                            disabled={!canMutate}
                            aria-label={`Pilih ${item.nama}`}
                          />
                          <span className="text-xs text-muted-foreground">
                            {index + 1}
                          </span>
                        </div>
                      </TableCell>
                      <TableCell>
                        <div className="flex gap-1">
                          <Button
                            variant="ghost"
                            size="sm"
                            aria-label="Kelola peserta"
                            onClick={() => openPeserta(item)}
                          >
                            <UserPlus className="h-4 w-4" />
                            Peserta
                          </Button>
                          {canMutate && (
                            <>
                              <Button
                                variant="ghost"
                                size="icon"
                                className="h-8 w-8"
                                aria-label="Ubah"
                                onClick={() => openEdit(item)}
                              >
                                <FilePenLine className="h-4 w-4" />
                              </Button>
                              <Button
                                variant="ghost"
                                size="icon"
                                className="h-8 w-8 text-destructive hover:text-destructive"
                                aria-label="Hapus"
                                onClick={() => setDeleteTarget(item)}
                              >
                                <Trash2 className="h-4 w-4" />
                              </Button>
                            </>
                          )}
                        </div>
                      </TableCell>
                      <TableCell>
                        <button
                          type="button"
                          onClick={() => openPeserta(item)}
                          className="text-left font-medium hover:text-emerald-700 hover:underline"
                        >
                          {item.nama}
                        </button>
                      </TableCell>
                      <TableCell>
                        <Badge variant="secondary">
                          {item._count?.peserta ?? 0} {labelSasaran(item.sasaran)}
                        </Badge>
                      </TableCell>
                      <TableCell>{labelSasaran(item.sasaran)}</TableCell>
                      <TableCell>{item.tahun ?? "-"}</TableCell>
                      <TableCell>
                        <Badge variant={item.aktif ? "success" : "secondary"}>
                          {item.aktif ? "Aktif" : "Nonaktif"}
                        </Badge>
                      </TableCell>
                      <TableCell className="hidden xl:table-cell max-w-[300px] truncate text-muted-foreground">
                        {item.keterangan ?? "-"}
                      </TableCell>
                    </TableRow>
                  ))
                ) : (
                  <TableRow>
                    <TableCell
                      colSpan={8}
                      className="py-12 text-center text-muted-foreground"
                    >
                      {sasaranFilter || tahunFilter
                        ? "Tidak ada data suplemen yang cocok dengan filter."
                        : "Belum ada data suplemen."}
                    </TableCell>
                  </TableRow>
                )}
              </TableBody>
            </Table>
          </div>
        </CardContent>
      </Card>

      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>
              {editing ? "Ubah Data Suplemen" : "Tambah Data Suplemen"}
            </DialogTitle>
            <DialogDescription>
              Data suplemen dapat berisi peserta penduduk atau keluarga.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={save} className="space-y-4">
            <Field label="Nama Data Suplemen" required>
              <Input
                required
                value={form.nama}
                onChange={(event) =>
                  setForm((current) => ({ ...current, nama: event.target.value }))
                }
                placeholder="Penerima Bantuan Pangan"
              />
            </Field>
            <div className="grid gap-4 sm:grid-cols-2">
              <Field label="Sasaran">
                <Select
                  value={form.sasaran}
                  disabled={!!editing}
                  onChange={(event) =>
                    setForm((current) => ({
                      ...current,
                      sasaran: event.target.value as SasaranSuplemen,
                    }))
                  }
                >
                  <option value="PENDUDUK">Penduduk</option>
                  <option value="KELUARGA">Keluarga</option>
                </Select>
              </Field>
              <Field label="Tahun">
                <Input
                  type="number"
                  min={2000}
                  max={2100}
                  value={form.tahun}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, tahun: event.target.value }))
                  }
                />
              </Field>
            </div>
            <Field label="Keterangan">
              <Textarea
                rows={3}
                value={form.keterangan}
                onChange={(event) =>
                  setForm((current) => ({
                    ...current,
                    keterangan: event.target.value,
                  }))
                }
              />
            </Field>

            <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"
              />
              Data suplemen aktif
            </label>

            <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={!!pesertaTarget}
        onOpenChange={(open) => !open && setPesertaTarget(null)}
      >
        <DialogContent className="max-h-[85vh] max-w-2xl overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Peserta — {pesertaTarget?.nama}</DialogTitle>
            <DialogDescription>
              Sasaran {pesertaTarget ? labelSasaran(pesertaTarget.sasaran) : "-"}.
              Tambahkan atau hapus peserta data suplemen ini.
            </DialogDescription>
          </DialogHeader>

          <div className="space-y-3 rounded-lg border p-4">
            <div className="grid gap-3 sm:grid-cols-[1fr_1fr_auto]">
              <Select
                value={pilihanPeserta}
                onChange={(event) => setPilihanPeserta(event.target.value)}
              >
                <option value="">
                  {pesertaTarget?.sasaran === "PENDUDUK"
                    ? "Pilih penduduk"
                    : "Pilih keluarga"}
                </option>
                {pilihanOptions.map((option) => (
                  <option key={option.value} value={option.value}>
                    {option.label}
                  </option>
                ))}
              </Select>
              <Input
                value={keteranganPeserta}
                onChange={(event) => setKeteranganPeserta(event.target.value)}
                placeholder="Keterangan (opsional)"
              />
              <Button onClick={addPeserta} disabled={adding}>
                <UserPlus className="h-4 w-4" />
                {adding ? "Menambah…" : "Tambah"}
              </Button>
            </div>
          </div>

          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b text-left text-muted-foreground">
                  <th className="py-2 pr-3 font-medium">Peserta</th>
                  <th className="py-2 pr-3 font-medium">Identitas</th>
                  <th className="py-2 pr-3 font-medium">Keterangan</th>
                  <th className="py-2 text-right font-medium">Aksi</th>
                </tr>
              </thead>
              <tbody>
                {peserta?.length ? (
                  peserta.map((row) => (
                    <tr key={row.id} className="border-b last:border-0">
                      <td className="py-2 pr-3 font-medium">
                        {row.penduduk?.nama ??
                          row.keluarga?.kepalaKeluarga?.nama ??
                          "Tanpa nama"}
                        <span className="block text-xs font-normal text-muted-foreground">
                          {row.penduduk
                            ? row.penduduk.jenisKelamin === "L"
                              ? "Laki-laki"
                              : "Perempuan"
                            : "Kartu Keluarga"}
                        </span>
                      </td>
                      <td className="py-2 pr-3">
                        {row.penduduk?.nik ?? row.keluarga?.noKk ?? "-"}
                      </td>
                      <td className="py-2 pr-3">{row.keterangan ?? "-"}</td>
                      <td className="py-2 text-right">
                        <Button
                          variant="ghost"
                          size="icon"
                          aria-label="Hapus peserta"
                          className="text-destructive hover:text-destructive"
                          disabled={removingId === row.id}
                          onClick={() => removePeserta(row.id)}
                        >
                          <Trash2 className="h-4 w-4" />
                        </Button>
                      </td>
                    </tr>
                  ))
                ) : (
                  <tr>
                    <td colSpan={4} className="py-8 text-center text-muted-foreground">
                      Belum ada peserta pada data suplemen ini.
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>

          <DialogFooter>
            <Button variant="outline" onClick={() => setPesertaTarget(null)}>
              Kembali Ke Daftar Data Suplemen
            </Button>
            {canMutate && (
              <Button
                variant="outline"
                disabled={!pesertaTarget}
                onClick={() => {
                  if (!pesertaTarget) return;
                  const target = pesertaTarget;
                  setPesertaTarget(null);
                  openEdit(target);
                }}
              >
                <FilePenLine className="h-4 w-4" />
                Ubah
              </Button>
            )}
            <Button onClick={cetakPeserta} disabled={!peserta?.length}>
              <Printer className="h-4 w-4" />
              Cetak Daftar Peserta
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={!!deleteTarget} onOpenChange={(open) => !open && setDeleteTarget(null)}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus data suplemen?</DialogTitle>
            <DialogDescription>
              Data <span className="font-semibold">{deleteTarget?.nama}</span> beserta
              seluruh pesertanya 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>
    </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>
  );
}
