import { useMemo, useRef, useState } from "react";
import { FormDialog, val, type Field } from "@/components/sip/FormDialog";
import { Section, DataTable } from "@/components/sip/Section";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Plus, Pencil, Trash2, Download, Upload } from "lucide-react";
import { toast } from "sonner";
import {
  AGAMA_LIST,
  newId,
  useSip,
  type Dapodik,
  type StatusDapodik,
  jenjangOfKelas,
  JENJANG_LIST,
} from "@/lib/sip-data";
import { FilterBar, type ViewMode } from "@/components/sip/FilterBar";

const KOLOM: { key: keyof Dapodik; label: string }[] = [
  { key: "nama", label: "Nama Siswa" },
  { key: "kelas", label: "Kelas" },
  { key: "tempatLahir", label: "Tempat Lahir" },
  { key: "tanggalLahir", label: "Tanggal Lahir" },
  { key: "nipd", label: "NIPD" },
  { key: "nisn", label: "NISN" },
  { key: "nik", label: "NIK" },
  { key: "jk", label: "JK" },
  { key: "agama", label: "Agama" },
  { key: "namaAyah", label: "Nama Ayah" },
  { key: "namaIbu", label: "Nama Ibu" },
  { key: "hpOrtu", label: "No HP Ortu/Wali" },
  { key: "hpSiswa", label: "No HP Siswa" },
  { key: "alamat", label: "Alamat Siswa" },
];

const statusVariant = (s: StatusDapodik) =>
  s === "Terverifikasi" ? "default" : s === "Perbaikan Diajukan" ? "destructive" : "secondary";

export function DataDapodik() {
  const { dapodik, setDapodik, kelasList } = useSip();
  const [kelas, setKelas] = useState("");
  const [query, setQuery] = useState("");
  const [view, setView] = useState<ViewMode>("rinci");
  const fileRef = useRef<HTMLInputElement>(null);

  const fields = (d?: Dapodik): Field[] => [
    { name: "nama", label: "Nama Siswa", defaultValue: d?.nama },
    { name: "kelas", label: "Kelas", type: "select", options: kelasList, defaultValue: d?.kelas },
    { name: "tempatLahir", label: "Tempat Lahir", defaultValue: d?.tempatLahir },
    { name: "tanggalLahir", label: "Tanggal Lahir", type: "date", defaultValue: d?.tanggalLahir },
    { name: "nipd", label: "NIPD", defaultValue: d?.nipd },
    { name: "nisn", label: "NISN", defaultValue: d?.nisn },
    { name: "nik", label: "NIK", defaultValue: d?.nik },
    { name: "jk", label: "Jenis Kelamin", type: "select", options: ["L", "P"], defaultValue: d?.jk },
    { name: "agama", label: "Agama", type: "select", options: AGAMA_LIST, defaultValue: d?.agama },
    { name: "namaAyah", label: "Nama Ayah", defaultValue: d?.namaAyah },
    { name: "namaIbu", label: "Nama Ibu", defaultValue: d?.namaIbu },
    { name: "hpOrtu", label: "No HP Orang Tua/Wali", defaultValue: d?.hpOrtu },
    { name: "hpSiswa", label: "No HP Siswa", optional: true, defaultValue: d?.hpSiswa },
    { name: "alamat", label: "Alamat Siswa", type: "textarea", defaultValue: d?.alamat },
  ];

  const fromValues = (v: Record<string, string>) => ({
    nama: val(v, "nama"),
    kelas: val(v, "kelas"),
    tempatLahir: val(v, "tempatLahir"),
    tanggalLahir: val(v, "tanggalLahir"),
    nipd: val(v, "nipd"),
    nisn: val(v, "nisn"),
    nik: val(v, "nik"),
    jk: (val(v, "jk") === "P" ? "P" : "L") as "L" | "P",
    agama: val(v, "agama"),
    namaAyah: val(v, "namaAyah"),
    namaIbu: val(v, "namaIbu"),
    hpOrtu: val(v, "hpOrtu"),
    hpSiswa: val(v, "hpSiswa"),
    alamat: val(v, "alamat"),
  });

  const downloadTemplate = async () => {
    const XLSX = await import("xlsx");
    const ws = XLSX.utils.json_to_sheet([
      {
        "Nama Siswa": "Andi Saputra",
        Kelas: kelasList[0] ?? "VII-A",
        "Tempat Lahir": "Palangka Raya",
        "Tanggal Lahir": "2012-05-14",
        NIPD: "10101",
        NISN: "0123456789",
        NIK: "6271010101120001",
        "Jenis Kelamin": "L",
        Agama: "Islam",
        "Nama Ayah": "Yanto",
        "Nama Ibu": "Sri",
        "No HP Ortu": "081234567890",
        "No HP Siswa": "081234567891",
        Alamat: "Jl. Rajawali No. 10",
      },
    ]);
    ws["!cols"] = KOLOM.map(() => ({ wch: 20 }));
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "Data Dapodik");
    XLSX.writeFile(wb, "template-data-dapodik.xlsx");
    toast.success("Template Excel diunduh");
  };

  const handleUpload = async (file: File) => {
    try {
      const XLSX = await import("xlsx");
      const wb = XLSX.read(await file.arrayBuffer(), { type: "array" });
      const sheetName = wb.SheetNames[0];
      if (!sheetName) throw new Error("kosong");
      const rows = XLSX.utils.sheet_to_json<Record<string, unknown>>(wb.Sheets[sheetName]!);
      const parsed: Dapodik[] = [];
      for (const r of rows) {
        const get = (...keys: string[]) => {
          for (const k of keys) {
            const hit = Object.keys(r).find((kk) => kk.trim().toLowerCase() === k.toLowerCase());
            if (hit && r[hit] !== undefined && r[hit] !== null) return String(r[hit]).trim();
          }
          return "";
        };
        const nama = get("Nama Siswa", "Nama");
        if (!nama) continue;
        parsed.push({
          id: newId("DP"),
          nama,
          kelas: get("Kelas") || (kelasList[0] ?? ""),
          tempatLahir: get("Tempat Lahir"),
          tanggalLahir: get("Tanggal Lahir"),
          nipd: get("NIPD"),
          nisn: get("NISN"),
          nik: get("NIK"),
          jk: get("Jenis Kelamin", "JK").toUpperCase() === "P" ? "P" : "L",
          agama: get("Agama"),
          namaAyah: get("Nama Ayah"),
          namaIbu: get("Nama Ibu"),
          hpOrtu: get("No HP Ortu", "No HP Orang Tua", "HP Ortu"),
          hpSiswa: get("No HP Siswa", "HP Siswa"),
          alamat: get("Alamat", "Alamat Siswa"),
          status: "Belum Diverifikasi",
        });
      }
      if (!parsed.length) {
        toast.error("Tidak ada data valid", { description: "Gunakan template yang disediakan." });
        return;
      }
      setDapodik((prev) => [...prev, ...parsed]);
      toast.success(`${parsed.length} data dapodik diimpor`);
    } catch {
      toast.error("Gagal membaca file", { description: "Pastikan file berformat .xlsx atau .xls" });
    }
  };

  const q = query.trim().toLowerCase();
  const data = dapodik.filter(
    (d) =>
      (!kelas || d.kelas === kelas) &&
      (!q ||
        d.nama.toLowerCase().includes(q) ||
        d.kelas.toLowerCase().includes(q) ||
        d.nisn.includes(q) ||
        d.nipd.includes(q)),
  );

  const rekapKelas = useMemo(
    () =>
      (kelas ? [kelas] : kelasList).map((k) => {
        const isi = dapodik.filter((d) => d.kelas === k);
        return {
          kelas: k,
          total: isi.length,
          verif: isi.filter((d) => d.status === "Terverifikasi").length,
          perbaikan: isi.filter((d) => d.status === "Perbaikan Diajukan").length,
        };
      }),
    [dapodik, kelas, kelasList],
  );

  const rekapJenjang = useMemo(
    () =>
      JENJANG_LIST.map((j) => {
        const isi = dapodik.filter((d) => jenjangOfKelas(d.kelas) === j);
        return {
          jenjang: j,
          total: isi.length,
          verif: isi.filter((d) => d.status === "Terverifikasi").length,
          perbaikan: isi.filter((d) => d.status === "Perbaikan Diajukan").length,
        };
      }),
    [dapodik],
  );

  return (
    <div className="space-y-6">
      <Section title="Status Validasi Orang Tua Per Tingkat">
        <div className="grid gap-3 sm:grid-cols-3">
          {rekapJenjang.map((r) => (
            <div key={r.jenjang} className="border-border bg-muted/30 rounded-xl border p-4">
              <p className="text-muted-foreground text-xs font-semibold">Tingkat {r.jenjang}</p>
              <p className="text-primary text-2xl font-bold">{r.total} siswa</p>
              <p className="text-muted-foreground mt-1 text-xs">
                {r.verif} terverifikasi · {r.perbaikan} perbaikan diajukan
              </p>
            </div>
          ))}
        </div>
      </Section>

      <Section
        title="Data Siswa (Dapodik)"
        action={
          <div className="flex w-full flex-wrap items-center gap-2 md:w-auto">
            <input
              ref={fileRef}
              type="file"
              accept=".xlsx,.xls"
              className="hidden"
              onChange={(e) => {
                const f = e.target.files?.[0];
                if (f) void handleUpload(f);
                e.target.value = "";
              }}
            />
            <Button size="sm" variant="outline" onClick={() => void downloadTemplate()}>
              <Download className="mr-1 h-4 w-4" /> Template
            </Button>
            <Button size="sm" variant="outline" onClick={() => fileRef.current?.click()}>
              <Upload className="mr-1 h-4 w-4" /> Unggah Excel
            </Button>
            <FormDialog
              title="Tambah Data Dapodik Siswa"
              fields={fields()}
              onSubmit={(v) => {
                setDapodik((prev) => [
                  ...prev,
                  { id: newId("DP"), ...fromValues(v), status: "Belum Diverifikasi" },
                ]);
                toast.success("Data dapodik ditambahkan");
              }}
              trigger={
                <Button size="sm">
                  <Plus className="mr-1 h-4 w-4" /> Tambah Data
                </Button>
              }
            />
          </div>
        }
      >
        <FilterBar
          query={query}
          onQueryChange={setQuery}
          kelas={kelas}
          onKelasChange={setKelas}
          kelasList={kelasList}
          view={view}
          onViewChange={setView}
          placeholder="Cari nama / NISN / NIPD / kelas..."
        />

        {view === "ringkas" ? (
          <DataTable
            head={["Kelas", "Jumlah Siswa", "Terverifikasi", "Perbaikan Diajukan"]}
            empty="Belum ada data kelas."
            rows={rekapKelas.map((r) => [
              <span className="font-medium">{r.kelas}</span>,
              r.total,
              r.verif,
              r.perbaikan,
            ])}
          />
        ) : (
          <DataTable
            head={["Nama Siswa", "Kelas", "NISN", "NIPD", "Status Validasi", "Catatan Ortu", "Aksi"]}
            alignLast
            empty="Belum ada data dapodik."
            rows={data.map((d) => [
              <span className="font-medium">{d.nama}</span>,
              <Badge variant="secondary">{d.kelas}</Badge>,
              d.nisn || "-",
              d.nipd || "-",
              <div className="space-y-1">
                <Badge variant={statusVariant(d.status)}>{d.status}</Badge>
                {d.diperbaruiPada ? (
                  <p className="text-muted-foreground text-xs">
                    {d.diperbaruiOleh} · {d.diperbaruiPada}
                  </p>
                ) : null}
              </div>,
              <span className="text-muted-foreground text-xs">{d.catatanOrtu || "-"}</span>,
              <div className="flex justify-center gap-1">
                <FormDialog
                  title={`Edit Data — ${d.nama}`}
                  fields={fields(d)}
                  submitLabel="Update"
                  onSubmit={(v) => {
                    setDapodik((prev) =>
                      prev.map((x) =>
                        x.id === d.id
                          ? { ...x, ...fromValues(v), status: "Belum Diverifikasi", catatanOrtu: "" }
                          : x,
                      ),
                    );
                    toast.success("Data dapodik diperbarui");
                  }}
                  trigger={
                    <Button size="icon" variant="ghost">
                      <Pencil className="h-4 w-4" />
                    </Button>
                  }
                />
                <Button
                  size="icon"
                  variant="ghost"
                  onClick={() => {
                    setDapodik((prev) => prev.filter((x) => x.id !== d.id));
                    toast.success("Data dapodik dihapus");
                  }}
                >
                  <Trash2 className="text-destructive h-4 w-4" />
                </Button>
              </div>,
            ])}
          />
        )}
      </Section>
    </div>
  );
}

export { KOLOM as KOLOM_DAPODIK };
