"use client";

import { useState } from "react";
import useSWR, { mutate } from "swr";
import {
  Download,
  Home,
  Printer,
  Send,
  Trash2,
  Upload,
  User,
  UserCheck,
  Users,
} from "lucide-react";
import { toast } from "sonner";
import type {
  ArsipLaporanPenduduk,
  DaftarArsipLaporan,
  Desa,
  LaporanKependudukan,
} from "@/lib/types";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import { PageHeader, StatCard } from "@/components/page-header";
import { BarList } from "@/components/charts/bar-list";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } 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 { formatDate, formatNumber, labelGender, labelStatusDasar } from "@/lib/utils";

const LABELS: Record<string, (value: string) => string> = {
  statusDasar: labelStatusDasar,
  jenisKelamin: labelGender,
};

const BULAN = [
  "Januari",
  "Februari",
  "Maret",
  "April",
  "Mei",
  "Juni",
  "Juli",
  "Agustus",
  "September",
  "Oktober",
  "November",
  "Desember",
];

const FORM_KOSONG = {
  judul: "",
  bulan: String(new Date().getMonth() + 1),
  tahun: String(new Date().getFullYear()),
  berkasNama: "",
  berkasData: "",
};

function strip(value: string | null | undefined, prefix: string) {
  if (!value) return "-";
  return value.replace(new RegExp(`^${prefix}\\s+`, "i"), "");
}

export default function LaporanPage() {
  const { data, isLoading } = useSWR<LaporanKependudukan>("/laporan/kependudukan", fetcher);
  const { data: desa } = useSWR<Desa>("/desa", fetcher);
  const [tahun, setTahun] = useState("");
  const { data: arsip, isLoading: arsipLoading } = useSWR<DaftarArsipLaporan>(
    `/laporan/arsip${tahun ? `?tahun=${tahun}` : ""}`,
    fetcher,
  );
  const [terpilih, setTerpilih] = useState<number[]>([]);
  const [dialog, setDialog] = useState(false);
  const [form, setForm] = useState(FORM_KOSONG);
  const [menyimpan, setMenyimpan] = useState(false);

  const namaDesa = strip(desa?.nama, "Desa");
  const kecamatan = strip(desa?.kecamatan, "Kecamatan");
  const kabupaten = strip(desa?.kabupaten, "Kabupaten");

  function toggle(id: number) {
    setTerpilih((sebelum) =>
      sebelum.includes(id) ? sebelum.filter((nilai) => nilai !== id) : [...sebelum, id],
    );
  }

  async function pilihBerkas(event: React.ChangeEvent<HTMLInputElement>) {
    const berkas = event.target.files?.[0];
    if (!berkas) return;
    if (berkas.size > 10 * 1024 * 1024) {
      toast.error("Ukuran berkas maksimal 10 MB");
      event.target.value = "";
      return;
    }
    const dataUrl = await new Promise<string>((resolve, reject) => {
      const pembaca = new FileReader();
      pembaca.onload = () => resolve(String(pembaca.result));
      pembaca.onerror = () => reject(new Error("Gagal membaca berkas"));
      pembaca.readAsDataURL(berkas);
    });
    setForm((sebelum) => ({ ...sebelum, berkasNama: berkas.name, berkasData: dataUrl }));
  }

  async function jalankan(action: () => Promise<unknown>, pesan: string) {
    setMenyimpan(true);
    try {
      await action();
      toast.success(pesan);
      setTerpilih([]);
      await mutate(`/laporan/arsip${tahun ? `?tahun=${tahun}` : ""}`);
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Aksi gagal, coba lagi");
    } finally {
      setMenyimpan(false);
    }
  }

  function simpan() {
    if (!form.judul.trim()) {
      toast.error("Judul laporan wajib diisi");
      return;
    }
    if (!form.berkasData) {
      toast.error("Unggah berkas laporan terlebih dahulu");
      return;
    }
    return jalankan(
      () =>
        apiSend("/laporan/arsip", "POST", {
          judul: form.judul.trim(),
          bulan: Number(form.bulan),
          tahun: Number(form.tahun),
          berkasNama: form.berkasNama,
          berkasData: form.berkasData,
        }),
      "Laporan tersimpan di arsip",
    ).then(() => {
      setDialog(false);
      setForm(FORM_KOSONG);
    });
  }

  function hapus() {
    if (!terpilih.length) {
      toast.error("Pilih laporan yang akan dihapus");
      return;
    }
    if (!window.confirm(`Hapus ${terpilih.length} laporan dari arsip?`)) return;
    return jalankan(
      () => apiSend("/laporan/arsip/hapus", "POST", { ids: terpilih }),
      "Laporan dihapus dari arsip",
    );
  }

  function kirim() {
    if (!terpilih.length) {
      toast.error("Pilih laporan yang akan dikirim");
      return;
    }
    return jalankan(
      () => apiSend("/laporan/arsip/kirim", "POST", { ids: terpilih }),
      "Laporan diterbitkan ke website desa",
    );
  }

  async function bukaBerkas(item: ArsipLaporanPenduduk) {
    try {
      const res = await fetch(`/api/backend/laporan/arsip/${item.id}/berkas`, {
        credentials: "include",
      });
      if (!res.ok) {
        const body = await res.json().catch(() => null);
        toast.error(body?.message ?? "Berkas tidak tersedia");
        return;
      }
      const url = URL.createObjectURL(await res.blob());
      window.open(url, "_blank", "noopener,noreferrer");
      setTimeout(() => URL.revokeObjectURL(url), 60_000);
    } catch {
      toast.error("Gagal membuka berkas");
    }
  }

  return (
    <div className="animate-fade-in space-y-6">
      <div className="no-print">
        <PageHeader
          title="Laporan Penduduk"
          description="Rekapitulasi lengkap data penduduk Desa Mulyadadi menurut jenis kelamin, usia, pendidikan, pekerjaan, agama, dan wilayah, beserta arsip laporan bulanan."
          action={
            <Button onClick={() => window.print()}>
              <Printer className="h-4 w-4" />
              Cetak Laporan
            </Button>
          }
        />
      </div>

      <div className="hidden print:block">
        <div className="border-b-2 border-black pb-2 text-center">
          <p className="text-sm font-semibold uppercase">
            Pemerintah Kabupaten {kabupaten} · Kecamatan {kecamatan}
          </p>
          <p className="text-xl font-bold uppercase">Desa {namaDesa}</p>
          <p className="mt-1 text-sm font-semibold">Laporan Penduduk</p>
          <p className="text-xs">Dicetak {formatDate(new Date())}</p>
        </div>
      </div>

      {arsipLoading || !arsip ? (
        <div className="h-40 animate-pulse rounded-xl bg-muted" />
      ) : (
        <Card className="no-print">
          <CardHeader className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            <div>
              <CardTitle>Arsip Laporan Penduduk</CardTitle>
              <p className="text-sm text-muted-foreground">
                Berkas laporan per periode beserta status pengirimannya ke website desa.
              </p>
            </div>
            <div className="flex flex-wrap items-center gap-2">
              <Select
                aria-label="Saring tahun"
                className="w-40"
                value={tahun}
                onChange={(event) => {
                  setTahun(event.target.value);
                  setTerpilih([]);
                }}
              >
                <option value="">Semua tahun</option>
                {arsip.tahun.map((nilai) => (
                  <option key={nilai} value={nilai}>
                    {nilai}
                  </option>
                ))}
              </Select>
              <Button variant="outline" onClick={hapus} disabled={!terpilih.length || menyimpan}>
                <Trash2 className="h-4 w-4" />
                Hapus
              </Button>
              <Button variant="outline" onClick={kirim} disabled={!terpilih.length || menyimpan}>
                <Send className="h-4 w-4" />
                Kirim Ke Website Desa
              </Button>
              <Button
                onClick={() => {
                  setForm(FORM_KOSONG);
                  setDialog(true);
                }}
              >
                <Upload className="h-4 w-4" />
                Tambah
              </Button>
            </div>
          </CardHeader>
          <CardContent className="p-0 pb-2">
            {arsip.data.length ? (
              <div className="overflow-x-auto">
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead className="w-10">
                        <input
                          type="checkbox"
                          aria-label="Pilih semua laporan"
                          className="h-4 w-4"
                          checked={terpilih.length === arsip.data.length}
                          onChange={(event) =>
                            setTerpilih(event.target.checked ? arsip.data.map((row) => row.id) : [])
                          }
                        />
                      </TableHead>
                      <TableHead className="w-10">No</TableHead>
                      <TableHead>Aksi</TableHead>
                      <TableHead>Judul</TableHead>
                      <TableHead>Bulan</TableHead>
                      <TableHead>Tahun</TableHead>
                      <TableHead>Tanggal Upload</TableHead>
                      <TableHead>Tanggal Kirim</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {arsip.data.map((item, index) => (
                      <TableRow key={item.id}>
                        <TableCell>
                          <input
                            type="checkbox"
                            aria-label={`Pilih ${item.judul}`}
                            className="h-4 w-4"
                            checked={terpilih.includes(item.id)}
                            onChange={() => toggle(item.id)}
                          />
                        </TableCell>
                        <TableCell className="text-muted-foreground">{index + 1}</TableCell>
                        <TableCell>
                          {item.berkas ? (
                            <Button
                              variant="ghost"
                              size="icon"
                              title="Unduh berkas laporan"
                              onClick={() => bukaBerkas(item)}
                            >
                              <Download className="h-4 w-4" />
                            </Button>
                          ) : (
                            <span className="text-xs text-muted-foreground">tanpa berkas</span>
                          )}
                        </TableCell>
                        <TableCell className="font-medium">{item.judul}</TableCell>
                        <TableCell>{BULAN[item.bulan - 1] ?? item.bulan}</TableCell>
                        <TableCell className="tabular-nums">{item.tahun}</TableCell>
                        <TableCell>{formatDate(item.uploadedAt)}</TableCell>
                        <TableCell>
                          {item.sentAt ? (
                            <Badge variant="success">
                              {formatDate(item.sentAt)}
                              <span className="ml-1 opacity-70">#{item.artikelId}</span>
                            </Badge>
                          ) : (
                            <Badge variant="secondary">Belum dikirim</Badge>
                          )}
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              </div>
            ) : (
              <p className="px-5 py-10 text-center text-sm text-muted-foreground">
                Belum ada laporan yang diarsipkan pada {tahun ? `tahun ${tahun}` : "seluruh periode"}.
              </p>
            )}
          </CardContent>
        </Card>
      )}

      <Dialog open={dialog} onOpenChange={setDialog}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Tambah Laporan Penduduk</DialogTitle>
            <DialogDescription>
              Arsipkan berkas laporan bulanan beserta periodenya agar dapat dikirim ke website desa.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <div className="space-y-1.5">
              <Label htmlFor="arsip-judul">Judul</Label>
              <Input
                id="arsip-judul"
                value={form.judul}
                onChange={(event) => setForm({ ...form, judul: event.target.value })}
                placeholder="Laporan Penduduk Desember 2026"
              />
            </div>
            <div className="grid gap-3 sm:grid-cols-2">
              <div className="space-y-1.5">
                <Label htmlFor="arsip-bulan">Bulan</Label>
                <Select
                  id="arsip-bulan"
                  value={form.bulan}
                  onChange={(event) => setForm({ ...form, bulan: event.target.value })}
                >
                  {BULAN.map((nama, index) => (
                    <option key={nama} value={index + 1}>
                      {nama}
                    </option>
                  ))}
                </Select>
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="arsip-tahun">Tahun</Label>
                <Input
                  id="arsip-tahun"
                  type="number"
                  min={2000}
                  max={2100}
                  value={form.tahun}
                  onChange={(event) => setForm({ ...form, tahun: event.target.value })}
                />
              </div>
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="arsip-berkas">Berkas laporan</Label>
              <Input
                id="arsip-berkas"
                type="file"
                accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png"
                onChange={pilihBerkas}
              />
              <p className="text-xs text-muted-foreground">
                {form.berkasNama
                  ? `Terpilih: ${form.berkasNama}`
                  : "PDF, Word, Excel, JPG, atau PNG maksimal 10 MB."}
              </p>
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDialog(false)} disabled={menyimpan}>
              Batal
            </Button>
            <Button onClick={simpan} disabled={menyimpan}>
              {menyimpan ? "Menyimpan…" : "Simpan"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {isLoading || !data ? (
        <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
          {Array.from({ length: 4 }).map((_, index) => (
            <div key={index} className="h-28 animate-pulse rounded-xl bg-muted" />
          ))}
        </div>
      ) : (
        <>
          <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
            <StatCard
              title="Penduduk hidup"
              value={formatNumber(data.ringkasan.penduduk)}
              hint={`${formatNumber(data.ringkasan.keluarga)} kartu keluarga`}
              icon={Users}
            />
            <StatCard
              title="Laki-laki"
              value={formatNumber(data.ringkasan.lakiLaki)}
              icon={User}
              tone="sky"
            />
            <StatCard
              title="Perempuan"
              value={formatNumber(data.ringkasan.perempuan)}
              icon={UserCheck}
              tone="violet"
            />
            <StatCard
              title="Kartu keluarga"
              value={formatNumber(data.ringkasan.keluarga)}
              icon={Home}
              tone="amber"
            />
          </div>

          <div className="grid gap-4 lg:grid-cols-2">
            <Card>
              <CardHeader>
                <CardTitle>Kelompok Umur</CardTitle>
              </CardHeader>
              <CardContent>
                <BarList data={data.byUmur} />
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle>Pendidikan Terakhir</CardTitle>
              </CardHeader>
              <CardContent>
                <BarList data={data.byPendidikan} />
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle>Pekerjaan (10 terbesar)</CardTitle>
              </CardHeader>
              <CardContent>
                <BarList data={data.byPekerjaan} />
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle>Status Perkawinan</CardTitle>
              </CardHeader>
              <CardContent>
                <BarList data={data.byStatusKawin} />
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle>Agama</CardTitle>
              </CardHeader>
              <CardContent>
                <BarList data={data.byAgama} />
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle>Golongan Darah</CardTitle>
              </CardHeader>
              <CardContent>
                <BarList data={data.byGolonganDarah} />
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle>Sebaran Menurut RT</CardTitle>
              </CardHeader>
              <CardContent>
                <BarList data={data.byRt} />
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle>Status Dasar Penduduk</CardTitle>
              </CardHeader>
              <CardContent>
                <BarList data={data.ringkasan.statusDasar} labels={LABELS.statusDasar} />
              </CardContent>
            </Card>
          </div>
        </>
      )}
    </div>
  );
}
