"use client";

import { useState } from "react";
import useSWR from "swr";
import type { LucideIcon } from "lucide-react";
import {
  Building2,
  Download,
  FilePenLine,
  GitBranch,
  Home,
  Map,
  Plus,
  Printer,
  Trash2,
  UserRound,
  Users,
} from "lucide-react";
import { toast } from "sonner";
import type { Penduduk, Wilayah } from "@/lib/types";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import { cetakHtml } from "@/lib/cetak";
import { unduhCsv } from "@/lib/sekretariat";
import { useSession } from "@/lib/use-session";
import { PageHeader, StatCard } from "@/components/page-header";
import { SettingsForm, type SettingField } from "@/components/admin/settings-form";
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 { cn, formatNumber } from "@/lib/utils";

const LEVEL_LABEL: Record<string, string> = {
  DUSUN: "Dusun",
  RW: "RW",
  RT: "RT",
};

// Acuan: OpenSID lama -> Info Desa > Wilayah Administratif > tombol "Pengaturan".
const WILAYAH_PENGATURAN: SettingField[] = [
  {
    kunci: "wilayah.sebutan_dusun",
    label: "Sebutan Dusun",
    defaultValue: "dusun",
    help: "Pengganti sebutan wilayah dusun.",
  },
  {
    kunci: "wilayah.sebutan_singkatan_kepala_dusun",
    label: "Sebutan Singkatan Kepala Dusun",
    defaultValue: "Kepala Dusun",
    help: "Sebutan singkatan Kepala Dusun.",
  },
];

type FormState = {
  nama: string;
  level: "DUSUN" | "RW" | "RT";
  parentId: string;
  kepalaId: string;
  urut: string;
};

const emptyForm: FormState = {
  nama: "",
  level: "DUSUN",
  parentId: "",
  kepalaId: "",
  urut: "0",
};

type PendudukPage = {
  data: Penduduk[];
  meta: { total: number; page: number; limit: number; totalPages: number };
};

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

  const { data: wilayah, isLoading, mutate } = useSWR<Wilayah[]>("/wilayah", fetcher);
  const { data: pendudukPage } = useSWR<PendudukPage>(
    "/penduduk?limit=200&status=HIDUP",
    fetcher,
  );
  const penduduk = pendudukPage?.data ?? [];

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

  const list = wilayah ?? [];
  const dusun = list.filter((item) => item.level === "DUSUN");
  const rwList = list.filter((item) => item.level === "RW");
  const rtList = list.filter((item) => item.level === "RT");

  const parentOptions =
    form.level === "RW"
      ? dusun
      : form.level === "RT"
        ? rwList
        : [];

  function openCreate(level: FormState["level"] = "DUSUN", parentId?: number) {
    setEditing(null);
    setForm({ ...emptyForm, level, parentId: parentId ? String(parentId) : "" });
    setFormOpen(true);
  }

  function openEdit(item: Wilayah) {
    setEditing(item);
    setForm({
      nama: item.nama,
      level: item.level,
      parentId: item.parentId ? String(item.parentId) : "",
      kepalaId: item.kepalaId ? String(item.kepalaId) : "",
      urut: String(item.urut ?? 0),
    });
    setFormOpen(true);
  }

  async function save(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSaving(true);
    try {
      const payload: Record<string, unknown> = {
        nama: form.nama,
        level: form.level,
        ...(form.level !== "DUSUN"
          ? { parentId: form.parentId ? Number(form.parentId) : null }
          : { parentId: null }),
        kepalaId: form.kepalaId ? Number(form.kepalaId) : null,
        urut: Number(form.urut) || 0,
      };
      if (editing) {
        await apiSend(`/wilayah/${editing.id}`, "PATCH", payload);
        toast.success("Wilayah diperbarui");
      } else {
        await apiSend("/wilayah", "POST", payload);
        toast.success("Wilayah ditambahkan");
      }
      setFormOpen(false);
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyimpan wilayah");
    } finally {
      setSaving(false);
    }
  }

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

  const byUrutNama = (a: Wilayah, b: Wilayah) =>
    (a.urut ?? 0) - (b.urut ?? 0) || a.nama.localeCompare(b.nama);
  const sortedRw = (parentId: number) =>
    rwList.filter((item) => item.parentId === parentId).sort(byUrutNama);
  const sortedRt = (parentId: number) =>
    rtList.filter((item) => item.parentId === parentId).sort(byUrutNama);

  const REKAP_KEPALA = ["No", "Dusun", "NIK", "RW", "RT", "KK", "L+P", "L", "P", "Total"];
  const rekapDusun = dusun.slice().sort(byUrutNama);
  const barisRekap = rekapDusun.map((item, index) => {
    const l = item.lakiLaki ?? 0;
    const p = item.perempuan ?? 0;
    const penduduk = item.jumlahPenduduk ?? 0;
    return [
      index + 1,
      item.nama,
      penduduk,
      item.jumlahRw ?? 0,
      item.jumlahRt ?? 0,
      item.jumlahKk ?? 0,
      l + p,
      l,
      p,
      penduduk,
    ];
  });
  const jumlah = (kolom: number) =>
    barisRekap.reduce((total, baris) => total + Number(baris[kolom] ?? 0), 0);
  const totalRekap = [
    "",
    "Total",
    jumlah(2),
    jumlah(3),
    jumlah(4),
    jumlah(5),
    jumlah(6),
    jumlah(7),
    jumlah(8),
    jumlah(9),
  ];

  function tabelRekapHtml() {
    const kepala = `<tr>${REKAP_KEPALA.map((judul) => `<th>${judul}</th>`).join("")}</tr>`;
    const isi = barisRekap
      .map(
        (baris) =>
          `<tr>${baris
            .map((nilai) => `<td${typeof nilai === "number" ? ' align="right"' : ""}>${nilai}</td>`)
            .join("")}</tr>`,
      )
      .join("");
    const ekor = `<tr><td colspan="2"><strong>Total</strong></td>${totalRekap
      .slice(2)
      .map((nilai) => `<td align="right"><strong>${nilai}</strong></td>`)
      .join("")}</tr>`;
    return `<table border="1" cellspacing="0" cellpadding="6" width="100%"><thead>${kepala}</thead><tbody>${isi}${ekor}</tbody></table>`;
  }

  function cetakRekap() {
    if (!cetakHtml("Rekapitulasi Wilayah Administratif", tabelRekapHtml())) {
      toast.error("Izinkan pop-up untuk mencetak");
    }
  }

  function unduhRekap() {
    unduhCsv(
      `rekap-wilayah-${new Date().toISOString().slice(0, 10)}.csv`,
      REKAP_KEPALA,
      [...barisRekap, totalRekap],
    );
    toast.success("Rekap wilayah diunduh");
  }

  return (
    <div className="animate-fade-in space-y-6">
      <PageHeader
        title="Wilayah Administratif"
        description="Struktur dusun, RW, dan RT Desa Mulyadadi beserta jumlah penduduk dan keluarga."
        action={
          <div className="flex flex-wrap gap-2 print:hidden">
            <Button variant="outline" onClick={() => window.print()}>
              <Printer className="h-4 w-4" />
              Cetak
            </Button>
            {isAdmin && (
              <Button onClick={() => openCreate()}>
                <Plus className="h-4 w-4" />
                Tambah Wilayah
              </Button>
            )}
          </div>
        }
      />

      <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
        <StatCard title="Dusun" value={dusun.length} icon={Map} />
        <StatCard title="RW" value={rwList.length} icon={GitBranch} tone="sky" />
        <StatCard title="RT" value={rtList.length} icon={Home} tone="amber" />
        <StatCard
          title="Penduduk terpetakan"
          value={formatNumber(
            list
              .filter((item) => item.level === "RT")
              .reduce((total, item) => total + (item.jumlahPenduduk ?? 0), 0),
          )}
          icon={Users}
          tone="violet"
        />
      </div>

      <Card>
        <CardContent className="p-0">
          {isLoading ? (
            <div className="space-y-2 p-4">
              {Array.from({ length: 5 }).map((_, index) => (
                <div key={index} className="h-14 animate-pulse rounded-lg bg-muted" />
              ))}
            </div>
          ) : dusun.length ? (
            <div className="divide-y">
              {dusun.map((dusunItem) => (
                <div key={dusunItem.id} className="p-4">
                  <WilayahRow
                    item={dusunItem}
                    icon={Building2}
                    canManage={isAdmin}
                    onEdit={openEdit}
                    onDelete={setDeleteTarget}
                    onAdd={() => openCreate("RW", dusunItem.id)}
                    addLabel="Tambah RW"
                  />
                  <div className="mt-2 space-y-2 border-l-2 border-emerald-100 pl-4">
                    {sortedRw(dusunItem.id).map((rw) => (
                      <div key={rw.id}>
                        <WilayahRow
                          item={rw}
                          icon={GitBranch}
                          canManage={isAdmin}
                          onEdit={openEdit}
                          onDelete={setDeleteTarget}
                          onAdd={() => openCreate("RT", rw.id)}
                          addLabel="Tambah RT"
                        />
                        <div className="mt-2 space-y-1.5 border-l-2 border-slate-100 pl-4">
                          {sortedRt(rw.id).map((rt) => (
                            <WilayahRow
                              key={rt.id}
                              item={rt}
                              icon={Home}
                              canManage={isAdmin}
                              onEdit={openEdit}
                              onDelete={setDeleteTarget}
                              compact
                            />
                          ))}
                          {!sortedRt(rw.id).length && (
                            <p className="py-1 text-xs text-muted-foreground">
                              Belum ada RT.
                            </p>
                          )}
                        </div>
                      </div>
                    ))}
                    {!sortedRw(dusunItem.id).length && (
                      <p className="py-1 text-xs text-muted-foreground">
                        Belum ada RW.
                      </p>
                    )}
                  </div>
                </div>
              ))}
            </div>
          ) : (
            <div className="py-16 text-center">
              <p className="font-semibold">Belum ada wilayah</p>
              <p className="mt-1 text-sm text-muted-foreground">
                Tambahkan dusun terlebih dahulu, lalu RW dan RT di bawahnya.
              </p>
            </div>
          )}
        </CardContent>
      </Card>

      <Card>
        <CardContent className="space-y-4 p-4 md:p-5">
          <div className="flex flex-wrap items-center justify-between gap-2">
            <div>
              <h2 className="text-sm font-semibold">Rekapitulasi per Dusun</h2>
              <p className="text-xs text-muted-foreground">
                NIK = jumlah penduduk terdata; L+P dan Total = laki-laki + perempuan.
              </p>
            </div>
            <div className="flex flex-wrap gap-2">
              <Button variant="outline" size="sm" onClick={cetakRekap}>
                <Printer className="h-4 w-4" /> Cetak
              </Button>
              <Button variant="outline" size="sm" onClick={unduhRekap}>
                <Download className="h-4 w-4" /> Unduh
              </Button>
            </div>
          </div>

          {rekapDusun.length ? (
            <div className="overflow-x-auto rounded-lg border border-border">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead className="w-14">No</TableHead>
                    <TableHead className="w-28">Aksi</TableHead>
                    <TableHead>Dusun</TableHead>
                    <TableHead className="text-right">NIK</TableHead>
                    <TableHead className="text-right">RW</TableHead>
                    <TableHead className="text-right">RT</TableHead>
                    <TableHead className="text-right">KK</TableHead>
                    <TableHead className="text-right">L+P</TableHead>
                    <TableHead className="text-right">L</TableHead>
                    <TableHead className="text-right">P</TableHead>
                    <TableHead className="text-right">Total</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {rekapDusun.map((item, index) => {
                    const l = item.lakiLaki ?? 0;
                    const p = item.perempuan ?? 0;
                    return (
                      <TableRow key={item.id}>
                        <TableCell className="text-muted-foreground">{index + 1}</TableCell>
                        <TableCell>
                          <div className="flex gap-1">
                            <Button
                              variant="ghost"
                              size="icon"
                              className="h-8 w-8"
                              onClick={() => openEdit(item)}
                              title="Ubah Dusun"
                              aria-label={`Ubah ${item.nama}`}
                            >
                              <FilePenLine className="h-4 w-4" />
                            </Button>
                            {isAdmin && (
                              <Button
                                variant="ghost"
                                size="icon"
                                className="h-8 w-8 text-destructive"
                                onClick={() => setDeleteTarget(item)}
                                title="Hapus Dusun"
                                aria-label={`Hapus ${item.nama}`}
                              >
                                <Trash2 className="h-4 w-4" />
                              </Button>
                            )}
                          </div>
                        </TableCell>
                        <TableCell className="font-medium">{item.nama}</TableCell>
                        <TableCell className="text-right">{item.jumlahPenduduk ?? 0}</TableCell>
                        <TableCell className="text-right">{item.jumlahRw ?? 0}</TableCell>
                        <TableCell className="text-right">{item.jumlahRt ?? 0}</TableCell>
                        <TableCell className="text-right">{item.jumlahKk ?? 0}</TableCell>
                        <TableCell className="text-right">{l + p}</TableCell>
                        <TableCell className="text-right">{l}</TableCell>
                        <TableCell className="text-right">{p}</TableCell>
                        <TableCell className="text-right">{item.jumlahPenduduk ?? 0}</TableCell>
                      </TableRow>
                    );
                  })}
                  <TableRow className="border-t-2 font-semibold">
                    <TableCell colSpan={3}>Total</TableCell>
                    <TableCell className="text-right">{jumlah(2)}</TableCell>
                    <TableCell className="text-right">{jumlah(3)}</TableCell>
                    <TableCell className="text-right">{jumlah(4)}</TableCell>
                    <TableCell className="text-right">{jumlah(5)}</TableCell>
                    <TableCell className="text-right">{jumlah(6)}</TableCell>
                    <TableCell className="text-right">{jumlah(7)}</TableCell>
                    <TableCell className="text-right">{jumlah(8)}</TableCell>
                    <TableCell className="text-right">{jumlah(9)}</TableCell>
                  </TableRow>
                </TableBody>
              </Table>
            </div>
          ) : (
            <p className="py-8 text-center text-sm text-muted-foreground">
              Belum ada dusun untuk direkap.
            </p>
          )}
        </CardContent>
      </Card>

      <SettingsForm
        grup="wilayah"
        title="Pengaturan Wilayah Administratif"
        hideHeader
        cardTitle="Pengaturan Wilayah Administratif"
        fields={WILAYAH_PENGATURAN}
      />

      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>{editing ? "Ubah Wilayah" : "Tambah Wilayah"}</DialogTitle>
            <DialogDescription>
              Hierarki wilayah: Dusun → RW → RT.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={save} className="space-y-4">
            <div className="space-y-1.5">
              <Label>
                Nama wilayah <span className="text-destructive">*</span>
              </Label>
              <Input
                required
                value={form.nama}
                onChange={(event) =>
                  setForm((current) => ({ ...current, nama: event.target.value }))
                }
                placeholder="Contoh: Dusun Sukamaju / RW 01 / RT 02"
              />
            </div>
            <div className="space-y-1.5">
              <Label>Level</Label>
              <Select
                value={form.level}
                onChange={(event) =>
                  setForm((current) => ({
                    ...current,
                    level: event.target.value as FormState["level"],
                    parentId: "",
                  }))
                }
              >
                <option value="DUSUN">Dusun</option>
                <option value="RW">RW</option>
                <option value="RT">RT</option>
              </Select>
            </div>
            {form.level !== "DUSUN" && (
              <div className="space-y-1.5">
                <Label>
                  Induk {form.level === "RW" ? "Dusun" : "RW"}{" "}
                  <span className="text-destructive">*</span>
                </Label>
                <Select
                  required
                  value={form.parentId}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, parentId: event.target.value }))
                  }
                >
                  <option value="">Pilih induk wilayah</option>
                  {parentOptions.map((option) => (
                    <option key={option.id} value={option.id}>
                      {option.nama}
                    </option>
                  ))}
                </Select>
              </div>
            )}
            <div className="grid gap-4 sm:grid-cols-2">
              <div className="space-y-1.5">
                <Label>Kepala / Ketua wilayah</Label>
                <Select
                  value={form.kepalaId}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, kepalaId: event.target.value }))
                  }
                >
                  <option value="">Belum ditentukan</option>
                  {penduduk.map((item) => (
                    <option key={item.id} value={item.id}>
                      {item.nama} — {item.nik}
                    </option>
                  ))}
                </Select>
              </div>
              <div className="space-y-1.5">
                <Label>Urutan tampil</Label>
                <Input
                  type="number"
                  min={0}
                  value={form.urut}
                  onChange={(event) =>
                    setForm((current) => ({ ...current, urut: event.target.value }))
                  }
                />
              </div>
            </div>
            <DialogFooter>
              <Button type="button" variant="outline" onClick={() => setFormOpen(false)}>
                Batal
              </Button>
              <Button type="submit" disabled={saving}>
                {saving ? "Menyimpan…" : editing ? "Simpan Perubahan" : "Tambah"}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <Dialog open={!!deleteTarget} onOpenChange={(open) => !open && setDeleteTarget(null)}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus wilayah?</DialogTitle>
            <DialogDescription>
              Wilayah <span className="font-semibold">{deleteTarget?.nama}</span> akan
              dihapus. Wilayah yang masih memiliki sub-wilayah, penduduk, atau keluarga
              tidak dapat dihapus.
            </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 WilayahRow({
  item,
  icon: Icon,
  canManage,
  onEdit,
  onDelete,
  onAdd,
  addLabel,
  compact,
}: {
  item: Wilayah;
  icon: LucideIcon;
  canManage: boolean;
  onEdit: (item: Wilayah) => void;
  onDelete: (item: Wilayah) => void;
  onAdd?: () => void;
  addLabel?: string;
  compact?: boolean;
}) {
  return (
    <div
      className={cn(
        "flex flex-wrap items-center justify-between gap-2 rounded-lg px-2 py-1.5",
        !compact && "bg-muted/40",
      )}
    >
      <div className="flex min-w-0 items-center gap-2">
        <Icon className="h-4 w-4 shrink-0 text-emerald-700" />
        <span className={cn("truncate font-medium", compact ? "text-sm" : "text-sm")}>
          {item.nama}
        </span>
        <Badge variant="secondary">{LEVEL_LABEL[item.level]}</Badge>
        {item.kepala && (
          <span className="flex items-center gap-1 text-[11px] text-muted-foreground">
            <UserRound className="h-3 w-3" />
            {item.kepala.nama}
          </span>
        )}
        <span className="text-[11px] text-muted-foreground">
          {item.jumlahPenduduk ?? 0} jiwa · {item.jumlahKk ?? 0} KK
          {item.level !== "RT"
            ? ` · ${item.level === "DUSUN" ? item.jumlahRw ?? 0 : item.jumlahRt ?? 0} ${
                item.level === "DUSUN" ? "RW" : "RT"
              }`
            : ` · L ${item.lakiLaki ?? 0} / P ${item.perempuan ?? 0}`}
        </span>
      </div>
      {canManage && (
        <div className="flex gap-1 print:hidden">
          {onAdd && addLabel && (
            <Button variant="ghost" size="sm" className="h-7 px-2 text-xs" onClick={onAdd}>
              <Plus className="h-3.5 w-3.5" />
              {addLabel}
            </Button>
          )}
          <Button
            variant="ghost"
            size="icon"
            className="h-7 w-7"
            onClick={() => onEdit(item)}
            aria-label="Ubah wilayah"
          >
            <FilePenLine className="h-3.5 w-3.5" />
          </Button>
          <Button
            variant="ghost"
            size="icon"
            className="h-7 w-7 text-destructive hover:text-destructive"
            onClick={() => onDelete(item)}
            aria-label="Hapus wilayah"
          >
            <Trash2 className="h-3.5 w-3.5" />
          </Button>
        </div>
      )}
    </div>
  );
}
