"use client";

import { useMemo, useState } from "react";
import useSWR from "swr";
import { DoorOpen, FilePenLine, ListChecks, Plus, Printer, Trash2 } from "lucide-react";
import { toast } from "sonner";
import type { AlasanKeluar } 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 { Badge } from "@/components/ui/badge";
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 {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { formatNumber } from "@/lib/utils";

type FormState = { alasan: string; keterangan: string; aktif: boolean };

const emptyForm: FormState = { alasan: "", keterangan: "", aktif: true };

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

  const { data, isLoading, mutate } = useSWR<AlasanKeluar[]>(
    "/alasan-keluar",
    fetcher,
  );
  const daftar = data ?? [];

  const [formOpen, setFormOpen] = useState(false);
  const [editing, setEditing] = useState<AlasanKeluar | null>(null);
  const [form, setForm] = useState<FormState>(emptyForm);
  const [saving, setSaving] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<AlasanKeluar | null>(null);
  const [deleting, setDeleting] = useState(false);
  const [selected, setSelected] = useState<number[]>([]);
  const [konfirmasiTerpilih, setKonfirmasiTerpilih] = useState(false);

  const ringkasan = useMemo(() => {
    const aktif = daftar.filter((item) => item.aktif).length;
    return { total: daftar.length, aktif, nonaktif: daftar.length - aktif };
  }, [daftar]);

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

  function openEdit(item: AlasanKeluar) {
    setEditing(item);
    setForm({
      alasan: item.alasan,
      keterangan: item.keterangan ?? "",
      aktif: item.aktif,
    });
    setFormOpen(true);
  }

  async function save(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSaving(true);
    try {
      const payload = {
        alasan: form.alasan,
        aktif: form.aktif,
        ...(form.keterangan ? { keterangan: form.keterangan } : { keterangan: "" }),
      };
      if (editing) {
        await apiSend(`/alasan-keluar/${editing.id}`, "PATCH", payload);
        toast.success("Alasan keluar diperbarui");
      } else {
        await apiSend("/alasan-keluar", "POST", payload);
        toast.success("Alasan keluar 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(`/alasan-keluar/${deleteTarget.id}`, "DELETE");
      toast.success("Alasan keluar 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(`/alasan-keluar/${id}`, "DELETE")),
    );
    const terhapus = hasil.filter((item) => item.status === "fulfilled").length;
    if (terhapus) toast.success(`${terhapus} alasan keluar dihapus`);
    const gagal = hasil.length - terhapus;
    if (gagal) toast.error(`${gagal} alasan keluar gagal dihapus`);
    setSelected([]);
    setKonfirmasiTerpilih(false);
    await mutate();
    setDeleting(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="Alasan Keluar"
          description="Daftar alasan resmi perangkat desa meninggalkan kantor pada jam kerja."
          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 onClick={openCreate}>
                  <Plus className="h-4 w-4" />
                  Tambah Alasan
                </Button>
              )}
            </div>
          }
        />
      </div>

      <KopLaporan title="Daftar Alasan Keluar Perangkat Desa" />

      {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="Total alasan"
              value={formatNumber(ringkasan.total)}
              hint="Alasan tercatat"
              icon={ListChecks}
            />
            <StatCard
              title="Alasan aktif"
              value={formatNumber(ringkasan.aktif)}
              hint="Dapat dipilih perangkat"
              icon={DoorOpen}
              tone="sky"
            />
            <StatCard
              title="Nonaktif"
              value={formatNumber(ringkasan.nonaktif)}
              hint="Tidak ditampilkan"
              icon={DoorOpen}
              tone="amber"
            />
          </div>

          <Card>
            <CardContent className="space-y-4 p-4">
              {canMutate && selected.length > 0 && (
                <div className="flex justify-end">
                  <Button variant="outline" size="sm" onClick={() => setKonfirmasiTerpilih(true)}>
                    <Trash2 className="h-4 w-4" />
                    Hapus ({selected.length})
                  </Button>
                </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 alasan"
                            className="h-4 w-4 accent-[hsl(var(--primary))]"
                          />
                        </TableHead>
                      )}
                      <TableHead className="w-14">No</TableHead>
                      <TableHead className="w-24">Aksi</TableHead>
                      <TableHead>Alasan</TableHead>
                      <TableHead>Keterangan</TableHead>
                      <TableHead>Status</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.alasan}`}
                              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 alasan keluar"
                              >
                                <FilePenLine className="h-4 w-4" />
                              </Button>
                              <Button
                                variant="ghost"
                                size="icon"
                                onClick={() => setDeleteTarget(item)}
                                aria-label="Hapus alasan keluar"
                              >
                                <Trash2 className="h-4 w-4 text-destructive" />
                              </Button>
                            </div>
                          )}
                        </TableCell>
                        <TableCell className="font-medium">{item.alasan}</TableCell>
                        <TableCell className="max-w-[420px] text-muted-foreground">
                          {item.keterangan || "-"}
                        </TableCell>
                        <TableCell>
                          <Badge variant={item.aktif ? "success" : "secondary"}>
                            {item.aktif ? "Aktif" : "Nonaktif"}
                          </Badge>
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              ) : (
                <p className="py-10 text-center text-sm text-muted-foreground">
                  Belum ada alasan keluar yang tercatat.
                </p>
              )}
            </CardContent>
          </Card>
        </>
      )}

      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>
              {editing ? "Ubah Alasan Keluar" : "Tambah Alasan Keluar"}
            </DialogTitle>
            <DialogDescription>
              Alasan ini digunakan saat perangkat meninggalkan kantor pada jam kerja.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={save} className="space-y-4">
            <div className="space-y-1.5">
              <Label htmlFor="alasan">Alasan</Label>
              <Input
                id="alasan"
                value={form.alasan}
                onChange={(event) => setForm({ ...form, alasan: event.target.value })}
                placeholder="Contoh: Dinas Luar"
                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="Opsional"
              />
            </div>
            <label className="flex items-center gap-2 text-sm">
              <input
                type="checkbox"
                checked={form.aktif}
                onChange={(event) => setForm({ ...form, aktif: event.target.checked })}
                className="h-4 w-4 accent-primary"
              />
              Alasan aktif dan dapat dipilih
            </label>
            <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 alasan keluar?</DialogTitle>
            <DialogDescription>
              Alasan {deleteTarget?.alasan} 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={konfirmasiTerpilih} onOpenChange={setKonfirmasiTerpilih}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus {selected.length} alasan keluar?</DialogTitle>
            <DialogDescription>
              Alasan yang terpilih akan dihapus permanen dari daftar.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setKonfirmasiTerpilih(false)}>
              Batal
            </Button>
            <Button variant="destructive" onClick={hapusSemuaTerpilih} disabled={deleting}>
              {deleting ? "Menghapus..." : "Hapus"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
