"use client";

import { useMemo, useState } from "react";
import useSWR from "swr";
import {
  CalendarDays,
  CalendarOff,
  Download,
  FilePenLine,
  Plus,
  Printer,
  Trash2,
} from "lucide-react";
import { toast } from "sonner";
import type { HariLibur } from "@/lib/types";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import { useSession } from "@/lib/use-session";
import { PageHeader, StatCard } from "@/components/page-header";
import { KopLaporan } from "@/components/admin/kop-laporan";
import { PengaturanKehadiran } from "@/components/admin/pengaturan-kehadiran";
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 { formatDateShort, formatNumber } from "@/lib/utils";

const TAHUN_INI = new Date().getFullYear();
const TAHUN_OPTIONS = Array.from({ length: 5 }, (_, index) => TAHUN_INI - 2 + index);

function namaHari(value: string) {
  return new Intl.DateTimeFormat("id-ID", { weekday: "long" }).format(new Date(value));
}

type FormState = { tanggal: string; keterangan: string };

const emptyForm: FormState = { tanggal: "", keterangan: "" };

export default function HariLiburPage() {
  const { user } = useSession();
  const canMutate = user?.role === "ADMIN" || user?.role === "OPERATOR";

  const [tahun, setTahun] = useState(String(TAHUN_INI));
  const { data, isLoading, mutate } = useSWR<HariLibur[]>(
    `/hari-libur?tahun=${tahun}`,
    fetcher,
  );
  const daftar = data ?? [];

  const [formOpen, setFormOpen] = useState(false);
  const [editing, setEditing] = useState<HariLibur | null>(null);
  const [form, setForm] = useState<FormState>(emptyForm);
  const [saving, setSaving] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<HariLibur | null>(null);
  const [deleting, setDeleting] = useState(false);
  const [selected, setSelected] = useState<number[]>([]);
  const [hapusTerpilih, setHapusTerpilih] = useState(false);
  const [imporOpen, setImporOpen] = useState(false);
  const [imporTahun, setImporTahun] = useState(tahun);
  const [imporLoading, setImporLoading] = useState(false);

  const ringkasan = useMemo(() => {
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const bulanIni = today.getMonth();
    const tahunIni = today.getFullYear();
    const mendatang = daftar
      .map((item) => new Date(item.tanggal))
      .filter((tanggal) => tanggal >= today)
      .sort((a, b) => a.getTime() - b.getTime());
    return {
      total: daftar.length,
      bulanIni: daftar.filter((item) => {
        const tanggal = new Date(item.tanggal);
        return (
          tanggal.getUTCFullYear() === tahunIni && tanggal.getUTCMonth() === bulanIni
        );
      }).length,
      terdekat: mendatang[0] ?? null,
    };
  }, [daftar]);

  function openCreate() {
    setEditing(null);
    setForm(emptyForm);
    setFormOpen(true);
  }

  function openEdit(item: HariLibur) {
    setEditing(item);
    setForm({ tanggal: item.tanggal.slice(0, 10), keterangan: item.keterangan });
    setFormOpen(true);
  }

  async function save(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSaving(true);
    try {
      if (editing) {
        await apiSend(`/hari-libur/${editing.id}`, "PATCH", form);
        toast.success("Hari libur diperbarui");
      } else {
        await apiSend("/hari-libur", "POST", form);
        toast.success("Hari libur ditambahkan");
      }
      setFormOpen(false);
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyimpan data");
    } finally {
      setSaving(false);
    }
  }

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

  async function hapusSemuaTerpilih() {
    if (!selected.length) return;
    setDeleting(true);
    const hasil = await Promise.allSettled(
      selected.map((id) => apiSend(`/hari-libur/${id}`, "DELETE")),
    );
    const terhapus = hasil.filter((item) => item.status === "fulfilled").length;
    if (terhapus) toast.success(`${terhapus} hari libur dihapus`);
    const gagal = hasil.length - terhapus;
    if (gagal) toast.error(`${gagal} hari libur gagal dihapus`);
    setSelected([]);
    setHapusTerpilih(false);
    await mutate();
    setDeleting(false);
  }

  async function jalankanImpor() {
    setImporLoading(true);
    try {
      const hasil = await apiSend<{ ditambahkan: number; dilewati: number }>(
        "/hari-libur/impor",
        "POST",
        { tahun: Number(imporTahun) },
      );
      toast.success(
        `${hasil.ditambahkan} libur nasional diimpor${
          hasil.dilewati ? `, ${hasil.dilewati} tanggal dilewati` : ""
        }`,
      );
      setImporOpen(false);
      setTahun(imporTahun);
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal mengimpor hari libur");
    } finally {
      setImporLoading(false);
    }
  }

  function toggleSemua() {
    setSelected(selected.length === daftar.length ? [] : daftar.map((item) => item.id));
  }

  function toggleSatu(id: number) {
    setSelected((current) =>
      current.includes(id) ? current.filter((item) => item !== id) : [...current, id],
    );
  }

  return (
    <div className="animate-fade-in space-y-6">
      <div className="no-print">
        <PageHeader
          title="Hari Libur"
          description="Daftar hari libur nasional dan cuti bersama yang memengaruhi layanan desa."
          action={
            <div className="flex flex-wrap gap-2">
              <Button variant="outline" onClick={() => window.print()}>
                <Printer className="h-4 w-4" />
                Cetak
              </Button>
              <PengaturanKehadiran />
              {canMutate && (
                <>
                  <Button variant="outline" onClick={() => setImporOpen(true)}>
                    <Download className="h-4 w-4" />
                    Impor
                  </Button>
                  <Button onClick={openCreate}>
                    <Plus className="h-4 w-4" />
                    Tambah Hari Libur
                  </Button>
                </>
              )}
            </div>
          }
        />
      </div>

      <KopLaporan title="Daftar Hari Libur" subtitle={`Tahun ${tahun}`} />

      {isLoading || !data ? (
        <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
          {Array.from({ length: 3 }).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-3">
            <StatCard
              title={`Libur ${tahun}`}
              value={formatNumber(ringkasan.total)}
              hint="Hari libur tercatat"
              icon={CalendarOff}
            />
            <StatCard
              title="Bulan berjalan"
              value={formatNumber(ringkasan.bulanIni)}
              hint="Hari libur bulan ini"
              icon={CalendarDays}
              tone="sky"
            />
            <StatCard
              title="Libur terdekat"
              value={
                ringkasan.terdekat ? formatDateShort(ringkasan.terdekat.toISOString()) : "-"
              }
              hint="Tanggal libur berikutnya"
              icon={CalendarDays}
              tone="violet"
            />
          </div>

          <Card>
            <CardContent className="space-y-4 p-4">
              <div className="no-print flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                <p className="text-sm text-muted-foreground">
                  Menampilkan hari libur tahun {tahun}.
                </p>
                <div className="flex items-center gap-2">
                  {canMutate && selected.length > 0 && (
                    <Button variant="outline" size="sm" onClick={() => setHapusTerpilih(true)}>
                      <Trash2 className="h-4 w-4" />
                      Hapus ({selected.length})
                    </Button>
                  )}
                  <Select
                    value={tahun}
                    onChange={(event) => setTahun(event.target.value)}
                    className="sm:w-36"
                  >
                    {TAHUN_OPTIONS.map((option) => (
                      <option key={option} value={option}>
                        Tahun {option}
                      </option>
                    ))}
                  </Select>
                </div>
              </div>

              {daftar.length ? (
                <Table>
                  <TableHeader>
                    <TableRow>
                      {canMutate && (
                        <TableHead className="w-10">
                          <input
                            type="checkbox"
                            checked={selected.length === daftar.length}
                            onChange={toggleSemua}
                            aria-label="Pilih semua hari libur"
                            className="h-4 w-4 accent-[hsl(var(--primary))]"
                          />
                        </TableHead>
                      )}
                      <TableHead className="w-14">No</TableHead>
                      <TableHead className="w-24">Aksi</TableHead>
                      <TableHead>Tanggal</TableHead>
                      <TableHead>Keterangan</TableHead>
                      <TableHead className="hidden md:table-cell">Hari</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {daftar.map((item, index) => (
                      <TableRow key={item.id}>
                        {canMutate && (
                          <TableCell>
                            <input
                              type="checkbox"
                              checked={selected.includes(item.id)}
                              onChange={() => toggleSatu(item.id)}
                              aria-label={`Pilih ${item.keterangan}`}
                              className="h-4 w-4 accent-[hsl(var(--primary))]"
                            />
                          </TableCell>
                        )}
                        <TableCell className="text-muted-foreground">{index + 1}</TableCell>
                        <TableCell>
                          {canMutate && (
                            <div className="flex gap-1">
                              <Button
                                variant="ghost"
                                size="icon"
                                onClick={() => openEdit(item)}
                                aria-label="Ubah hari libur"
                              >
                                <FilePenLine className="h-4 w-4" />
                              </Button>
                              <Button
                                variant="ghost"
                                size="icon"
                                onClick={() => setDeleteTarget(item)}
                                aria-label="Hapus hari libur"
                              >
                                <Trash2 className="h-4 w-4 text-destructive" />
                              </Button>
                            </div>
                          )}
                        </TableCell>
                        <TableCell className="whitespace-nowrap font-medium">
                          {formatDateShort(item.tanggal)}
                        </TableCell>
                        <TableCell>{item.keterangan}</TableCell>
                        <TableCell className="hidden capitalize text-muted-foreground md:table-cell">
                          {namaHari(item.tanggal)}
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              ) : (
                <p className="py-10 text-center text-sm text-muted-foreground">
                  Belum ada hari libur pada tahun {tahun}.
                </p>
              )}
            </CardContent>
          </Card>
        </>
      )}

      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>
              {editing ? "Ubah Hari Libur" : "Tambah Hari Libur"}
            </DialogTitle>
            <DialogDescription>
              Catat tanggal libur beserta keterangannya.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={save} className="space-y-4">
            <div className="space-y-1.5">
              <Label htmlFor="tanggal">Tanggal</Label>
              <Input
                id="tanggal"
                type="date"
                value={form.tanggal}
                onChange={(event) => setForm({ ...form, tanggal: event.target.value })}
                required
              />
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="keterangan">Keterangan</Label>
              <Input
                id="keterangan"
                value={form.keterangan}
                onChange={(event) => setForm({ ...form, keterangan: event.target.value })}
                placeholder="Contoh: Hari Kemerdekaan RI"
                required
              />
            </div>
            <DialogFooter>
              <Button type="button" variant="outline" onClick={() => setFormOpen(false)}>
                Batal
              </Button>
              <Button type="submit" disabled={saving}>
                {saving ? "Menyimpan..." : "Simpan"}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <Dialog open={!!deleteTarget} onOpenChange={(open) => !open && setDeleteTarget(null)}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus hari libur?</DialogTitle>
            <DialogDescription>
              {deleteTarget ? formatDateShort(deleteTarget.tanggal) : ""} —{" "}
              {deleteTarget?.keterangan} akan dihapus permanen.
            </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>

      <Dialog open={hapusTerpilih} onOpenChange={setHapusTerpilih}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus {selected.length} hari libur?</DialogTitle>
            <DialogDescription>
              Tanggal yang terpilih akan dihapus permanen dari daftar hari libur.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setHapusTerpilih(false)}>
              Batal
            </Button>
            <Button variant="destructive" onClick={hapusSemuaTerpilih} disabled={deleting}>
              {deleting ? "Menghapus..." : "Hapus"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={imporOpen} onOpenChange={setImporOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Impor Hari Libur Nasional</DialogTitle>
            <DialogDescription>
              Mengambil kalender libur nasional satu tahun dari sumber resmi. Tanggal
              yang sudah tercatat tidak akan ditumpuk.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-1.5">
            <Label htmlFor="imporTahun">Tahun</Label>
            <Select
              id="imporTahun"
              value={imporTahun}
              onChange={(event) => setImporTahun(event.target.value)}
            >
              {TAHUN_OPTIONS.map((option) => (
                <option key={option} value={String(option)}>
                  Tahun {option}
                </option>
              ))}
            </Select>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setImporOpen(false)}>
              Batal
            </Button>
            <Button onClick={jalankanImpor} disabled={imporLoading}>
              {imporLoading ? "Mengimpor..." : "Impor"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
