"use client";

import { useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import useSWR from "swr";
import {
  Ban,
  CheckCircle2,
  ChevronLeft,
  ChevronRight,
  Clock,
  Copy,
  Download,
  Eye,
  FilePlus2,
  FileText,
  Plus,
  Printer,
  Search,
  Settings2,
  Star,
  Trash2,
  Upload,
  XCircle,
} from "lucide-react";
import { toast } from "sonner";
import type {
  HeaderSurat,
  HasilImporJenis,
  OrientasiSurat,
  Paginated,
  PengaturanCetakSurat,
  Penduduk,
  PermohonanSurat,
  RingkasanSurat,
  SatuanMasaBerlaku,
  SuratJenis,
  UkuranKertas,
} from "@/lib/types";
import {
  ORIENTASI_SURAT,
  PILIHAN_HEADER_SURAT,
  SATUAN_MASA_BERLAKU,
  UKURAN_KERTAS,
} from "@/lib/types";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import { unduhCsv, unduhJson } from "@/lib/sekretariat";
import { useSession } from "@/lib/use-session";
import {
  DEFAULT_PENGATURAN_CETAK,
  labelMasaBerlaku as labelMasaBerlakuCalc,
  pengaturanCetak,
} from "@/lib/surat/cetak";
import { SURAT_TEMPLATES, getSuratTemplate } from "@/lib/surat/templates";
import type { SuratData } from "@/lib/surat/types";
import { SuratDataForm } from "@/components/surat/surat-data-form";
import { FormPendudukLuar } from "@/components/surat/form-penduduk-luar";
import { KodeIsianAlias } from "@/components/surat/kode-isian-alias";
import { PageHeader, StatCard } from "@/components/page-header";
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 { Textarea } from "@/components/ui/textarea";
import { SettingsForm, type SettingField } from "@/components/admin/settings-form";
import { cn, formatDateShort, labelStatusSurat } from "@/lib/utils";

const STATUS_VARIANT: Record<string, "info" | "warning" | "success" | "danger"> = {
  DIAJUKAN: "info",
  DIPROSES: "warning",
  SELESAI: "success",
  DITOLAK: "danger",
};

const YA_TIDAK = [
  { value: "1", label: "Ya" },
  { value: "0", label: "Tidak" },
];

const PILIHAN_FONT_SURAT = [
  "Andale Mono",
  "Arial",
  "Arial Black",
  "Bookman Old Style",
  "Comic Sans MS",
  "Courier New",
  "Georgia",
  "Helvetica",
  "Impact",
  "Tahoma",
  "Times New Roman",
  "Trebuchet MS",
  "Verdana",
].map((nama) => ({ value: nama, label: nama }));

const PILIHAN_PENOMORAN_SURAT = [
  {
    value: "1",
    label:
      "Nomor berurutan untuk masing-masing surat masuk dan keluar; dan untuk semua surat layanan",
  },
  {
    value: "2",
    label:
      "Nomor berurutan untuk masing-masing surat masuk dan keluar; dan untuk setiap surat layanan dengan jenis yang sama",
  },
  { value: "3", label: "Nomor berurutan untuk keseluruhan surat layanan, masuk dan keluar" },
  { value: "4", label: "Nomor berurutan untuk masing-masing klasifikasi surat yang sama" },
];

// Acuan: OpenSID lama -> Layanan Surat > Pengaturan Surat > tombol "Pengaturan"
// (Header, Footer, Alur Surat, Pengaturan TTE, Lainnya).
const SURAT_PENGATURAN: SettingField[] = [
  {
    kunci: "surat.tinggi_header",
    label: "Tinggi Header Surat",
    type: "number",
    defaultValue: "3.3",
    help: "Tinggi kop surat dalam centimeter.",
  },
  {
    kunci: "surat.header",
    label: "Template Header Surat",
    type: "textarea",
    placeholder: "Contoh: <table style=\"width:100%\">…</table>",
    help: "Kosongkan untuk memakai kop bawaan identitas desa.",
  },
  {
    kunci: "surat.tinggi_footer",
    label: "Tinggi Footer Surat",
    type: "number",
    defaultValue: "2",
    help: "Tinggi kaki surat dalam centimeter.",
  },
  {
    kunci: "surat.footer",
    label: "Template Footer Surat",
    type: "textarea",
    help: "Kosongkan jika kaki surat tidak berubah.",
  },
  { kunci: "surat.verifikasi_sekdes", label: "Verifikasi Sekretaris", type: "select", options: YA_TIDAK, defaultValue: "1" },
  { kunci: "surat.verifikasi_kades", label: "Verifikasi Kepala Desa", type: "select", options: YA_TIDAK, defaultValue: "1" },
  { kunci: "surat.tte", label: "Aktifkan Modul TTE", type: "select", options: YA_TIDAK, defaultValue: "0" },
  { kunci: "surat.tte_api", label: "URL API Server TTE", type: "url", placeholder: "https://tte.desa.id/api" },
  { kunci: "surat.tte_username", label: "Username Login TTE", type: "text" },
  { kunci: "surat.tte_password", label: "Password Login TTE", type: "password" },
  { kunci: "surat.visual_tte", label: "Visual TTE", type: "select", options: YA_TIDAK, defaultValue: "0" },
  {
    kunci: "surat.visual_tte_gambar",
    label: "Gambar Visual",
    type: "image",
    help: "Gambar tampilan tanda tangan elektronik (PNG/JPG/WebP).",
  },
  { kunci: "surat.visual_tte_height", label: "Tinggi Gambar Visual", type: "number", defaultValue: "100" },
  { kunci: "surat.visual_tte_weight", label: "Lebar Gambar Visual", type: "number", defaultValue: "100" },
  { kunci: "surat.ssl_tte", label: "SSL TTE", type: "select", options: YA_TIDAK, defaultValue: "0" },
  { kunci: "surat.font", label: "Jenis Font Bawaan", type: "select", options: PILIHAN_FONT_SURAT, defaultValue: "Arial" },
  {
    kunci: "surat.font_custom",
    label: "Upload Font Custom",
    placeholder: "mis. NotoSerif",
    help: "Nama font custom. Berkas font tidak diunggah; cetak memakai font yang tersedia di peramban.",
  },
  {
    kunci: "surat.format_nomor",
    label: "Format Penomoran Surat",
    defaultValue: "[kode_surat]/[nomor_surat, 3]/[kode_desa]/[bulan_romawi]/[tahun]",
    help: "Token: [kode_surat], [nomor_surat, n], [kode_desa], [bulan_romawi], [tahun].",
  },
  {
    kunci: "surat.penomoran",
    label: "Penomoran Surat",
    type: "select",
    options: PILIHAN_PENOMORAN_SURAT,
    defaultValue: "2",
  },
  {
    kunci: "surat.panjang_nomor",
    label: "Panjang Nomor Surat",
    type: "number",
    help: "Kosongkan mengikuti panjang token nomor pada format penomoran.",
  },
  {
    kunci: "surat.data_kosong",
    label: "Kode Isian Data Kosong",
    defaultValue: "-",
    help: "Teks pengganti isian yang belum terisi pada cetak surat.",
  },
  { kunci: "surat.format_tanggal", label: "Format Tanggal Surat", defaultValue: "d F Y", placeholder: "d F Y" },
  { kunci: "surat.margin_kiri", label: "Margin Kiri", type: "number", defaultValue: "1.78", help: "Centimeter." },
  { kunci: "surat.margin_atas", label: "Margin Atas", type: "number", defaultValue: "0.63", help: "Centimeter." },
  { kunci: "surat.margin_kanan", label: "Margin Kanan", type: "number", defaultValue: "1.78", help: "Centimeter." },
  { kunci: "surat.margin_bawah", label: "Margin Bawah", type: "number", defaultValue: "1.37", help: "Centimeter." },
  {
    kunci: "surat.penduduk_berulang",
    label: "Data Pelaku Digunakan Berulang",
    type: "select",
    options: YA_TIDAK,
    defaultValue: "1",
  },
];

type JenisForm = {
  nama: string;
  kode: string;
  urlSurat: string;
  jenis: string;
  mandiri: boolean;
  masaBerlaku: string;
  satuanMasaBerlaku: SatuanMasaBerlaku;
  deskripsi: string;
  syarat: string;
  lampiran: string;
  aktif: boolean;
} & PengaturanCetakSurat;

const emptyJenis: JenisForm = {
  nama: "",
  kode: "",
  urlSurat: "",
  jenis: "3",
  mandiri: false,
  masaBerlaku: "1",
  satuanMasaBerlaku: "M",
  deskripsi: "",
  syarat: "",
  lampiran: "",
  aktif: true,
  ...DEFAULT_PENGATURAN_CETAK,
};

const JENIS_SURAT: Record<number, string> = {
  1: "Surat Keterangan",
  2: "Surat Permohonan",
  3: "Surat Sistem",
  4: "Surat Desa",
};

function labelMasaBerlaku(jenis: SuratJenis) {
  return labelMasaBerlakuCalc(jenis.masaBerlaku, jenis.satuanMasaBerlaku);
}

function formatLampiran(value: string | null) {
  if (!value) return "-";
  return value
    .replace(/\.php/gi, "")
    .split(",")
    .map((item) => item.trim().toUpperCase())
    .filter(Boolean)
    .join(", ");
}

function CetakSwitch({
  label,
  checked,
  onChange,
}: {
  label: string;
  checked: boolean;
  onChange: (value: boolean) => void;
}) {
  return (
    <label className="flex h-9 items-center gap-2 rounded-lg border border-input px-3 text-xs">
      <input
        type="checkbox"
        checked={checked}
        onChange={(event) => onChange(event.target.checked)}
        className="h-4 w-4 rounded border-input accent-emerald-600"
      />
      {label}
    </label>
  );
}

function CetakAngka({
  label,
  value,
  disabled,
  onChange,
}: {
  label: string;
  value: number;
  disabled: boolean;
  onChange: (value: number) => void;
}) {
  return (
    <div className="space-y-1">
      <Label className="text-[11px] text-muted-foreground">{label}</Label>
      <Input
        type="number"
        step={0.1}
        min={0}
        max={10}
        disabled={disabled}
        value={value}
        onChange={(event) => onChange(Number(event.target.value))}
        className="h-9 text-xs disabled:opacity-50"
      />
    </div>
  );
}

export default function SuratPage() {
  const { user } = useSession();
  const isAdmin = user?.role === "ADMIN";
  const onJenisRoute = usePathname().endsWith("/jenis");

  const [tab, setTab] = useState<"permohonan" | "jenis">(
    onJenisRoute ? "jenis" : "permohonan",
  );
  const [jenisSearch, setJenisSearch] = useState("");

  const [page, setPage] = useState(1);
  const [limit, setLimit] = useState(10);
  const [search, setSearch] = useState("");
  const [q, setQ] = useState("");
  const [status, setStatus] = useState("");
  const [selectedPermohonanIds, setSelectedPermohonanIds] = useState<number[]>([]);
  const [bulkPermohonanOpen, setBulkPermohonanOpen] = useState(false);

  const [permohonanOpen, setPermohonanOpen] = useState(false);
  const [permohonanForm, setPermohonanForm] = useState({
    jenisId: "",
    pendudukId: "",
    keperluan: "",
  });
  const [permohonanData, setPermohonanData] = useState<SuratData>({});
  const [saving, setSaving] = useState(false);

  const [processTarget, setProcessTarget] = useState<PermohonanSurat | null>(null);
  const [processForm, setProcessForm] = useState({ status: "DIPROSES", catatan: "" });

  const [deletePermohonan, setDeletePermohonan] = useState<PermohonanSurat | null>(null);
  const [deleteJenis, setDeleteJenis] = useState<SuratJenis | null>(null);
  const [deleting, setDeleting] = useState(false);

  const [jenisOpen, setJenisOpen] = useState(false);
  const [editingJenis, setEditingJenis] = useState<SuratJenis | null>(null);
  const [jenisForm, setJenisForm] = useState<JenisForm>(emptyJenis);
  const [jenisStatus, setJenisStatus] = useState("");
  const [jenisKategori, setJenisKategori] = useState("");
  const [jenisEntri, setJenisEntri] = useState(25);
  const [jenisHalaman, setJenisHalaman] = useState(1);

  const [detailJenis, setDetailJenis] = useState<SuratJenis | null>(null);
  const [selectedJenisIds, setSelectedJenisIds] = useState<number[]>([]);
  const [bulkJenisOpen, setBulkJenisOpen] = useState(false);
  const [bulkDeleting, setBulkDeleting] = useState(false);

  const [imporOpen, setImporOpen] = useState(false);
  const [imporNama, setImporNama] = useState("");
  const [imporItems, setImporItems] = useState<Record<string, unknown>[] | null>(
    null,
  );
  const [imporError, setImporError] = useState("");
  const [imporLoading, setImporLoading] = useState(false);

  const query = new URLSearchParams({ page: String(page), limit: String(limit) });
  if (q) query.set("q", q);
  if (status) query.set("status", status);

  const { data: ringkasan, mutate: mutateRingkasan } = useSWR<RingkasanSurat>(
    "/surat/ringkasan",
    fetcher,
  );
  const { data, isLoading, mutate } = useSWR<Paginated<PermohonanSurat>>(
    tab === "permohonan" ? `/surat?${query.toString()}` : null,
    fetcher,
  );
  const { data: jenisList, isLoading: jenisLoading, mutate: mutateJenis } = useSWR<
    SuratJenis[]
  >(tab === "jenis" ? "/surat/jenis" : null, fetcher);
  const { data: jenisAktif } = useSWR<SuratJenis[]>("/surat/jenis", fetcher);
  const { data: pendudukList } = useSWR<Paginated<Penduduk>>(
    "/penduduk?limit=200",
    fetcher,
  );

  const daftar = data?.data ?? [];
  const teleponWarga = useMemo(() => {
    const peta = new Map<number, string>();
    (pendudukList?.data ?? []).forEach((warga) => {
      if (warga.telepon) peta.set(warga.id, warga.telepon);
    });
    return peta;
  }, [pendudukList]);
  const selectedJenis = (jenisAktif ?? []).find(
    (jenis) => String(jenis.id) === permohonanForm.jenisId,
  );
  const permohonanTemplate = getSuratTemplate(
    selectedJenis?.urlSurat,
    selectedJenis?.nama,
  );
  const jenisTersaring = useMemo(() => {
    const kata = jenisSearch.trim().toLowerCase();
    return (jenisList ?? []).filter((jenis) => {
      if (jenisStatus === "aktif" && !jenis.aktif) return false;
      if (jenisStatus === "nonaktif" && jenis.aktif) return false;
      if (jenisKategori && String(jenis.jenis) !== jenisKategori) return false;
      if (!kata) return true;
      return (
        jenis.nama.toLowerCase().includes(kata) ||
        jenis.kode.toLowerCase().includes(kata) ||
        (jenis.urlSurat ?? "").toLowerCase().includes(kata) ||
        (jenis.lampiran ?? "").toLowerCase().includes(kata)
      );
    });
  }, [jenisList, jenisSearch, jenisStatus, jenisKategori]);

  const jenisTotalHalaman = Math.max(
    1,
    Math.ceil(jenisTersaring.length / jenisEntri),
  );
  const jenisHalamanAktif = Math.min(jenisHalaman, jenisTotalHalaman);
  const jenisTerpak = jenisTersaring.slice(
    (jenisHalamanAktif - 1) * jenisEntri,
    jenisHalamanAktif * jenisEntri,
  );

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

  useEffect(() => {
    setSelectedJenisIds([]);
  }, [jenisSearch, jenisStatus, jenisKategori, jenisEntri]);

  useEffect(() => {
    setJenisHalaman(1);
  }, [jenisSearch, jenisStatus, jenisKategori, jenisEntri]);

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

  const semuaPermohonanDipilih =
    daftar.length > 0 && daftar.every((surat) => selectedPermohonanIds.includes(surat.id));

  const semuaJenisDipilih =
    jenisTerpak.length > 0 &&
    jenisTerpak.every((jenis) => selectedJenisIds.includes(jenis.id));

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

  function toggleSemuaPermohonan() {
    setSelectedPermohonanIds(
      semuaPermohonanDipilih ? [] : daftar.map((surat) => surat.id),
    );
  }

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

  function toggleSemuaJenis() {
    setSelectedJenisIds(
      semuaJenisDipilih
        ? selectedJenisIds.filter(
            (value) => !jenisTerpak.some((jenis) => jenis.id === value),
          )
        : [...new Set([...selectedJenisIds, ...jenisTerpak.map((jenis) => jenis.id)])],
    );
  }

  function openJenisEditor(jenis: SuratJenis) {
    setEditingJenis(jenis);
    setJenisForm({
      nama: jenis.nama,
      kode: jenis.kode,
      urlSurat: jenis.urlSurat ?? "",
      jenis: String(jenis.jenis),
      mandiri: jenis.mandiri,
      masaBerlaku: String(jenis.masaBerlaku),
      satuanMasaBerlaku: jenis.satuanMasaBerlaku,
      deskripsi: jenis.deskripsi ?? "",
      syarat: jenis.syarat ?? "",
      lampiran: jenis.lampiran ?? "",
      aktif: jenis.aktif,
      ...pengaturanCetak(jenis),
    });
    setJenisOpen(true);
  }

  async function toggleFavorit(jenis: SuratJenis) {
    try {
      await apiSend(`/surat/jenis/${jenis.id}`, "PATCH", {
        favorit: !jenis.favorit,
      });
      toast.success(
        jenis.favorit
          ? `${jenis.nama} dikeluarkan dari favorit`
          : `${jenis.nama} ditambahkan ke favorit`,
      );
      await mutateJenis();
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal mengubah favorit",
      );
    }
  }

  async function toggleAktif(jenis: SuratJenis) {
    try {
      await apiSend(`/surat/jenis/${jenis.id}`, "PATCH", { aktif: !jenis.aktif });
      toast.success(
        jenis.aktif ? `${jenis.nama} dinonaktifkan` : `${jenis.nama} diaktifkan`,
      );
      await mutateJenis();
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : "Gagal mengubah status surat",
      );
    }
  }

  async function salinJenis(jenis: SuratJenis) {
    try {
      await apiSend("/surat/jenis", "POST", {
        nama: `${jenis.nama} (Salinan)`,
        kode: jenis.kode,
        jenis: jenis.jenis,
        mandiri: jenis.mandiri,
        masaBerlaku: Math.max(1, jenis.masaBerlaku),
        satuanMasaBerlaku: jenis.satuanMasaBerlaku,
        ...(jenis.deskripsi ? { deskripsi: jenis.deskripsi } : {}),
        ...(jenis.template ? { template: jenis.template } : {}),
        ...(jenis.syarat ? { syarat: jenis.syarat } : {}),
        lampiran: jenis.lampiran ?? "",
        favorit: false,
        aktif: jenis.aktif,
        ...pengaturanCetak(jenis),
      });
      toast.success(`${jenis.nama} disalin`);
      await refreshAll();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyalin surat");
    }
  }

  function eksporJenis() {
    if (!jenisTersaring.length) {
      toast.error("Tidak ada surat untuk diekspor");
      return;
    }
    unduhCsv(
      `daftar-jenis-surat-${new Date().toISOString().slice(0, 10)}.csv`,
      [
        "Nama Surat",
        "Kode / Klasifikasi",
        "Lampiran",
        "Kategori",
        "Masa Berlaku",
        "Layanan Mandiri",
        "Status",
      ],
      jenisTersaring.map((jenis) => [
        jenis.nama,
        jenis.kode,
        formatLampiran(jenis.lampiran),
        JENIS_SURAT[jenis.jenis] ?? String(jenis.jenis),
        labelMasaBerlaku(jenis),
        jenis.mandiri ? "Ya" : "Tidak",
        jenis.aktif ? "Aktif" : "Tidak Aktif",
      ]),
    );
    toast.success(`${jenisTersaring.length} jenis surat diekspor`);
  }

  function berkasJenis(jenis: SuratJenis) {
    return {
      nama: jenis.nama,
      kode: jenis.kode,
      urlSurat: jenis.urlSurat,
      jenis: jenis.jenis,
      mandiri: jenis.mandiri,
      masaBerlaku: jenis.masaBerlaku,
      satuanMasaBerlaku: jenis.satuanMasaBerlaku,
      deskripsi: jenis.deskripsi,
      syarat: jenis.syarat,
      lampiran: jenis.lampiran,
      favorit: jenis.favorit,
      aktif: jenis.aktif,
      ...pengaturanCetak(jenis),
    };
  }

  function eksporJenisJson() {
    const sumber = selectedJenisIds.length
      ? (jenisAktif ?? []).filter((jenis) => selectedJenisIds.includes(jenis.id))
      : jenisTersaring;
    if (!sumber.length) {
      toast.error("Tidak ada surat untuk diekspor");
      return;
    }
    unduhJson(
      `impor-jenis-surat-${new Date().toISOString().slice(0, 10)}.json`,
      { items: sumber.map(berkasJenis) },
    );
    toast.success(`${sumber.length} jenis surat diekspor sebagai berkas impor`);
  }

  function contohJenisSistem() {
    unduhJson("contoh-surat-layanan-sistem.json", {
      items: SURAT_TEMPLATES.map((template) => ({
        nama: template.nama,
        kode: template.kode,
        urlSurat: template.urlSurat,
        jenis: 3,
        mandiri: false,
        masaBerlaku: 1,
        satuanMasaBerlaku: "M",
        deskripsi: template.ringkasan,
        ...DEFAULT_PENGATURAN_CETAK,
      })),
    });
    toast.success(
      `${SURAT_TEMPLATES.length} surat bawaan sistem diunduh sebagai contoh`,
    );
  }

  async function pilihBerkasImpor(file: File | undefined) {
    if (!file) {
      setImporItems(null);
      setImporNama("");
      setImporError("");
      return;
    }
    setImporNama(file.name);
    try {
      const teks = await file.text();
      const data = JSON.parse(teks) as unknown;
      const items = Array.isArray(data)
        ? data
        : Array.isArray((data as { items?: unknown })?.items)
          ? ((data as { items: unknown[] }).items as Record<string, unknown>[])
          : null;
      if (!items?.length) {
        setImporItems(null);
        setImporError(
          "Berkas tidak memuat daftar jenis surat. Gunakan hasil Ekspor atau array objek berisi kolom nama.",
        );
        return;
      }
      setImporItems(items as Record<string, unknown>[]);
      setImporError("");
    } catch {
      setImporItems(null);
      setImporError("Berkas bukan JSON yang valid.");
    }
  }

  async function jalankanImpor() {
    if (!imporItems?.length) {
      setImporError("Pilih berkas JSON berisi daftar jenis surat terlebih dahulu.");
      return;
    }
    setImporLoading(true);
    try {
      const hasil = await apiSend<HasilImporJenis>("/surat/jenis/impor", "POST", {
        items: imporItems,
      });
      toast.success(
        `${hasil.ditambahkan} jenis surat ditambahkan${
          hasil.dilewati ? `, ${hasil.dilewati} dilewati` : ""
        }`,
      );
      setImporOpen(false);
      setImporItems(null);
      setImporNama("");
      setImporError("");
      await mutateJenis();
    } catch (error) {
      setImporError(
        error instanceof ApiError ? error.message : "Gagal mengimpor jenis surat",
      );
    } finally {
      setImporLoading(false);
    }
  }

  async function hapusPermohonanTerpilih() {
    setBulkDeleting(true);
    try {
      const results = await Promise.allSettled(
        selectedPermohonanIds.map((id) => apiSend(`/surat/${id}`, "DELETE")),
      );
      const sukses = results.filter((result) => result.status === "fulfilled").length;
      const gagal = results.length - sukses;
      if (sukses) toast.success(`${sukses} permohonan surat dihapus`);
      if (gagal) {
        const alasan = results.find(
          (result): result is PromiseRejectedResult => result.status === "rejected",
        )?.reason;
        toast.error(
          `${gagal} permohonan gagal dihapus${
            alasan instanceof ApiError ? `: ${alasan.message}` : ""
          }`,
        );
      }
      setBulkPermohonanOpen(false);
      setSelectedPermohonanIds([]);
      await refreshAll();
    } finally {
      setBulkDeleting(false);
    }
  }

  async function hapusJenisTerpilih() {
    setBulkDeleting(true);
    try {
      const results = await Promise.allSettled(
        selectedJenisIds.map((id) => apiSend(`/surat/jenis/${id}`, "DELETE")),
      );
      const sukses = results.filter((result) => result.status === "fulfilled").length;
      const gagal = results.length - sukses;
      if (sukses) toast.success(`${sukses} jenis surat dihapus`);
      if (gagal) {
        const alasan = results.find(
          (result): result is PromiseRejectedResult => result.status === "rejected",
        )?.reason;
        toast.error(
          `${gagal} jenis surat gagal dihapus${
            alasan instanceof ApiError ? `: ${alasan.message}` : ""
          }`,
        );
      }
      setBulkJenisOpen(false);
      setSelectedJenisIds([]);
      await mutateJenis();
    } finally {
      setBulkDeleting(false);
    }
  }

  async function refreshAll() {
    await mutate();
    await mutateRingkasan();
    await mutateJenis();
  }

  async function createPermohonan(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSaving(true);
    try {
      const isian = Object.fromEntries(
        Object.entries(permohonanData).filter(([, value]) => value.trim()),
      );
      await apiSend("/surat", "POST", {
        jenisId: Number(permohonanForm.jenisId),
        pendudukId: Number(permohonanForm.pendudukId),
        keperluan: permohonanForm.keperluan,
        ...(permohonanTemplate.fields.length ? { dataIsian: isian } : {}),
      });
      toast.success("Permohonan surat dibuat");
      setPermohonanOpen(false);
      setPermohonanForm({ jenisId: "", pendudukId: "", keperluan: "" });
      setPermohonanData({});
      await refreshAll();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal membuat permohonan");
    } finally {
      setSaving(false);
    }
  }

  async function updateStatus(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!processTarget) return;
    setSaving(true);
    try {
      await apiSend(`/surat/${processTarget.id}/status`, "PATCH", {
        status: processForm.status,
        ...(processForm.catatan ? { catatan: processForm.catatan } : {}),
      });
      toast.success("Status permohonan diperbarui");
      setProcessTarget(null);
      await refreshAll();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal memperbarui status");
    } finally {
      setSaving(false);
    }
  }

  async function saveJenis(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSaving(true);
    try {
      const payload = {
        nama: jenisForm.nama,
        kode: jenisForm.kode,
        ...(jenisForm.urlSurat ? { urlSurat: jenisForm.urlSurat } : {}),
        jenis: Number(jenisForm.jenis),
        mandiri: jenisForm.mandiri,
        masaBerlaku: Number(jenisForm.masaBerlaku) || 1,
        satuanMasaBerlaku: jenisForm.satuanMasaBerlaku,
        ...(jenisForm.deskripsi ? { deskripsi: jenisForm.deskripsi } : {}),
        ...(jenisForm.syarat ? { syarat: jenisForm.syarat } : {}),
        lampiran: jenisForm.lampiran,
        aktif: jenisForm.aktif,
        orientasi: jenisForm.orientasi,
        ukuran: jenisForm.ukuran,
        marginGlobal: jenisForm.marginGlobal,
        marginKiri: Number(jenisForm.marginKiri),
        marginAtas: Number(jenisForm.marginAtas),
        marginKanan: Number(jenisForm.marginKanan),
        marginBawah: Number(jenisForm.marginBawah),
        formatNomorGlobal: jenisForm.formatNomorGlobal,
        ...(jenisForm.formatNomor?.trim()
          ? { formatNomor: jenisForm.formatNomor.trim() }
          : {}),
        header: jenisForm.header,
        footer: jenisForm.footer,
        logoGaruda: jenisForm.logoGaruda,
        qrCode: jenisForm.qrCode,
        qrCodeTte: jenisForm.qrCodeTte,
        sumberPendudukBerulang: jenisForm.sumberPendudukBerulang,
      };
      if (editingJenis) {
        await apiSend(`/surat/jenis/${editingJenis.id}`, "PATCH", payload);
        toast.success("Jenis surat diperbarui");
      } else {
        await apiSend("/surat/jenis", "POST", payload);
        toast.success("Jenis surat ditambahkan");
      }
      setJenisOpen(false);
      setEditingJenis(null);
      setJenisForm(emptyJenis);
      await refreshAll();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyimpan jenis surat");
    } finally {
      setSaving(false);
    }
  }

  async function removePermohonan() {
    if (!deletePermohonan) return;
    setDeleting(true);
    try {
      await apiSend(`/surat/${deletePermohonan.id}`, "DELETE");
      toast.success("Permohonan dihapus");
      setDeletePermohonan(null);
      await refreshAll();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menghapus");
    } finally {
      setDeleting(false);
    }
  }

  async function removeJenis() {
    if (!deleteJenis) return;
    setDeleting(true);
    try {
      await apiSend(`/surat/jenis/${deleteJenis.id}`, "DELETE");
      toast.success("Jenis surat dihapus");
      setDeleteJenis(null);
      await refreshAll();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menghapus");
    } finally {
      setDeleting(false);
    }
  }

  return (
    <div className="animate-fade-in space-y-6">
      <PageHeader
        title={tab === "jenis" ? "Pengaturan Surat" : "Layanan Surat"}
        description={
          tab === "jenis"
            ? "Daftar format surat desa: kode klasifikasi, lampiran, favorit, dan pengaturan template."
            : "Kelola permohonan surat warga dan jenis layanan surat keterangan desa."
        }
        action={
          tab === "permohonan" ? (
            <Button onClick={() => setPermohonanOpen(true)}>
              <FilePlus2 className="h-4 w-4" />
              Permohonan Baru
            </Button>
          ) : isAdmin ? (
            <Button
              onClick={() => {
                setEditingJenis(null);
                setJenisForm(emptyJenis);
                setJenisOpen(true);
              }}
            >
              <Plus className="h-4 w-4" />
              Tambah Jenis Surat
            </Button>
          ) : undefined
        }
      />

      <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
        <StatCard
          title="Diajukan"
          value={ringkasan?.DIAJUKAN ?? 0}
          hint="Menunggu diproses"
          icon={FileText}
          tone="sky"
        />
        <StatCard
          title="Diproses"
          value={ringkasan?.DIPROSES ?? 0}
          hint="Sedang dikerjakan"
          icon={Clock}
          tone="amber"
        />
        <StatCard
          title="Selesai"
          value={ringkasan?.SELESAI ?? 0}
          hint="Surat telah diterbitkan"
          icon={CheckCircle2}
          tone="emerald"
        />
        <StatCard
          title="Ditolak"
          value={ringkasan?.DITOLAK ?? 0}
          hint={`Total ${ringkasan?.total ?? 0} permohonan`}
          icon={XCircle}
          tone="violet"
        />
      </div>

      <div className="inline-flex rounded-xl border border-border bg-card p-1">
        {[
          { key: "permohonan" as const, label: "Permohonan", icon: FileText },
          { key: "jenis" as const, label: "Pengaturan Surat", icon: Settings2 },
        ].map((item) => (
          <button
            key={item.key}
            type="button"
            onClick={() => setTab(item.key)}
            className={cn(
              "inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors",
              tab === item.key
                ? "bg-primary text-primary-foreground shadow-sm"
                : "text-muted-foreground hover:bg-muted",
            )}
          >
            <item.icon className="h-4 w-4" />
            {item.label}
          </button>
        ))}
      </div>

      {tab === "permohonan" ? (
        <Card>
          <CardContent className="p-0">
            <div className="flex flex-col gap-3 border-b p-4 lg:flex-row lg:items-center lg:justify-between">
              <div className="flex flex-wrap items-center gap-2">
                <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 surat, pemohon, jenis…"
                    className="pl-9"
                  />
                </form>
                <Select
                  value={status}
                  onChange={(event) => setStatus(event.target.value)}
                  aria-label="Pilih Status"
                  className="w-full sm:w-44"
                >
                  <option value="">Pilih Status</option>
                  <option value="DIAJUKAN">Diajukan</option>
                  <option value="DIPROSES">Diproses</option>
                  <option value="SELESAI">Selesai</option>
                  <option value="DITOLAK">Ditolak</option>
                </Select>
                <Select
                  value={String(limit)}
                  onChange={(event) => setLimit(Number(event.target.value))}
                  aria-label="Tampilkan entri"
                  className="w-28"
                >
                  <option value="10">10</option>
                  <option value="25">25</option>
                  <option value="50">50</option>
                  <option value="100">100</option>
                </Select>
                {(q || status || limit !== 10) && (
                  <Button
                    type="button"
                    variant="ghost"
                    onClick={() => {
                      setSearch("");
                      setQ("");
                      setStatus("");
                      setLimit(10);
                    }}
                  >
                    Bersihkan
                  </Button>
                )}
              </div>
              {isAdmin && (
                <Button
                  variant="outline"
                  disabled={!selectedPermohonanIds.length}
                  className={cn(
                    "text-destructive hover:text-destructive",
                    !selectedPermohonanIds.length &&
                      "border-input text-muted-foreground hover:text-muted-foreground",
                  )}
                  onClick={() => setBulkPermohonanOpen(true)}
                >
                  <Trash2 className="h-4 w-4" />
                  Hapus{selectedPermohonanIds.length ? ` (${selectedPermohonanIds.length})` : ""}
                </Button>
              )}
            </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>
                    {isAdmin && (
                      <TableHead className="w-10">
                        <input
                          type="checkbox"
                          checked={semuaPermohonanDipilih}
                          onChange={toggleSemuaPermohonan}
                          aria-label="Pilih semua permohonan"
                          className="h-4 w-4 accent-emerald-600"
                        />
                      </TableHead>
                    )}
                    <TableHead className="w-14">No</TableHead>
                    <TableHead className="w-44">Aksi</TableHead>
                    <TableHead className="w-24">No Antrean</TableHead>
                    <TableHead>Nomor Surat</TableHead>
                    <TableHead>NIK</TableHead>
                    <TableHead>Nama Penduduk</TableHead>
                    <TableHead className="hidden lg:table-cell">No HP Aktif</TableHead>
                    <TableHead>Jenis Surat</TableHead>
                    <TableHead className="hidden xl:table-cell">Keterangan</TableHead>
                    <TableHead>Tanggal Kirim</TableHead>
                    <TableHead>Status</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {daftar.map((surat, index) => (
                    <TableRow
                      key={surat.id}
                      className={cn(
                        selectedPermohonanIds.includes(surat.id) && "bg-primary/5",
                      )}
                    >
                      {isAdmin && (
                        <TableCell>
                          <input
                            type="checkbox"
                            checked={selectedPermohonanIds.includes(surat.id)}
                            onChange={() => togglePermohonanDipilih(surat.id)}
                            aria-label={`Pilih permohonan ${surat.nomor}`}
                            className="h-4 w-4 accent-emerald-600"
                          />
                        </TableCell>
                      )}
                      <TableCell className="text-muted-foreground">
                        {(page - 1) * limit + index + 1}
                      </TableCell>
                      <TableCell>
                        <div className="flex items-center gap-1">
                          <Button variant="outline" size="sm" asChild>
                            <Link href={`/admin/surat/${surat.id}/cetak`}>
                              <Printer className="h-4 w-4" />
                              Cetak
                            </Link>
                          </Button>
                          <Button
                            variant="outline"
                            size="sm"
                            onClick={() => {
                              setProcessTarget(surat);
                              setProcessForm({
                                status:
                                  surat.status === "DIAJUKAN"
                                    ? "DIPROSES"
                                    : surat.status,
                                catatan: surat.catatan ?? "",
                              });
                            }}
                          >
                            Proses
                          </Button>
                          {isAdmin && (
                            <Button
                              variant="ghost"
                              size="icon"
                              className="h-8 w-8 text-destructive hover:text-destructive"
                              onClick={() => setDeletePermohonan(surat)}
                              aria-label="Hapus permohonan"
                            >
                              <Trash2 className="h-4 w-4" />
                            </Button>
                          )}
                        </div>
                      </TableCell>
                      <TableCell className="font-mono text-xs">
                        {surat.noAntrean ?? "-"}
                      </TableCell>
                      <TableCell className="font-mono text-xs font-semibold">
                        {surat.nomor}
                      </TableCell>
                      <TableCell className="font-mono text-xs">
                        {surat.penduduk?.nik ?? "-"}
                      </TableCell>
                      <TableCell className="font-medium">
                        {surat.penduduk?.nama ?? "-"}
                      </TableCell>
                      <TableCell className="hidden whitespace-nowrap lg:table-cell">
                        {teleponWarga.get(surat.pendudukId) ?? "-"}
                      </TableCell>
                      <TableCell>
                        <div>{surat.jenis?.nama ?? "-"}</div>
                        <div className="text-xs text-muted-foreground">
                          {surat.jenis?.kode ?? "-"}
                        </div>
                      </TableCell>
                      <TableCell className="hidden max-w-[240px] truncate text-sm text-muted-foreground xl:table-cell">
                        {surat.keperluan}
                      </TableCell>
                      <TableCell className="whitespace-nowrap">
                        {formatDateShort(surat.tanggal)}
                      </TableCell>
                      <TableCell>
                        <Badge variant={STATUS_VARIANT[surat.status] ?? "secondary"}>
                          {labelStatusSurat(surat.status)}
                        </Badge>
                        {surat.diprosesOleh && (
                          <div className="mt-1 text-[10px] text-muted-foreground">
                            oleh {surat.diprosesOleh}
                          </div>
                        )}
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            ) : (
              <div className="py-16 text-center">
                <p className="font-semibold">Belum ada permohonan</p>
                <p className="mt-1 text-sm text-muted-foreground">
                  Buat permohonan 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>
      ) : (
        <Card>
          <CardContent className="p-0">
            <div className="flex flex-col gap-3 border-b p-4 lg:flex-row lg:items-center lg:justify-between">
              <div className="flex flex-wrap items-center gap-2">
                <Select
                  value={jenisStatus}
                  onChange={(event) => setJenisStatus(event.target.value)}
                  aria-label="Pilih Status"
                  className="w-full sm:w-40"
                >
                  <option value="">Pilih Status</option>
                  <option value="aktif">Aktif</option>
                  <option value="nonaktif">Tidak Aktif</option>
                </Select>
                <Select
                  value={jenisKategori}
                  onChange={(event) => setJenisKategori(event.target.value)}
                  aria-label="Pilih Surat"
                  className="w-full sm:w-48"
                >
                  <option value="">Pilih Surat</option>
                  {Object.entries(JENIS_SURAT).map(([value, label]) => (
                    <option key={value} value={value}>
                      {label}
                    </option>
                  ))}
                </Select>
                <Input
                  value={jenisSearch}
                  onChange={(event) => setJenisSearch(event.target.value)}
                  placeholder="Cari nama surat, kode, atau lampiran…"
                  className="w-full lg:max-w-xs"
                />
                {(jenisStatus || jenisKategori || jenisSearch) && (
                  <Button
                    type="button"
                    variant="ghost"
                    onClick={() => {
                      setJenisStatus("");
                      setJenisKategori("");
                      setJenisSearch("");
                    }}
                  >
                    Bersihkan
                  </Button>
                )}
              </div>
              <div className="flex flex-wrap items-center gap-2">
                {isAdmin && (
                  <Button
                    variant="outline"
                    disabled={!selectedJenisIds.length}
                    className={cn(
                      "text-destructive hover:text-destructive",
                      !selectedJenisIds.length &&
                        "border-input text-muted-foreground hover:text-muted-foreground",
                    )}
                    onClick={() => setBulkJenisOpen(true)}
                  >
                    <Trash2 className="h-4 w-4" />
                    Hapus{selectedJenisIds.length ? ` (${selectedJenisIds.length})` : ""}
                  </Button>
                )}
                <Button variant="outline" onClick={eksporJenisJson}>
                  <Download className="h-4 w-4" />
                  Ekspor
                </Button>
                <Button variant="ghost" onClick={eksporJenis}>
                  Ekspor CSV
                </Button>
                {isAdmin && (
                  <Button variant="outline" onClick={() => setImporOpen(true)}>
                    <Upload className="h-4 w-4" />
                    Impor
                  </Button>
                )}
                <span className="text-xs text-muted-foreground">
                  {jenisTersaring.length} dari {jenisList?.length ?? 0} surat ·{" "}
                  {(jenisList ?? []).filter((jenis) => jenis.favorit).length} favorit ·{" "}
                  {(jenisList ?? []).filter((jenis) => jenis.mandiri).length} mandiri
                </span>
              </div>
            </div>

            {jenisLoading ? (
              <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>
            ) : jenisTersaring.length ? (
              <Table>
                <TableHeader>
                  <TableRow>
                    {isAdmin && (
                      <TableHead className="w-10">
                        <input
                          type="checkbox"
                          checked={semuaJenisDipilih}
                          onChange={toggleSemuaJenis}
                          aria-label="Pilih semua surat"
                          className="h-4 w-4 accent-emerald-600"
                        />
                      </TableHead>
                    )}
                    <TableHead className="w-14">No</TableHead>
                    <TableHead className="w-44">Aksi</TableHead>
                    <TableHead>Nama Surat</TableHead>
                    <TableHead className="w-40">Kode / Klasifikasi</TableHead>
                    <TableHead className="w-64">Lampiran</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {jenisTerpak.map((jenis, index) => (
                    <TableRow
                      key={jenis.id}
                      className={cn(selectedJenisIds.includes(jenis.id) && "bg-primary/5")}
                    >
                      {isAdmin && (
                        <TableCell>
                          <input
                            type="checkbox"
                            checked={selectedJenisIds.includes(jenis.id)}
                            onChange={() => toggleJenisDipilih(jenis.id)}
                            aria-label={`Pilih ${jenis.nama}`}
                            className="h-4 w-4 accent-emerald-600"
                          />
                        </TableCell>
                      )}
                      <TableCell className="text-muted-foreground">
                        {(jenisHalamanAktif - 1) * jenisEntri + index + 1}
                      </TableCell>
                      <TableCell>
                        <div className="flex items-center gap-1">
                          <Button
                            variant="outline"
                            size="icon"
                            className="h-8 w-8 border-sky-200 bg-sky-50 text-sky-700 hover:bg-sky-100"
                            onClick={() => setDetailJenis(jenis)}
                            title="Lihat Data"
                            aria-label={`Lihat ${jenis.nama}`}
                          >
                            <Eye className="h-4 w-4" />
                          </Button>
                          {isAdmin && (
                            <Button
                              variant="outline"
                              size="icon"
                              className="h-8 w-8 border-indigo-200 bg-indigo-50 text-indigo-700 hover:bg-indigo-100"
                              onClick={() => salinJenis(jenis)}
                              title="Salin"
                              aria-label={`Salin ${jenis.nama}`}
                            >
                              <Copy className="h-4 w-4" />
                            </Button>
                          )}
                          {isAdmin && (
                            <Button
                              variant="outline"
                              size="icon"
                              className={cn(
                                "h-8 w-8",
                                jenis.aktif
                                  ? "border-rose-200 bg-rose-50 text-rose-700 hover:bg-rose-100"
                                  : "border-emerald-200 bg-emerald-50 text-emerald-700 hover:bg-emerald-100",
                              )}
                              onClick={() => toggleAktif(jenis)}
                              title={jenis.aktif ? "Nonaktifkan" : "Aktifkan"}
                              aria-label={`${
                                jenis.aktif ? "Nonaktifkan" : "Aktifkan"
                              } ${jenis.nama}`}
                            >
                              {jenis.aktif ? (
                                <Ban className="h-4 w-4" />
                              ) : (
                                <CheckCircle2 className="h-4 w-4" />
                              )}
                            </Button>
                          )}
                          {isAdmin && (
                            <Button
                              variant="outline"
                              size="icon"
                              className="h-8 w-8 border-emerald-200 bg-emerald-50 text-emerald-700 hover:bg-emerald-100"
                              onClick={() => openJenisEditor(jenis)}
                              title="Pengaturan"
                              aria-label={`Pengaturan ${jenis.nama}`}
                            >
                              <Settings2 className="h-4 w-4" />
                            </Button>
                          )}
                          <Button
                            variant="outline"
                            size="icon"
                            className="h-8 w-8 border-slate-200 bg-slate-50 text-slate-700 hover:bg-slate-100"
                            asChild
                          >
                            <Link
                              href={`/admin/cetak-surat/${jenis.id}`}
                              title="Cetak surat"
                              aria-label={`Cetak ${jenis.nama}`}
                            >
                              <Printer className="h-4 w-4" />
                            </Link>
                          </Button>
                          {isAdmin && (
                            <Button
                              variant="outline"
                              size="icon"
                              className={cn(
                                "h-8 w-8",
                                jenis.favorit
                                  ? "border-amber-300 bg-amber-100 text-amber-700 hover:bg-amber-200"
                                  : "border-violet-200 bg-violet-50 text-violet-700 hover:bg-violet-100",
                              )}
                              onClick={() => toggleFavorit(jenis)}
                              title={
                                jenis.favorit
                                  ? "Keluarkan dari Daftar Favorit"
                                  : "Tambahkan ke Daftar Favorit"
                              }
                              aria-label={
                                jenis.favorit
                                  ? `Keluarkan ${jenis.nama} dari favorit`
                                  : `Favoritkan ${jenis.nama}`
                              }
                            >
                              <Star
                                className={cn("h-4 w-4", jenis.favorit && "fill-current")}
                              />
                            </Button>
                          )}
                        </div>
                      </TableCell>
                      <TableCell>
                        <div className="flex flex-wrap items-center gap-2">
                          <span className="font-medium">{jenis.nama}</span>
                          {jenis.favorit && (
                            <Badge variant="warning" className="gap-1">
                              <Star className="h-3 w-3 fill-current" />
                              Favorit
                            </Badge>
                          )}
                          {jenis.mandiri && <Badge variant="info">Mandiri</Badge>}
                          {!jenis.aktif && <Badge variant="secondary">Nonaktif</Badge>}
                        </div>
                        {jenis.urlSurat && (
                          <div className="mt-0.5 font-mono text-[11px] text-muted-foreground">
                            {jenis.urlSurat}
                          </div>
                        )}
                      </TableCell>
                      <TableCell>
                        <span className="rounded-full bg-muted px-2 py-0.5 font-mono text-[11px] text-muted-foreground">
                          {jenis.kode}
                        </span>
                      </TableCell>
                      <TableCell>
                        <span
                          className={cn(
                            "font-mono text-xs",
                            jenis.lampiran ? "text-foreground" : "text-muted-foreground",
                          )}
                        >
                          {formatLampiran(jenis.lampiran)}
                        </span>
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            ) : (
              <div className="py-16 text-center">
                <p className="font-semibold">Belum ada jenis surat</p>
                <p className="mt-1 text-sm text-muted-foreground">
                  Tambahkan jenis layanan surat yang tersedia di kantor desa.
                </p>
              </div>
            )}

            {jenisTersaring.length > 0 && (
              <div className="flex flex-col gap-3 border-t px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
                <p className="text-xs text-muted-foreground">
                  Menampilkan {(jenisHalamanAktif - 1) * jenisEntri + 1} sampai{" "}
                  {Math.min(jenisTersaring.length, jenisHalamanAktif * jenisEntri)} dari{" "}
                  {jenisTersaring.length} entri
                </p>
                <div className="flex flex-wrap items-center gap-2">
                  <span className="text-xs text-muted-foreground">Tampilkan</span>
                  <Select
                    value={String(jenisEntri)}
                    onChange={(event) => setJenisEntri(Number(event.target.value))}
                    aria-label="Tampilkan entri"
                    className="h-9 w-20"
                  >
                    <option value="10">10</option>
                    <option value="25">25</option>
                    <option value="50">50</option>
                    <option value="100">100</option>
                  </Select>
                  <span className="text-xs text-muted-foreground">entri</span>
                  <Button
                    variant="outline"
                    size="sm"
                    disabled={jenisHalamanAktif <= 1}
                    onClick={() => setJenisHalaman(jenisHalamanAktif - 1)}
                  >
                    <ChevronLeft className="h-4 w-4" />
                    Sebelumnya
                  </Button>
                  {Array.from({ length: jenisTotalHalaman }, (_, index) => index + 1)
                    .filter(
                      (nomor) =>
                        jenisTotalHalaman <= 7 ||
                        nomor === 1 ||
                        nomor === jenisTotalHalaman ||
                        Math.abs(nomor - jenisHalamanAktif) <= 2,
                    )
                    .map((nomor) => (
                      <Button
                        key={nomor}
                        size="sm"
                        variant={nomor === jenisHalamanAktif ? "default" : "outline"}
                        className="w-9"
                        onClick={() => setJenisHalaman(nomor)}
                      >
                        {nomor}
                      </Button>
                    ))}
                  <Button
                    variant="outline"
                    size="sm"
                    disabled={jenisHalamanAktif >= jenisTotalHalaman}
                    onClick={() => setJenisHalaman(jenisHalamanAktif + 1)}
                  >
                    Selanjutnya
                    <ChevronRight className="h-4 w-4" />
                  </Button>
                </div>
              </div>
            )}
          </CardContent>
        </Card>
      )}

      {tab === "jenis" && (
        <>
          <SettingsForm
            grup="surat"
            title="Pengaturan Surat"
            hideHeader
            cardTitle="Pengaturan Surat Global"
            submitLabel="Simpan Pengaturan Surat"
            fields={SURAT_PENGATURAN}
          />
          <FormPendudukLuar />
          <KodeIsianAlias />
        </>
      )}

      <Dialog open={permohonanOpen} onOpenChange={setPermohonanOpen}>
        <DialogContent className="max-h-[88vh] max-w-3xl overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Permohonan Surat Baru</DialogTitle>
            <DialogDescription>
              Nomor surat dibuat otomatis berdasarkan kode jenis surat dan tahun berjalan.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={createPermohonan} className="space-y-4">
            <div className="grid gap-4 sm:grid-cols-2">
              <div className="space-y-1.5">
                <Label>
                  Pemohon <span className="text-destructive">*</span>
                </Label>
                <Select
                  required
                  value={permohonanForm.pendudukId}
                  onChange={(event) =>
                    setPermohonanForm((current) => ({
                      ...current,
                      pendudukId: event.target.value,
                    }))
                  }
                >
                  <option value="">Pilih penduduk</option>
                  {(pendudukList?.data ?? []).map((warga) => (
                    <option key={warga.id} value={warga.id}>
                      {warga.nama} · {warga.nik}
                    </option>
                  ))}
                </Select>
              </div>

              <div className="space-y-1.5">
                <Label>
                  Jenis surat <span className="text-destructive">*</span>
                </Label>
                <Select
                  required
                  value={permohonanForm.jenisId}
                  onChange={(event) => {
                    setPermohonanData({});
                    setPermohonanForm((current) => ({
                      ...current,
                      jenisId: event.target.value,
                    }));
                  }}
                >
                  <option value="">Pilih jenis surat</option>
                  {(jenisAktif ?? [])
                    .filter((jenis) => jenis.aktif)
                    .map((jenis) => (
                      <option key={jenis.id} value={jenis.id}>
                        {jenis.nama} ({jenis.kode})
                      </option>
                    ))}
                </Select>
              </div>
            </div>

            <div className="space-y-1.5">
              <Label>
                Keperluan <span className="text-destructive">*</span>
              </Label>
              <Textarea
                required
                rows={2}
                value={permohonanForm.keperluan}
                onChange={(event) =>
                  setPermohonanForm((current) => ({
                    ...current,
                    keperluan: event.target.value,
                  }))
                }
                placeholder="Contoh: persyaratan pendaftaran sekolah anak"
              />
            </div>

            {selectedJenis && (
              <div className="rounded-xl border border-border bg-muted/30 p-4">
                <SuratDataForm
                  template={permohonanTemplate}
                  value={permohonanData}
                  onChange={setPermohonanData}
                  idPrefix="baru"
                />
              </div>
            )}

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

      <Dialog
        open={!!processTarget}
        onOpenChange={(open) => !open && setProcessTarget(null)}
      >
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>Proses Permohonan</DialogTitle>
            <DialogDescription>
              {processTarget?.nomor} · {processTarget?.penduduk?.nama} ·{" "}
              {processTarget?.jenis?.nama}
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={updateStatus} className="space-y-4">
            <div className="rounded-lg bg-muted/60 p-3 text-sm">
              <div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                Keperluan
              </div>
              <p className="mt-1">{processTarget?.keperluan}</p>
            </div>

            <div className="space-y-1.5">
              <Label>Status</Label>
              <Select
                value={processForm.status}
                onChange={(event) =>
                  setProcessForm((current) => ({ ...current, status: event.target.value }))
                }
              >
                <option value="DIAJUKAN">Diajukan</option>
                <option value="DIPROSES">Diproses</option>
                <option value="SELESAI">Selesai</option>
                <option value="DITOLAK">Ditolak</option>
              </Select>
            </div>

            <div className="space-y-1.5">
              <Label>Catatan</Label>
              <Textarea
                rows={3}
                value={processForm.catatan}
                onChange={(event) =>
                  setProcessForm((current) => ({
                    ...current,
                    catatan: event.target.value,
                  }))
                }
                placeholder="Catatan internal atau alasan penolakan"
              />
            </div>

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

      <Dialog open={jenisOpen} onOpenChange={setJenisOpen}>
        <DialogContent className="max-w-xl">
          <DialogHeader>
            <DialogTitle>
              {editingJenis ? "Ubah Jenis Surat" : "Tambah Jenis Surat"}
            </DialogTitle>
            <DialogDescription>
              Kode surat dipakai sebagai awalan nomor surat otomatis.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={saveJenis} className="space-y-4">
            <div className="grid gap-4 sm:grid-cols-[1.6fr_1fr]">
              <div className="space-y-1.5">
                <Label>
                  Nama Layanan <span className="text-destructive">*</span>
                </Label>
                <Input
                  required
                  value={jenisForm.nama}
                  onChange={(event) =>
                    setJenisForm((current) => ({ ...current, nama: event.target.value }))
                  }
                  placeholder="Surat Keterangan Domisili"
                />
              </div>
              <div className="space-y-1.5">
                <Label>
                  Kode/Klasifikasi Surat <span className="text-destructive">*</span>
                </Label>
                <Input
                  required
                  maxLength={20}
                  value={jenisForm.kode}
                  onChange={(event) =>
                    setJenisForm((current) => ({
                      ...current,
                      kode: event.target.value,
                    }))
                  }
                  placeholder="SKD"
                  className="uppercase"
                />
              </div>
            </div>

            <div className="space-y-1.5">
              <Label>URL surat</Label>
              <Input
                value={jenisForm.urlSurat}
                onChange={(event) =>
                  setJenisForm((current) => ({
                    ...current,
                    urlSurat: event.target.value,
                  }))
                }
                placeholder="sistem-surat-keterangan-domisili"
                className="font-mono text-xs"
              />
            </div>

            <div className="space-y-1.5">
              <Label>Lampiran</Label>
              <Input
                value={jenisForm.lampiran}
                onChange={(event) =>
                  setJenisForm((current) => ({
                    ...current,
                    lampiran: event.target.value,
                  }))
                }
                placeholder="F-1.01, F-1.02"
                className="font-mono text-xs uppercase"
                maxLength={200}
              />
              <p className="text-xs text-muted-foreground">
                Kode formulir lampiran dipisahkan koma, kosongkan bila tidak ada.
              </p>
            </div>

            <div className="grid gap-4 sm:grid-cols-3">
              <div className="space-y-1.5">
                <Label>Kategori</Label>
                <Select
                  value={jenisForm.jenis}
                  onChange={(event) =>
                    setJenisForm((current) => ({ ...current, jenis: event.target.value }))
                  }
                >
                  <option value="1">Surat Keterangan</option>
                  <option value="2">Surat Permohonan</option>
                  <option value="3">Surat Sistem</option>
                  <option value="4">Surat Desa</option>
                </Select>
              </div>
              <div className="space-y-1.5">
                <Label>Masa Berlaku Default</Label>
                <div className="flex gap-2">
                  <Input
                    type="number"
                    min={1}
                    value={jenisForm.masaBerlaku}
                    onChange={(event) =>
                      setJenisForm((current) => ({
                        ...current,
                        masaBerlaku: event.target.value,
                      }))
                    }
                  />
                  <Select
                    value={jenisForm.satuanMasaBerlaku}
                    onChange={(event) =>
                      setJenisForm((current) => ({
                        ...current,
                        satuanMasaBerlaku: event.target.value as SatuanMasaBerlaku,
                      }))
                    }
                    aria-label="Satuan masa berlaku"
                  >
                    {SATUAN_MASA_BERLAKU.map((satuan) => (
                      <option key={satuan} value={satuan}>
                        {{ d: "Hari", w: "Minggu", M: "Bulan", y: "Tahun" }[satuan]}
                      </option>
                    ))}
                  </Select>
                </div>
              </div>
              <div className="space-y-1.5">
                <Label>Sediakan di Layanan Mandiri</Label>
                <label className="flex h-9 items-center gap-2 rounded-lg border border-input px-3 text-sm">
                  <input
                    type="checkbox"
                    checked={jenisForm.mandiri}
                    onChange={(event) =>
                      setJenisForm((current) => ({
                        ...current,
                        mandiri: event.target.checked,
                      }))
                    }
                    className="h-4 w-4 rounded border-input accent-emerald-600"
                  />
                  Dapat diajukan warga
                </label>
              </div>
            </div>

            <div className="space-y-1.5">
              <Label>Deskripsi</Label>
              <Textarea
                rows={2}
                value={jenisForm.deskripsi}
                onChange={(event) =>
                  setJenisForm((current) => ({
                    ...current,
                    deskripsi: event.target.value,
                  }))
                }
              />
            </div>

            <div className="space-y-1.5">
              <Label>Syarat Surat</Label>
              <Textarea
                rows={3}
                value={jenisForm.syarat}
                onChange={(event) =>
                  setJenisForm((current) => ({ ...current, syarat: event.target.value }))
                }
                placeholder={"Satu persyaratan per baris, contoh:\nFotokopi KTP\nFotokopi KK"}
              />
            </div>

            <fieldset className="space-y-3 rounded-xl border border-border bg-muted/30 p-4">
              <legend className="px-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                Pengaturan Cetak
              </legend>
              <div className="grid gap-3 sm:grid-cols-2">
                <div className="space-y-1.5">
                  <Label>Orientasi Kertas</Label>
                  <Select
                    value={jenisForm.orientasi}
                    onChange={(event) =>
                      setJenisForm((current) => ({
                        ...current,
                        orientasi: event.target.value as OrientasiSurat,
                      }))
                    }
                  >
                    {ORIENTASI_SURAT.map((nilai) => (
                      <option key={nilai} value={nilai}>
                        {nilai}
                      </option>
                    ))}
                  </Select>
                </div>
                <div className="space-y-1.5">
                  <Label>Ukuran Kertas</Label>
                  <Select
                    value={jenisForm.ukuran}
                    onChange={(event) =>
                      setJenisForm((current) => ({
                        ...current,
                        ukuran: event.target.value as UkuranKertas,
                      }))
                    }
                  >
                    {UKURAN_KERTAS.map((nilai) => (
                      <option key={nilai} value={nilai}>
                        {nilai}
                      </option>
                    ))}
                  </Select>
                </div>
              </div>

              <div className="space-y-2">
                <CetakSwitch
                  label="Gunakan Margin Kertas Global"
                  checked={jenisForm.marginGlobal}
                  onChange={(marginGlobal) =>
                    setJenisForm((current) => ({ ...current, marginGlobal }))
                  }
                />
                <div className="grid grid-cols-4 gap-2">
                  <CetakAngka
                    label="Kiri (cm)"
                    value={jenisForm.marginKiri}
                    disabled={jenisForm.marginGlobal}
                    onChange={(marginKiri) =>
                      setJenisForm((current) => ({ ...current, marginKiri }))
                    }
                  />
                  <CetakAngka
                    label="Atas (cm)"
                    value={jenisForm.marginAtas}
                    disabled={jenisForm.marginGlobal}
                    onChange={(marginAtas) =>
                      setJenisForm((current) => ({ ...current, marginAtas }))
                    }
                  />
                  <CetakAngka
                    label="Kanan (cm)"
                    value={jenisForm.marginKanan}
                    disabled={jenisForm.marginGlobal}
                    onChange={(marginKanan) =>
                      setJenisForm((current) => ({ ...current, marginKanan }))
                    }
                  />
                  <CetakAngka
                    label="Bawah (cm)"
                    value={jenisForm.marginBawah}
                    disabled={jenisForm.marginGlobal}
                    onChange={(marginBawah) =>
                      setJenisForm((current) => ({ ...current, marginBawah }))
                    }
                  />
                </div>
              </div>

              <div className="space-y-2">
                <CetakSwitch
                  label="Format Nomor Surat Global"
                  checked={jenisForm.formatNomorGlobal}
                  onChange={(formatNomorGlobal) =>
                    setJenisForm((current) => ({ ...current, formatNomorGlobal }))
                  }
                />
                <div className="space-y-1">
                  <Label className="text-[11px] text-muted-foreground">
                    Format Nomor Surat
                  </Label>
                  <Input
                    disabled={jenisForm.formatNomorGlobal}
                    value={jenisForm.formatNomor ?? ""}
                    onChange={(event) =>
                      setJenisForm((current) => ({
                        ...current,
                        formatNomor: event.target.value,
                      }))
                    }
                    placeholder="[nomor_surat, 3]/PK-TBT/[bulan_romawi]/[tahun]"
                    className="h-9 font-mono text-xs disabled:opacity-50"
                  />
                  <p className="text-[11px] text-muted-foreground">
                    Token: [nomor_surat, 3] · [kode_surat] · [bulan] · [bulan_romawi] ·
                    [bulan_bahasa] · [tahun] · [tahun_romawi]
                  </p>
                </div>
              </div>

              <div className="space-y-1.5">
                <Label>Tampilkan Header</Label>
                <Select
                  value={String(jenisForm.header)}
                  onChange={(event) =>
                    setJenisForm((current) => ({
                      ...current,
                      header: Number(event.target.value) as HeaderSurat,
                    }))
                  }
                >
                  {PILIHAN_HEADER_SURAT.map((nilai) => (
                    <option key={nilai} value={nilai}>
                      {{ 1: "Semua Halaman", 2: "Hanya Halaman Awal", 0: "Tidak" }[nilai]}
                    </option>
                  ))}
                </Select>
              </div>

              <div className="grid gap-2 sm:grid-cols-2">
                <CetakSwitch
                  label="Tampilkan Footer"
                  checked={jenisForm.footer}
                  onChange={(footer) =>
                    setJenisForm((current) => ({ ...current, footer }))
                  }
                />
                <CetakSwitch
                  label="Logo Burung Garuda"
                  checked={jenisForm.logoGaruda}
                  onChange={(logoGaruda) =>
                    setJenisForm((current) => ({ ...current, logoGaruda }))
                  }
                />
                <CetakSwitch
                  label="Tampilkan QR Code"
                  checked={jenisForm.qrCode}
                  onChange={(qrCode) =>
                    setJenisForm((current) => ({ ...current, qrCode }))
                  }
                />
                <CetakSwitch
                  label="Tampilkan QR Code TTE"
                  checked={jenisForm.qrCodeTte}
                  onChange={(qrCodeTte) =>
                    setJenisForm((current) => ({ ...current, qrCodeTte }))
                  }
                />
                <CetakSwitch
                  label="Sumber Penduduk Berulang"
                  checked={jenisForm.sumberPendudukBerulang}
                  onChange={(sumberPendudukBerulang) =>
                    setJenisForm((current) => ({ ...current, sumberPendudukBerulang }))
                  }
                />
              </div>
            </fieldset>

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

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

      <Dialog
        open={!!deletePermohonan}
        onOpenChange={(open) => !open && setDeletePermohonan(null)}
      >
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus permohonan surat?</DialogTitle>
            <DialogDescription>
              Permohonan {deletePermohonan?.nomor} atas nama{" "}
              {deletePermohonan?.penduduk?.nama} akan dihapus permanen.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDeletePermohonan(null)}>
              Batal
            </Button>
            <Button variant="destructive" onClick={removePermohonan} disabled={deleting}>
              {deleting ? "Menghapus…" : "Hapus"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={!!detailJenis} onOpenChange={(open) => !open && setDetailJenis(null)}>
        <DialogContent className="max-w-xl">
          <DialogHeader>
            <DialogTitle className="flex flex-wrap items-center gap-2">
              {detailJenis?.nama}
              {detailJenis && (
                <Badge variant={detailJenis.aktif ? "success" : "secondary"}>
                  {detailJenis.aktif ? "Aktif" : "Nonaktif"}
                </Badge>
              )}
              {detailJenis?.mandiri && <Badge variant="info">Mandiri</Badge>}
              {detailJenis?.favorit && <Badge variant="warning">Favorit</Badge>}
            </DialogTitle>
            <DialogDescription>
              {detailJenis
                ? JENIS_SURAT[detailJenis.jenis] ?? "Surat Sistem"
                : "Detail format surat"}
            </DialogDescription>
          </DialogHeader>

          {detailJenis && (
            <div className="space-y-4 text-sm">
              <div className="grid gap-3 sm:grid-cols-2">
                <div>
                  <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                    Kode surat
                  </p>
                  <p className="mt-0.5 font-mono text-sm">{detailJenis.kode}</p>
                </div>
                <div>
                  <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                    Lampiran
                  </p>
                  <p
                    className={cn(
                      "mt-0.5 font-mono text-sm",
                      detailJenis.lampiran ? "text-foreground" : "text-muted-foreground",
                    )}
                  >
                    {formatLampiran(detailJenis.lampiran)}
                  </p>
                </div>
                <div>
                  <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                    Masa berlaku
                  </p>
                  <p className="mt-0.5">{labelMasaBerlaku(detailJenis)}</p>
                </div>
                <div>
                  <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                    Permohonan
                  </p>
                  <p className="mt-0.5">{detailJenis._count?.permohonan ?? 0} permohonan</p>
                </div>
              </div>

              {detailJenis.urlSurat && (
                <div>
                  <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                    URL surat
                  </p>
                  <p className="mt-0.5 break-all font-mono text-xs">{detailJenis.urlSurat}</p>
                </div>
              )}

              <div>
                <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                  Deskripsi
                </p>
                <p className="mt-0.5 text-muted-foreground">
                  {detailJenis.deskripsi ?? "Belum ada deskripsi."}
                </p>
              </div>

              <div>
                <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                  Persyaratan
                </p>
                {detailJenis.syarat?.trim() ? (
                  <ul className="mt-1 list-inside list-disc space-y-1 text-muted-foreground">
                    {detailJenis.syarat
                      .split("\n")
                      .map((baris) => baris.trim())
                      .filter(Boolean)
                      .map((baris) => (
                        <li key={baris}>{baris}</li>
                      ))}
                  </ul>
                ) : (
                  <p className="mt-0.5 text-muted-foreground">Belum ada persyaratan.</p>
                )}
              </div>
            </div>
          )}

          <DialogFooter className="flex-wrap gap-2">
            <Button variant="outline" onClick={() => setDetailJenis(null)}>
              Kembali Ke Daftar Surat
            </Button>
            {isAdmin && detailJenis && (
              <Button
                variant="ghost"
                className="text-destructive hover:text-destructive"
                onClick={() => {
                  setDeleteJenis(detailJenis);
                  setDetailJenis(null);
                }}
              >
                <Trash2 className="mr-2 h-4 w-4" /> Hapus
              </Button>
            )}
            {isAdmin && detailJenis && (
              <Button
                variant="outline"
                onClick={() => {
                  openJenisEditor(detailJenis);
                  setDetailJenis(null);
                }}
              >
                <Settings2 className="mr-2 h-4 w-4" /> Pengaturan
              </Button>
            )}
            {detailJenis && (
              <Link href={`/admin/cetak-surat/${detailJenis.id}`}>
                <Button>
                  <Printer className="mr-2 h-4 w-4" /> Buat Surat
                </Button>
              </Link>
            )}
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={bulkPermohonanOpen} onOpenChange={setBulkPermohonanOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus {selectedPermohonanIds.length} permohonan surat?</DialogTitle>
            <DialogDescription>
              Permohonan beserta nomor suratnya dihapus permanen dan tidak dapat
              dikembalikan.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button
              variant="outline"
              onClick={() => setBulkPermohonanOpen(false)}
              disabled={bulkDeleting}
            >
              Batal
            </Button>
            <Button
              variant="destructive"
              onClick={hapusPermohonanTerpilih}
              disabled={bulkDeleting}
            >
              {bulkDeleting ? "Menghapus…" : "Hapus"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={bulkJenisOpen} onOpenChange={setBulkJenisOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus {selectedJenisIds.length} jenis surat?</DialogTitle>
            <DialogDescription>
              Jenis surat yang sudah digunakan pada permohonan tidak akan terhapus. Tindakan
              ini tidak dapat dibatalkan.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button
              variant="outline"
              onClick={() => setBulkJenisOpen(false)}
              disabled={bulkDeleting}
            >
              Batal
            </Button>
            <Button variant="destructive" onClick={hapusJenisTerpilih} disabled={bulkDeleting}>
              {bulkDeleting ? "Menghapus…" : "Hapus"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={imporOpen} onOpenChange={setImporOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>Impor Surat</DialogTitle>
            <DialogDescription>
              Muat berkas JSON hasil Ekspor jenis surat. Jenis surat dengan nama yang
              sama tidak dibuat ulang.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-3">
            <div className="space-y-1.5">
              <Label htmlFor="userfile">File Impor :</Label>
              <Input
                id="userfile"
                name="userfile"
                type="file"
                accept="application/json"
                onChange={(event) => pilihBerkasImpor(event.target.files?.[0])}
              />
              <p className="text-xs text-muted-foreground">
                {imporItems
                  ? `${imporNama}: ${imporItems.length} jenis surat siap diimpor`
                  : 'Format berkas: { "items": [ { "nama": "...", "kode": "..." } ] } atau array objek.'}
              </p>
            </div>
            {imporError && (
              <p className="rounded-lg bg-destructive/10 px-3 py-2 text-xs text-destructive">
                {imporError}
              </p>
            )}
          </div>
          <DialogFooter className="flex-col gap-2 sm:justify-between">
            <Button type="button" variant="ghost" onClick={contohJenisSistem}>
              Contoh Surat Layanan Sistem
            </Button>
            <div className="flex gap-2">
              <Button variant="outline" onClick={() => setImporOpen(false)}>
                Batal
              </Button>
              <Button onClick={jalankanImpor} disabled={imporLoading || !imporItems}>
                {imporLoading ? "Mengimpor…" : "Simpan"}
              </Button>
            </div>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={!!deleteJenis} onOpenChange={(open) => !open && setDeleteJenis(null)}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus jenis surat?</DialogTitle>
            <DialogDescription>
              Jenis surat {deleteJenis?.nama} akan dihapus. Jenis yang sudah digunakan
              pada permohonan tidak dapat dihapus.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDeleteJenis(null)}>
              Batal
            </Button>
            <Button variant="destructive" onClick={removeJenis} disabled={deleting}>
              {deleting ? "Menghapus…" : "Hapus"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
