"use client";

import { useMemo, useState } from "react";
import useSWR from "swr";
import {
  BarChart3,
  Eraser,
  Handshake,
  Home,
  MapPin,
  Search,
  Users,
} from "lucide-react";
import dynamic from "next/dynamic";
import { fetcher } from "@/lib/api";
import type { Keluarga, Paginated, Penduduk } from "@/lib/types";
import { PageHeader } from "@/components/page-header";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  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 { formatNumber } from "@/lib/utils";

const PemetaanMap = dynamic(() => import("@/components/admin/pemetaan-map"), {
  ssr: false,
  loading: () => <div className="h-[420px] w-full animate-pulse rounded-lg bg-muted" />,
});

interface Ringkasan {
  total: number;
  lakiLaki: number;
  perempuan: number;
  keluarga: number;
}

interface TitikLokasi {
  id: number;
  nama: string;
  kategori: string | null;
  lat: number | string;
  lng: number | string;
  keterangan: string | null;
}

interface Program {
  id: number;
  nama: string;
  aktif: boolean;
  _count?: { peserta?: number };
}

interface Wilayah {
  id: number;
  nama: string;
  level: string;
}

interface Pengaturan {
  kunci: string;
  nilai: string | null;
}

type Lapisan = { penduduk: boolean; keluarga: boolean; rumahTangga: boolean };

type Pencarian = {
  q: string;
  statusPenduduk: string;
  jenisKelamin: string;
  dusunId: string;
};

const LAPISAN_AWAL: Lapisan = { penduduk: true, keluarga: false, rumahTangga: false };
const PENCARIAN_AWAL: Pencarian = { q: "", statusPenduduk: "", jenisKelamin: "", dusunId: "" };

function dusunPenduduk(row: Penduduk) {
  return row.rt?.parent?.parent?.nama ?? row.rt?.parent?.nama ?? "-";
}

export default function PemetaanPage() {
  const [lapisan, setLapisan] = useState<Lapisan>(LAPISAN_AWAL);
  const [pencarian, setPencarian] = useState<Pencarian>(PENCARIAN_AWAL);
  const [spesifikOpen, setSpesifikOpen] = useState(false);
  const [spesifik, setSpesifik] = useState<Pencarian>(PENCARIAN_AWAL);
  const [statistikOpen, setStatistikOpen] = useState(false);
  const [bantuanOpen, setBantuanOpen] = useState(false);

  const { data: ringkasan } = useSWR<Ringkasan>("/penduduk/ringkasan", fetcher);
  const { data: wilayah } = useSWR<Wilayah[]>("/wilayah", fetcher);
  const { data: lokasi } = useSWR<TitikLokasi[]>("/master/lokasi-peta", fetcher);
  const { data: program } = useSWR<Program[]>("/master/program-bantuan", fetcher);
  const { data: pengaturan } = useSWR<Pengaturan[]>("/pengaturan-sistem?grup=peta", fetcher);

  const params = new URLSearchParams({ limit: "200" });
  if (pencarian.q) params.set("q", pencarian.q);
  if (pencarian.statusPenduduk) params.set("statusPenduduk", pencarian.statusPenduduk);
  if (pencarian.jenisKelamin) params.set("jenisKelamin", pencarian.jenisKelamin);
  if (pencarian.dusunId) params.set("dusunId", pencarian.dusunId);

  const { data: penduduk, isLoading: memuatPenduduk } = useSWR<Paginated<Penduduk>>(
    lapisan.penduduk ? `/penduduk?${params.toString()}` : null,
    fetcher,
  );
  const { data: keluarga } = useSWR<Paginated<Keluarga>>(
    lapisan.keluarga ? "/keluarga?limit=200" : null,
    fetcher,
  );
  const { data: rumahTangga } = useSWR<Record<string, unknown>[]>(
    lapisan.rumahTangga ? "/master/dtks" : null,
    fetcher,
  );

  const daftarDusun = useMemo(
    () => (wilayah ?? []).filter((row) => row.level === "DUSUN"),
    [wilayah],
  );

  const nilai = useMemo(() => {
    const map = new Map((pengaturan ?? []).map((row) => [row.kunci, row.nilai ?? ""]));
    return (kunci: string, cadangan: string) => map.get(kunci) || cadangan;
  }, [pengaturan]);

  const pusat: [number, number] = [
    Number(nilai("peta.lat", "-7.6212")) || -7.6212,
    Number(nilai("peta.lng", "108.8125")) || 108.8125,
  ];
  const zoom = Number(nilai("peta.zoom", "14")) || 14;
  const jenis = nilai("peta.jenis", "osm");

  const titik = useMemo(() => {
    const kata = pencarian.q.trim().toLowerCase();
    return (lokasi ?? []).filter((row) => {
      if (!kata) return true;
      return [row.nama, row.kategori ?? "", row.keterangan ?? ""]
        .some((value) => value.toLowerCase().includes(kata));
    });
  }, [lokasi, pencarian.q]);

  const totalPenduduk = penduduk?.meta?.total ?? 0;

  function ubahLapisan(kunci: keyof Lapisan) {
    setLapisan((current) => ({ ...current, [kunci]: !current[kunci] }));
  }

  function bersihkan() {
    setPencarian(PENCARIAN_AWAL);
    setSpesifik(PENCARIAN_AWAL);
  }

  return (
    <div className="animate-fade-in space-y-6">
      <PageHeader
        title="Pemetaan"
        description="Peta lokasi desa, sebaran penduduk, keluarga, dan rumah tangga."
      />

      <div className="grid gap-5 lg:grid-cols-[1fr_320px]">
        <Card>
          <CardHeader className="flex-row items-center justify-between space-y-0">
            <CardTitle className="text-base">Peta {titik.length} lokasi</CardTitle>
            <span className="text-xs text-muted-foreground">
              {totalPenduduk ? `${formatNumber(totalPenduduk)} penduduk sesuai filter` : ""}
            </span>
          </CardHeader>
          <CardContent>
            <PemetaanMap titik={titik} pusat={pusat} zoom={zoom} layerId={jenis} />
            {!titik.length && (
              <p className="mt-2 text-sm text-muted-foreground">
                Belum ada titik lokasi pada peta. Tambahkan melalui menu Pertanahan atau
                pengaturan peta.
              </p>
            )}
          </CardContent>
        </Card>

        <div className="space-y-4">
          <Card>
            <CardHeader>
              <CardTitle className="text-base">Filter</CardTitle>
            </CardHeader>
            <CardContent className="space-y-3">
              <div className="space-y-1.5">
                <Label htmlFor="cari-peta">Cari</Label>
                <div className="relative">
                  <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                  <Input
                    id="cari-peta"
                    className="pl-9"
                    value={pencarian.q}
                    onChange={(event) =>
                      setPencarian({ ...pencarian, q: event.target.value })
                    }
                    placeholder="Nama, NIK, atau lokasi"
                  />
                </div>
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="status-peta">Status Penduduk</Label>
                <Select
                  id="status-peta"
                  value={pencarian.statusPenduduk}
                  onChange={(event) =>
                    setPencarian({ ...pencarian, statusPenduduk: event.target.value })
                  }
                >
                  <option value="">Semua status</option>
                  <option value="TETAP">Tetap</option>
                  <option value="SEMENTARA">Sementara</option>
                </Select>
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="jk-peta">Jenis Kelamin</Label>
                <Select
                  id="jk-peta"
                  value={pencarian.jenisKelamin}
                  onChange={(event) =>
                    setPencarian({ ...pencarian, jenisKelamin: event.target.value })
                  }
                >
                  <option value="">Semua</option>
                  <option value="L">Laki-laki</option>
                  <option value="P">Perempuan</option>
                </Select>
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="dusun-peta">Dusun</Label>
                <Select
                  id="dusun-peta"
                  value={pencarian.dusunId}
                  onChange={(event) =>
                    setPencarian({ ...pencarian, dusunId: event.target.value })
                  }
                >
                  <option value="">Semua dusun</option>
                  {daftarDusun.map((row) => (
                    <option key={row.id} value={row.id}>
                      {row.nama}
                    </option>
                  ))}
                </Select>
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle className="text-base">Lapisan</CardTitle>
            </CardHeader>
            <CardContent className="space-y-2 text-sm">
              {(
                [
                  ["penduduk", "Penduduk", Users],
                  ["keluarga", "Keluarga", Home],
                  ["rumahTangga", "Rumah Tangga", MapPin],
                ] as const
              ).map(([kunci, label, Icon]) => (
                <label key={kunci} className="flex cursor-pointer items-center gap-2">
                  <input
                    type="checkbox"
                    checked={lapisan[kunci]}
                    onChange={() => ubahLapisan(kunci)}
                    className="h-4 w-4 accent-[hsl(var(--primary))]"
                  />
                  <Icon className="h-4 w-4 text-muted-foreground" /> {label}
                </label>
              ))}
              <div className="flex flex-wrap gap-2 pt-2">
                <Button variant="outline" size="sm" onClick={() => setStatistikOpen(true)}>
                  <BarChart3 className="h-4 w-4" /> Statistik Penduduk
                </Button>
                <Button variant="outline" size="sm" onClick={() => setBantuanOpen(true)}>
                  <Handshake className="h-4 w-4" /> Statistik Bantuan
                </Button>
                <Button variant="outline" size="sm" onClick={() => setSpesifikOpen(true)}>
                  <Search className="h-4 w-4" /> Pencarian Spesifik
                </Button>
                <Button variant="ghost" size="sm" onClick={bersihkan}>
                  <Eraser className="h-4 w-4" /> Bersihkan
                </Button>
              </div>
            </CardContent>
          </Card>
        </div>
      </div>

      {lapisan.penduduk && (
        <Card>
          <CardHeader>
            <CardTitle className="text-base">
              Penduduk ({formatNumber(totalPenduduk)})
            </CardTitle>
          </CardHeader>
          <CardContent className="max-h-[420px] overflow-auto">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Nama</TableHead>
                  <TableHead>NIK</TableHead>
                  <TableHead>JK</TableHead>
                  <TableHead>Dusun</TableHead>
                  <TableHead>Status</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {(penduduk?.data ?? []).map((row) => (
                  <TableRow key={row.id}>
                    <TableCell className="font-medium">{row.nama}</TableCell>
                    <TableCell className="font-mono text-xs">{row.nik}</TableCell>
                    <TableCell>{row.jenisKelamin === "L" ? "L" : "P"}</TableCell>
                    <TableCell>{dusunPenduduk(row)}</TableCell>
                    <TableCell>{row.statusPenduduk || "-"}</TableCell>
                  </TableRow>
                ))}
                {!memuatPenduduk && !penduduk?.data.length && (
                  <TableRow>
                    <TableCell colSpan={5} className="py-8 text-center text-muted-foreground">
                      Tidak ada penduduk yang sesuai filter.
                    </TableCell>
                  </TableRow>
                )}
              </TableBody>
            </Table>
          </CardContent>
        </Card>
      )}

      {lapisan.keluarga && (
        <Card>
          <CardHeader>
            <CardTitle className="text-base">
              Keluarga ({formatNumber(keluarga?.meta?.total ?? 0)})
            </CardTitle>
          </CardHeader>
          <CardContent className="max-h-[320px] overflow-auto">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>No. KK</TableHead>
                  <TableHead>Kepala Keluarga</TableHead>
                  <TableHead>Alamat</TableHead>
                  <TableHead>Anggota</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {(keluarga?.data ?? []).map((row) => (
                  <TableRow key={row.id}>
                    <TableCell className="font-mono text-xs">{row.noKk}</TableCell>
                    <TableCell>{row.kepalaKeluarga?.nama ?? "-"}</TableCell>
                    <TableCell>{row.alamat ?? "-"}</TableCell>
                    <TableCell>{row._count?.anggota ?? 0}</TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </CardContent>
        </Card>
      )}

      {lapisan.rumahTangga && (
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Rumah Tangga</CardTitle>
          </CardHeader>
          <CardContent className="max-h-[320px] overflow-auto">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Nomor KK</TableHead>
                  <TableHead>Kepala Keluarga</TableHead>
                  <TableHead>Kepala Rumah Tangga</TableHead>
                  <TableHead>Anggota</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {(rumahTangga ?? []).map((row) => (
                  <TableRow key={String(row.id)}>
                    <TableCell className="font-mono text-xs">
                      {String(row.nomorKk ?? "-")}
                    </TableCell>
                    <TableCell>{String(row.kepalaKeluarga ?? "-")}</TableCell>
                    <TableCell>
                      {String(row.kepalaRumahTangga ?? row.kepalaKeluarga ?? "-")}
                    </TableCell>
                    <TableCell>{String(row.jumlahAnggota ?? 0)}</TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </CardContent>
        </Card>
      )}

      <Dialog open={statistikOpen} onOpenChange={setStatistikOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Statistik Penduduk</DialogTitle>
          </DialogHeader>
          <div className="space-y-2 text-sm">
            <div className="flex justify-between border-b pb-2">
              <span>Total penduduk</span>
              <strong>{formatNumber(ringkasan?.total ?? 0)}</strong>
            </div>
            <div className="flex justify-between border-b pb-2">
              <span>Laki-laki</span>
              <strong>{formatNumber(ringkasan?.lakiLaki ?? 0)}</strong>
            </div>
            <div className="flex justify-between border-b pb-2">
              <span>Perempuan</span>
              <strong>{formatNumber(ringkasan?.perempuan ?? 0)}</strong>
            </div>
            <div className="flex justify-between border-b pb-2">
              <span>Kepala keluarga</span>
              <strong>{formatNumber(ringkasan?.keluarga ?? 0)}</strong>
            </div>
            <div className="flex justify-between">
              <span>Sesuai filter peta</span>
              <strong>{formatNumber(totalPenduduk)}</strong>
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setStatistikOpen(false)}>
              Tutup
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={bantuanOpen} onOpenChange={setBantuanOpen}>
        <DialogContent className="max-h-[80vh] max-w-lg overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Statistik Bantuan</DialogTitle>
          </DialogHeader>
          <div className="space-y-2">
            {(program ?? []).map((row) => (
              <div
                key={row.id}
                className="flex items-center justify-between rounded-lg border p-3 text-sm"
              >
                <div>
                  <div className="font-medium">{row.nama}</div>
                  <div className="text-xs text-muted-foreground">
                    {formatNumber(row._count?.peserta ?? 0)} peserta
                  </div>
                </div>
                <Badge variant={row.aktif ? "success" : "secondary"}>
                  {row.aktif ? "Aktif" : "Tidak Aktif"}
                </Badge>
              </div>
            ))}
            {!program?.length && (
              <p className="py-6 text-center text-sm text-muted-foreground">
                Belum ada program bantuan.
              </p>
            )}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setBantuanOpen(false)}>
              Tutup
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={spesifikOpen} onOpenChange={setSpesifikOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Pencarian Spesifik</DialogTitle>
          </DialogHeader>
          <div className="space-y-3">
            <div className="space-y-1.5">
              <Label htmlFor="spesifik-q">Nama atau NIK</Label>
              <Input
                id="spesifik-q"
                value={spesifik.q}
                onChange={(event) => setSpesifik({ ...spesifik, q: event.target.value })}
              />
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="spesifik-status">Status Penduduk</Label>
              <Select
                id="spesifik-status"
                value={spesifik.statusPenduduk}
                onChange={(event) =>
                  setSpesifik({ ...spesifik, statusPenduduk: event.target.value })
                }
              >
                <option value="">Semua status</option>
                <option value="TETAP">Tetap</option>
                <option value="SEMENTARA">Sementara</option>
              </Select>
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="spesifik-jk">Jenis Kelamin</Label>
              <Select
                id="spesifik-jk"
                value={spesifik.jenisKelamin}
                onChange={(event) =>
                  setSpesifik({ ...spesifik, jenisKelamin: event.target.value })
                }
              >
                <option value="">Semua</option>
                <option value="L">Laki-laki</option>
                <option value="P">Perempuan</option>
              </Select>
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="spesifik-dusun">Dusun</Label>
              <Select
                id="spesifik-dusun"
                value={spesifik.dusunId}
                onChange={(event) =>
                  setSpesifik({ ...spesifik, dusunId: event.target.value })
                }
              >
                <option value="">Semua dusun</option>
                {daftarDusun.map((row) => (
                  <option key={row.id} value={row.id}>
                    {row.nama}
                  </option>
                ))}
              </Select>
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setSpesifikOpen(false)}>
              Batal
            </Button>
            <Button
              onClick={() => {
                setPencarian(spesifik);
                setLapisan((current) => ({ ...current, penduduk: true }));
                setSpesifikOpen(false);
              }}
            >
              Terapkan
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
