"use client";

import { useEffect, useState } from "react";
import useSWR from "swr";
import {
  Download,
  Printer,
  Search,
  SlidersHorizontal,
  UserCheck,
  Users,
  UsersRound,
  Vote,
} from "lucide-react";
import { toast } from "sonner";
import type {
  CalonPemilih,
  CalonPemilihResponse,
  Desa,
  Wilayah,
} from "@/lib/types";
import { fetcher } from "@/lib/api";
import { cetakHtml, escapeHtml, kopDesa } from "@/lib/cetak";
import { unduhCsv } from "@/lib/sekretariat";
import {
  AGAMA_OPTIONS,
  PENDIDIKAN_OPTIONS,
  PENDIDIKAN_SEDANG_OPTIONS,
  PEKERJAAN_OPTIONS,
  PUNYA_TIDAK_OPTIONS,
  STATUS_KAWIN_OPTIONS,
  labelGender,
} from "@/lib/utils";
import { PageHeader, StatCard } from "@/components/page-header";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
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";

const KOLOM_CALON_PEMILIH_CSV = [
  "NIK",
  "Tag ID Card",
  "Nama",
  "No. KK",
  "Jenis Kelamin",
  "Umur",
  "Status Perkawinan",
  "Pendidikan Dalam KK",
  "Pekerjaan",
  "Alamat",
  "Dusun",
  "RW",
  "RT",
];

const STATUS_PENDUDUK_OPTIONS = ["TETAP", "TIDAK_TETAP"];
const STATUS_PENDUDUK_LABEL: Record<string, string> = {
  TETAP: "Tetap",
  TIDAK_TETAP: "Tidak tetap",
};

function isoHariIni() {
  const now = new Date();
  const bulan = String(now.getMonth() + 1).padStart(2, "0");
  const hari = String(now.getDate()).padStart(2, "0");
  return `${now.getFullYear()}-${bulan}-${hari}`;
}

function tanggalPendek(iso: string) {
  const [tahun, bulan, hari] = iso.split("-");
  return `${hari}-${bulan}-${tahun}`;
}

function tanggalPanjang(iso: string) {
  const [tahun, bulan, hari] = iso.split("-").map(Number);
  return new Date(Date.UTC(tahun, bulan - 1, hari)).toLocaleDateString("id-ID", {
    day: "numeric",
    month: "long",
    year: "numeric",
  });
}

const emptyFilter = {
  rtId: "",
  rwId: "",
  dusunId: "",
  jenisKelamin: "",
  statusKawin: "",
  agama: "",
  pendidikan: "",
  pendidikanSedangDitempuh: "",
  pekerjaan: "",
  statusPenduduk: "",
  punyaTagIdCard: "",
  umurMin: "",
  umurMax: "",
};

export default function CalonPemilihPage() {
  const [tglPemilihan, setTglPemilihan] = useState(isoHariIni);
  const [search, setSearch] = useState("");
  const [q, setQ] = useState("");
  const [filter, setFilter] = useState(emptyFilter);
  const [spesifik, setSpesifik] = useState(false);

  useEffect(() => {
    const timer = setTimeout(() => setQ(search.trim()), 300);
    return () => clearTimeout(timer);
  }, [search]);

  const acuan = /^\d{4}-\d{2}-\d{2}$/.test(tglPemilihan) ? tglPemilihan : isoHariIni();
  const tahun = acuan.slice(0, 4);

  const query = new URLSearchParams({ tglPemilihan: acuan });
  if (q) query.set("q", q);
  for (const [key, value] of Object.entries(filter)) {
    if (value) query.set(key, value);
  }

  const { data, isLoading } = useSWR<CalonPemilihResponse>(
    `/calon-pemilih?${query.toString()}`,
    fetcher,
  );
  const { data: wilayah } = useSWR<Wilayah[]>("/wilayah", fetcher);
  const { data: desa } = useSWR<Desa>("/desa", fetcher);

  const allRegional = wilayah ?? [];
  const dusunOptions = allRegional.filter((item) => item.level === "DUSUN");
  const rwOptions = allRegional.filter(
    (item) => item.level === "RW" && (!filter.dusunId || item.parentId === Number(filter.dusunId)),
  );
  const rtOptions = allRegional.filter(
    (item) => item.level === "RT" && (!filter.rwId || item.parentId === Number(filter.rwId)),
  );
  const daftar = data?.data ?? [];
  const ringkasan = data?.ringkasan;

  function setValue(key: keyof typeof emptyFilter, value: string) {
    setFilter((current) => ({
      ...current,
      [key]: value,
      ...(key === "dusunId" ? { rwId: "", rtId: "" } : {}),
      ...(key === "rwId" ? { rtId: "" } : {}),
    }));
  }

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

  const tersaring = daftar;

  const adaFilter = Boolean(q) || Object.values(filter).some(Boolean);

  function bersihkan() {
    setSearch("");
    setQ("");
    setFilter(emptyFilter);
  }

  function barisCsv(row: CalonPemilih) {
    const rantai = rantaiWilayah(row.rt?.id);
    return [
      row.nik,
      row.tagIdCard ?? "",
      row.nama,
      row.keluarga?.noKk ?? "",
      labelGender(row.jenisKelamin),
      row.umur ?? "",
      row.statusKawin ?? "",
      row.pendidikan ?? "",
      row.pekerjaan ?? "",
      row.alamat ?? "",
      rantai.dusun,
      rantai.rw,
      rantai.rt,
    ];
  }

  function cetak(rows: CalonPemilih[] = tersaring) {
    if (!rows.length) {
      toast.error("Belum ada calon pemilih untuk dicetak");
      return;
    }
    const isi = `
      ${kopDesa(desa, `Daftar Calon Pemilih Tahun ${tahun}`)}
      <table class="info">
        <tr><td>Total calon pemilih</td><td>:</td><td>${ringkasan?.total ?? 0}</td></tr>
        <tr><td>Laki-laki / Perempuan</td><td>:</td><td>${ringkasan?.lakiLaki ?? 0} / ${ringkasan?.perempuan ?? 0}</td></tr>
        <tr><td>Pemilih pemula</td><td>:</td><td>${ringkasan?.pemula ?? 0}</td></tr>
      </table>
      <table>
        <thead><tr><th>No</th><th>NIK</th><th>Tag ID Card</th><th>Nama</th><th>No. KK</th><th>L/P</th><th>Pendidikan Dalam KK</th><th>Umur Pada ${tanggalPendek(acuan)}</th><th>Pekerjaan</th><th>Kawin</th><th>Alamat</th><th>Dusun</th><th>RW</th><th>RT</th></tr></thead>
        <tbody>
          ${rows
            .map((row, index) => {
              const rantai = rantaiWilayah(row.rt?.id);
              return `<tr><td class="num">${index + 1}</td><td>${escapeHtml(row.nik)}</td><td>${escapeHtml(row.tagIdCard ?? "-")}</td><td>${escapeHtml(row.nama)}</td><td>${escapeHtml(row.keluarga?.noKk ?? "-")}</td><td>${row.jenisKelamin === "L" ? "L" : "P"}</td><td>${escapeHtml(row.pendidikan ?? "-")}</td><td class="num">${row.umur ?? "-"}</td><td>${escapeHtml(row.pekerjaan ?? "-")}</td><td>${escapeHtml(row.statusKawin ?? "-")}</td><td>${escapeHtml(row.alamat ?? "-")}</td><td>${escapeHtml(rantai.dusun || "-")}</td><td>${escapeHtml(rantai.rw || "-")}</td><td>${escapeHtml(rantai.rt || "-")}</td></tr>`;
            })
            .join("")}
        </tbody>
      </table>
      <div class="ttd">
        <div>
          <div>${escapeHtml((desa?.kecamatan ?? "Cipari").toUpperCase())}, ${new Date().toLocaleDateString("id-ID", { day: "2-digit", month: "long", year: "numeric" })}</div>
          <div>Kepala Desa ${escapeHtml((desa?.nama ?? "Mulyadadi").replace(/^Desa\s+/i, ""))}</div>
          <div class="ruang"></div>
          <div><strong>${escapeHtml(desa?.kepalaDesa ?? "-")}</strong></div>
        </div>
      </div>
    `;
    if (!cetakHtml(`DPT ${tahun}`, isi)) {
      toast.error("Izinkan pop-up untuk mencetak daftar pemilih");
    }
  }

  function unduh(rows: CalonPemilih[] = tersaring) {
    if (!rows.length) {
      toast.error("Belum ada calon pemilih untuk diunduh");
      return;
    }
    unduhCsv(
      `calon-pemilih-${acuan}.csv`,
      KOLOM_CALON_PEMILIH_CSV,
      rows.map(barisCsv),
    );
    toast.success(`${rows.length} calon pemilih diekspor`);
  }

  return (
    <div className="animate-fade-in space-y-6">
      <PageHeader
        title="Calon Pemilih"
        description={`Daftar warga berpotensi sebagai pemilih pada ${tanggalPanjang(acuan)}: berusia 17 tahun atau lebih, atau sudah menikah.`}
        action={
          <div className="flex flex-wrap gap-2">
            <Button variant="outline" onClick={() => setSpesifik((value) => !value)}>
              <SlidersHorizontal className="h-4 w-4" />
              Pencarian Spesifik
            </Button>
            <Button
              variant="outline"
              onClick={() => unduh()}
              disabled={!tersaring.length}
            >
              <Download className="h-4 w-4" />
              Unduh
            </Button>
            <Button onClick={() => cetak()} disabled={!tersaring.length}>
              <Printer className="h-4 w-4" />
              Cetak
            </Button>
          </div>
        }
      />

      <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
        <StatCard
          title="Total calon pemilih"
          value={ringkasan?.total ?? 0}
          icon={Vote}
        />
        <StatCard
          title="Laki-laki"
          value={ringkasan?.lakiLaki ?? 0}
          icon={Users}
          tone="sky"
        />
        <StatCard
          title="Perempuan"
          value={ringkasan?.perempuan ?? 0}
          icon={UsersRound}
          tone="amber"
        />
        <StatCard
          title="Pemilih pemula"
          value={ringkasan?.pemula ?? 0}
          icon={UserCheck}
          tone="sky"
        />
      </div>

      <Card>
        <CardContent className="space-y-4 p-5">
          <div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
            <div className="relative w-full lg:max-w-sm">
              <Search className="pointer-events-none 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 nama, NIK, Tag ID Card, alamat…"
                className="pl-9"
              />
            </div>
            <div className="flex flex-wrap items-center gap-2">
              <div className="flex items-center gap-2">
                <Label
                  htmlFor="tgl-pemilihan"
                  className="whitespace-nowrap text-xs text-muted-foreground"
                >
                  Tanggal Pemilihan
                </Label>
                <Input
                  id="tgl-pemilihan"
                  type="date"
                  value={tglPemilihan}
                  onChange={(event) => setTglPemilihan(event.target.value)}
                  className="w-44"
                />
              </div>
              <Select
                value={filter.jenisKelamin}
                onChange={(event) => setValue("jenisKelamin", event.target.value)}
                className="w-full sm:w-40"
                aria-label="Filter jenis kelamin"
              >
                <option value="">Laki & perempuan</option>
                <option value="L">Laki-laki</option>
                <option value="P">Perempuan</option>
              </Select>
              <Select
                value={filter.dusunId}
                onChange={(event) => setValue("dusunId", event.target.value)}
                className="w-full sm:w-40"
                aria-label="Filter dusun"
              >
                <option value="">Semua dusun</option>
                {dusunOptions.map((item) => (
                  <option key={item.id} value={item.id}>
                    {item.nama}
                  </option>
                ))}
              </Select>
              <Select
                value={filter.rwId}
                onChange={(event) => setValue("rwId", event.target.value)}
                className="w-full sm:w-36"
                aria-label="Filter RW"
              >
                <option value="">Semua RW</option>
                {rwOptions.map((item) => (
                  <option key={item.id} value={item.id}>
                    {item.nama}
                  </option>
                ))}
              </Select>
              <Select
                value={filter.rtId}
                onChange={(event) => setValue("rtId", event.target.value)}
                className="w-full sm:w-36"
                aria-label="Filter RT"
              >
                <option value="">Semua RT</option>
                {rtOptions.map((rt) => (
                  <option key={rt.id} value={rt.id}>
                    {rt.nama}
                  </option>
                ))}
              </Select>
              {adaFilter && (
                <Button type="button" variant="ghost" onClick={bersihkan}>
                  Bersihkan
                </Button>
              )}
            </div>
          </div>

          {spesifik && (
            <div className="grid gap-4 rounded-xl border bg-muted/40 p-4 sm:grid-cols-2 lg:grid-cols-4">
              <div className="space-y-1.5">
                <Label>Umur minimal</Label>
                <Input
                  type="number"
                  min={0}
                  max={120}
                  value={filter.umurMin}
                  onChange={(event) => setValue("umurMin", event.target.value)}
                  placeholder="17"
                />
              </div>
              <div className="space-y-1.5">
                <Label>Umur maksimal</Label>
                <Input
                  type="number"
                  min={0}
                  max={120}
                  value={filter.umurMax}
                  onChange={(event) => setValue("umurMax", event.target.value)}
                  placeholder="90"
                />
              </div>
              <Facet
                label="Status Perkawinan"
                value={filter.statusKawin}
                options={STATUS_KAWIN_OPTIONS}
                placeholder="Semua status perkawinan"
                onChange={(value) => setValue("statusKawin", value)}
              />
              <Facet
                label="Agama"
                value={filter.agama}
                options={AGAMA_OPTIONS}
                placeholder="Semua agama"
                onChange={(value) => setValue("agama", value)}
              />
              <Facet
                label="Pendidikan Dalam KK"
                value={filter.pendidikan}
                options={PENDIDIKAN_OPTIONS}
                placeholder="Semua pendidikan"
                onChange={(value) => setValue("pendidikan", value)}
              />
              <Facet
                label="Pendidikan Sedang Ditempuh"
                value={filter.pendidikanSedangDitempuh}
                options={PENDIDIKAN_SEDANG_OPTIONS}
                placeholder="Semua pendidikan"
                allowBelum
                onChange={(value) => setValue("pendidikanSedangDitempuh", value)}
              />
              <Facet
                label="Pekerjaan"
                value={filter.pekerjaan}
                options={PEKERJAAN_OPTIONS}
                placeholder="Semua pekerjaan"
                onChange={(value) => setValue("pekerjaan", value)}
              />
              <Facet
                label="Status Penduduk"
                value={filter.statusPenduduk}
                options={STATUS_PENDUDUK_OPTIONS}
                optionLabels={STATUS_PENDUDUK_LABEL}
                placeholder="Semua status penduduk"
                onChange={(value) => setValue("statusPenduduk", value)}
              />
              <Facet
                label="Kepemilikan Tag ID Card"
                value={filter.punyaTagIdCard}
                options={PUNYA_TIDAK_OPTIONS}
                placeholder="Semua"
                onChange={(value) => setValue("punyaTagIdCard", value)}
              />
            </div>
          )}

          <p className="text-xs text-muted-foreground">
            {ringkasan?.sudahKawin ?? 0} warga tercatat sudah menikah; kriteria umur
            dihitung per {tanggalPendek(acuan)}.
          </p>

          <div className="overflow-x-auto">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead className="w-12">No</TableHead>
                  <TableHead>NIK</TableHead>
                  <TableHead className="hidden lg:table-cell">Tag ID Card</TableHead>
                  <TableHead>Nama</TableHead>
                  <TableHead className="hidden lg:table-cell">No. KK</TableHead>
                  <TableHead>Jenis Kelamin</TableHead>
                  <TableHead className="hidden lg:table-cell">Alamat</TableHead>
                  <TableHead className="hidden xl:table-cell">Dusun</TableHead>
                  <TableHead className="hidden xl:table-cell">RW</TableHead>
                  <TableHead>RT</TableHead>
                  <TableHead className="hidden xl:table-cell">Pendidikan Dalam KK</TableHead>
                  <TableHead>Umur Pada {tanggalPendek(acuan)}</TableHead>
                  <TableHead className="hidden xl:table-cell">Pekerjaan</TableHead>
                  <TableHead>Kawin</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {isLoading ? (
                  <TableRow>
                    <TableCell
                      colSpan={14}
                      className="py-10 text-center text-muted-foreground"
                    >
                      Memuat data…
                    </TableCell>
                  </TableRow>
                ) : tersaring.length ? (
                  tersaring.map((row, index) => {
                    const rantai = rantaiWilayah(row.rt?.id);
                    return (
                      <TableRow key={row.id}>
                        <TableCell className="text-xs text-muted-foreground">
                          {index + 1}
                        </TableCell>
                        <TableCell className="font-mono text-xs">{row.nik}</TableCell>
                        <TableCell className="hidden lg:table-cell font-mono text-xs">
                          {row.tagIdCard ?? "-"}
                        </TableCell>
                        <TableCell className="font-medium">{row.nama}</TableCell>
                        <TableCell className="hidden lg:table-cell font-mono text-xs">
                          {row.keluarga?.noKk ?? "-"}
                        </TableCell>
                        <TableCell>{labelGender(row.jenisKelamin)}</TableCell>
                        <TableCell className="hidden lg:table-cell max-w-[220px] truncate">
                          {row.alamat ?? "-"}
                        </TableCell>
                        <TableCell className="hidden xl:table-cell">
                          {rantai.dusun || "-"}
                        </TableCell>
                        <TableCell className="hidden xl:table-cell">
                          {rantai.rw || "-"}
                        </TableCell>
                        <TableCell>{rantai.rt || row.rt?.nama || "-"}</TableCell>
                        <TableCell className="hidden xl:table-cell">
                          {row.pendidikan ?? "-"}
                        </TableCell>
                        <TableCell>{row.umur ?? "-"}</TableCell>
                        <TableCell className="hidden xl:table-cell">
                          {row.pekerjaan ?? "-"}
                        </TableCell>
                        <TableCell>{row.statusKawin ?? "-"}</TableCell>
                      </TableRow>
                    );
                  })
                ) : (
                  <TableRow>
                    <TableCell
                      colSpan={14}
                      className="py-12 text-center text-muted-foreground"
                    >
                      Tidak ada calon pemilih untuk kriteria ini.
                    </TableCell>
                  </TableRow>
                )}
              </TableBody>
            </Table>
          </div>

          {daftar.length >= 1000 && (
            <p className="text-xs text-muted-foreground">
              Menampilkan maksimal 1.000 calon pemilih. Persempit pencarian bila
              diperlukan.
            </p>
          )}
        </CardContent>
      </Card>
    </div>
  );
}

function Facet({
  label,
  value,
  options,
  placeholder,
  onChange,
  allowBelum,
  optionLabels,
}: {
  label: string;
  value: string;
  options: string[];
  placeholder: string;
  onChange: (value: string) => void;
  allowBelum?: boolean;
  optionLabels?: Record<string, string>;
}) {
  return (
    <div className="space-y-1.5">
      <Label>{label}</Label>
      <Select value={value} onChange={(event) => onChange(event.target.value)}>
        <option value="">{placeholder}</option>
        {allowBelum ? <option value="BELUM">Belum diisi</option> : null}
        {options.map((item) => (
          <option key={item} value={item}>
            {optionLabels?.[item] ?? item}
          </option>
        ))}
      </Select>
    </div>
  );
}
