"use client";

import { useEffect, useRef, useState } from "react";
import useSWR from "swr";
import {
  Download,
  FileSpreadsheet,
  Hash,
  Pencil,
  Plus,
  Power,
  Printer,
  Search,
  Tags,
  Trash2,
  Upload,
} from "lucide-react";
import { toast } from "sonner";
import type { KlasifikasiSurat, Paginated, RingkasanKlasifikasi } from "@/lib/types";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import { useSession } from "@/lib/use-session";
import { unduhCsv } from "@/lib/sekretariat";
import { PageHeader, StatCard } from "@/components/page-header";
import { Pagination } from "@/components/pagination";
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 { Select } from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Textarea } from "@/components/ui/textarea";

type FormState = { kode: string; nama: string; uraian: string };

function emptyForm(): FormState {
  return { kode: "", nama: "", uraian: "" };
}

function parseCsv(text: string): string[][] {
  const rows: string[][] = [];
  let row: string[] = [];
  let cell = "";
  let quote = false;
  const isi = text.replace(/^\uFEFF/, "").replace(/\r\n/g, "\n");
  for (let index = 0; index < isi.length; index += 1) {
    const char = isi[index];
    if (quote) {
      if (char === '"' && isi[index + 1] === '"') {
        cell += '"';
        index += 1;
      } else if (char === '"') {
        quote = false;
      } else {
        cell += char;
      }
    } else if (char === '"') {
      quote = true;
    } else if (char === ",") {
      row.push(cell);
      cell = "";
    } else if (char === "\n") {
      row.push(cell);
      rows.push(row);
      row = [];
      cell = "";
    } else {
      cell += char;
    }
  }
  if (cell || row.length) {
    row.push(cell);
    rows.push(row);
  }
  return rows.filter((baris) => baris.some((nilai) => nilai.trim()));
}

export default function KlasifikasiSuratPage() {
  const { user } = useSession();
  const isAdmin = user?.role === "ADMIN";

  const [page, setPage] = useState(1);
  const [search, setSearch] = useState("");
  const [q, setQ] = useState("");
  const [status, setStatus] = useState("");

  const filter = new URLSearchParams();
  if (q) filter.set("q", q);
  if (status) filter.set("status", status);

  const query = new URLSearchParams(filter);
  query.set("page", String(page));
  query.set("limit", "10");

  const { data, isLoading, mutate } = useSWR<Paginated<KlasifikasiSurat>>(
    `/sekretariat/klasifikasi?${query.toString()}`,
    fetcher,
  );
  const { data: ringkasan, mutate: mutateRingkasan } = useSWR<RingkasanKlasifikasi>(
    "/sekretariat/klasifikasi/ringkasan",
    fetcher,
  );
  const { data: semua } = useSWR<Paginated<KlasifikasiSurat>>(
    `/sekretariat/klasifikasi?limit=200&${filter.toString()}`,
    fetcher,
  );

  const daftar = data?.data ?? [];
  const [selected, setSelected] = useState<number[]>([]);

  const [formOpen, setFormOpen] = useState(false);
  const [editing, setEditing] = useState<KlasifikasiSurat | null>(null);
  const [form, setForm] = useState<FormState>(emptyForm);
  const [saving, setSaving] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<KlasifikasiSurat | null>(null);
  const [bulkOpen, setBulkOpen] = useState(false);
  const [deleting, setDeleting] = useState(false);

  const [importOpen, setImportOpen] = useState(false);
  const [importRows, setImportRows] = useState<{ kode: string; nama: string; uraian: string }[]>([]);
  const [importName, setImportName] = useState("");
  const [importing, setImporting] = useState(false);
  const fileRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    setPage(1);
  }, [q, status]);

  useEffect(() => {
    setSelected([]);
  }, [page, q, status]);

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

  function openEdit(item: KlasifikasiSurat) {
    setEditing(item);
    setForm({ kode: item.kode, nama: item.nama, uraian: item.uraian ?? "" });
    setFormOpen(true);
  }

  async function save(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!form.kode.trim() || !form.nama.trim()) {
      toast.error("Kode dan nama wajib diisi");
      return;
    }
    if (!/^[0-9A-Za-z.]+$/.test(form.kode.trim())) {
      toast.error("Kode hanya boleh berisi huruf, angka, dan titik");
      return;
    }
    setSaving(true);
    try {
      const payload = {
        kode: form.kode.trim(),
        nama: form.nama.trim(),
        ...(form.uraian.trim() ? { uraian: form.uraian.trim() } : {}),
      };
      if (editing) {
        await apiSend(`/sekretariat/klasifikasi/${editing.id}`, "PATCH", payload);
        toast.success("Klasifikasi surat diperbarui");
      } else {
        await apiSend("/sekretariat/klasifikasi", "POST", payload);
        toast.success("Klasifikasi surat ditambahkan");
      }
      setFormOpen(false);
      await mutate();
      await mutateRingkasan();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyimpan klasifikasi");
    } finally {
      setSaving(false);
    }
  }

  async function toggle(item: KlasifikasiSurat) {
    try {
      await apiSend(`/sekretariat/klasifikasi/${item.id}/toggle`, "PATCH");
      toast.success(item.enabled ? "Klasifikasi dinonaktifkan" : "Klasifikasi diaktifkan");
      await mutate();
      await mutateRingkasan();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal mengubah status");
    }
  }

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

  async function removeSelected() {
    setDeleting(true);
    try {
      await apiSend("/sekretariat/klasifikasi/bulk-delete", "POST", { ids: selected });
      toast.success(`${selected.length} klasifikasi dihapus`);
      setBulkOpen(false);
      setSelected([]);
      await mutate();
      await mutateRingkasan();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menghapus klasifikasi");
    } finally {
      setDeleting(false);
    }
  }

  function unduh() {
    const anchor = document.createElement("a");
    anchor.href = "/api/backend/sekretariat/klasifikasi/ekspor";
    anchor.click();
  }

  function ekspor() {
    const rows = (semua?.data ?? []).map((item) => [
      item.kode,
      item.nama,
      item.uraian ?? "",
      item.enabled ? "Aktif" : "Nonaktif",
    ]);
    unduhCsv(
      `klasifikasi-surat-${new Date().toISOString().slice(0, 10)}.csv`,
      ["Kode", "Nama", "Uraian", "Status"],
      rows,
    );
    toast.success("Klasifikasi surat diekspor");
  }

  async function bacaImpor(event: React.ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];
    if (!file) return;
    const text = await file.text();
    const rows = parseCsv(text);
    if (!rows.length) {
      toast.error("Berkas CSV kosong");
      return;
    }
    const mulai =
      rows[0][0]?.trim().toLowerCase() === "kode" || rows[0][1]?.trim().toLowerCase() === "nama"
        ? 1
        : 0;
    const items = rows
      .slice(mulai)
      .map((row) => ({
        kode: (row[0] ?? "").trim(),
        nama: (row[1] ?? "").trim(),
        uraian: (row[2] ?? "").trim(),
      }))
      .filter((item) => item.kode && item.nama);
    if (!items.length) {
      toast.error("Tidak ada baris valid. Format: Kode,Nama,Uraian");
      return;
    }
    setImportName(file.name);
    setImportRows(items);
  }

  async function prosesImpor() {
    if (!importRows.length) return;
    setImporting(true);
    try {
      const result = await apiSend<{ ditambah: number; diperbarui: number }>(
        "/sekretariat/klasifikasi/impor",
        "POST",
        { items: importRows },
      );
      toast.success(
        `Impor selesai: ${result.ditambah} baru, ${result.diperbarui} diperbarui`,
      );
      setImportOpen(false);
      setImportRows([]);
      setImportName("");
      if (fileRef.current) fileRef.current.value = "";
      await mutate();
      await mutateRingkasan();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal mengimpor klasifikasi");
    } finally {
      setImporting(false);
    }
  }

  const barisCetak = semua?.data ?? daftar;
  const semuaTerpilih = daftar.length > 0 && selected.length === daftar.length;

  return (
    <div className="animate-fade-in space-y-6">
      <div className="space-y-6 print:hidden">
        <PageHeader
          title="Klasifikasi Surat"
          description="Kode klasifikasi arsip surat desa sesuai pola tata naskah dinas."
          action={
            <div className="flex flex-wrap gap-2">
              <Button variant="outline" onClick={() => window.print()}>
                <Printer className="h-4 w-4" />
                Cetak
              </Button>
              <Button variant="outline" onClick={unduh}>
                <Download className="h-4 w-4" />
                Ekspor CSV
              </Button>
              {isAdmin && (
                <>
                  <Button
                    variant="outline"
                    onClick={() => {
                      setImportOpen(true);
                      setImportRows([]);
                      setImportName("");
                    }}
                  >
                    <Upload className="h-4 w-4" />
                    Impor
                  </Button>
                  <Button onClick={openCreate}>
                    <Plus className="h-4 w-4" />
                    Tambah Klasifikasi
                  </Button>
                </>
              )}
            </div>
          }
        />

        <div className="grid gap-4 sm:grid-cols-3">
          <StatCard
            title="Total klasifikasi"
            value={ringkasan?.total ?? 0}
            hint="Kode arsip surat desa"
            icon={Tags}
          />
          <StatCard
            title="Aktif"
            value={ringkasan?.aktif ?? 0}
            hint="Digunakan pada surat"
            icon={Hash}
            tone="sky"
          />
          <StatCard
            title="Nonaktif"
            value={ringkasan?.nonaktif ?? 0}
            hint="Disimpan sebagai arsip"
            icon={FileSpreadsheet}
            tone="amber"
          />
        </div>

        <Card>
          <CardContent className="p-0">
            <div className="flex flex-col gap-3 border-b p-4 xl:flex-row xl:items-center xl:justify-between">
              <form
                onSubmit={(event) => {
                  event.preventDefault();
                  setQ(search.trim());
                }}
                className="relative w-full xl:max-w-sm"
              >
                <Search className="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 kode, nama, atau keterangan…"
                  className="pl-9"
                />
              </form>
              <div className="flex flex-wrap items-end gap-2">
                <div className="space-y-1">
                  <Label className="text-xs text-muted-foreground">Status</Label>
                  <Select
                    value={status}
                    onChange={(event) => setStatus(event.target.value)}
                    className="w-full sm:w-40"
                  >
                    <option value="">Semua status</option>
                    <option value="true">Aktif</option>
                    <option value="false">Nonaktif</option>
                  </Select>
                </div>
                {(q || status) && (
                  <Button
                    type="button"
                    variant="ghost"
                    onClick={() => {
                      setSearch("");
                      setQ("");
                      setStatus("");
                    }}
                  >
                    Reset
                  </Button>
                )}
                <Button type="button" variant="outline" onClick={ekspor}>
                  <Download className="h-4 w-4" />
                  Ekspor data
                </Button>
                {isAdmin && selected.length > 0 && (
                  <Button type="button" variant="destructive" onClick={() => setBulkOpen(true)}>
                    <Trash2 className="h-4 w-4" />
                    Hapus ({selected.length})
                  </Button>
                )}
              </div>
            </div>

            {isLoading ? (
              <div className="space-y-2 p-4">
                {Array.from({ length: 6 }).map((_, index) => (
                  <div key={index} className="h-12 animate-pulse rounded-lg bg-muted" />
                ))}
              </div>
            ) : daftar.length ? (
              <div className="overflow-x-auto">
                <Table>
                  <TableHeader>
                    <TableRow>
                      {isAdmin && (
                        <TableHead className="w-10">
                          <input
                            type="checkbox"
                            checked={semuaTerpilih}
                            onChange={(event) =>
                              setSelected(event.target.checked ? daftar.map((item) => item.id) : [])
                            }
                            aria-label="Pilih semua klasifikasi"
                          />
                        </TableHead>
                      )}
                      <TableHead className="w-12">No</TableHead>
                      <TableHead className="w-32">Aksi</TableHead>
                      <TableHead className="w-28">Kode</TableHead>
                      <TableHead>Nama</TableHead>
                      <TableHead>Keterangan</TableHead>
                      <TableHead>Status</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {daftar.map((item, index) => (
                      <TableRow key={item.id}>
                        {isAdmin && (
                          <TableCell>
                            <input
                              type="checkbox"
                              checked={selected.includes(item.id)}
                              onChange={(event) =>
                                setSelected((current) =>
                                  event.target.checked
                                    ? [...current, item.id]
                                    : current.filter((id) => id !== item.id),
                                )
                              }
                              aria-label={`Pilih ${item.nama}`}
                            />
                          </TableCell>
                        )}
                        <TableCell className="text-muted-foreground">
                          {(page - 1) * 10 + index + 1}
                        </TableCell>
                        <TableCell>
                          <div className="flex items-center gap-1">
                            {isAdmin && (
                              <>
                                <Button
                                  variant="ghost"
                                  size="icon"
                                  className="h-8 w-8"
                                  title="Ubah klasifikasi"
                                  onClick={() => openEdit(item)}
                                >
                                  <Pencil className="h-4 w-4" />
                                </Button>
                                <Button
                                  variant="ghost"
                                  size="icon"
                                  className="h-8 w-8"
                                  title={item.enabled ? "Nonaktifkan" : "Aktifkan"}
                                  onClick={() => toggle(item)}
                                >
                                  <Power
                                    className={`h-4 w-4 ${item.enabled ? "text-emerald-600" : "text-muted-foreground"}`}
                                  />
                                </Button>
                                <Button
                                  variant="ghost"
                                  size="icon"
                                  className="h-8 w-8 text-destructive"
                                  title="Hapus klasifikasi"
                                  onClick={() => setDeleteTarget(item)}
                                >
                                  <Trash2 className="h-4 w-4" />
                                </Button>
                              </>
                            )}
                          </div>
                        </TableCell>
                        <TableCell>
                          <span className="font-mono text-sm font-semibold">{item.kode}</span>
                        </TableCell>
                        <TableCell className="font-medium">{item.nama}</TableCell>
                        <TableCell>
                          <div className="max-w-[420px] text-sm text-muted-foreground">
                            {item.uraian ?? "-"}
                          </div>
                        </TableCell>
                        <TableCell>
                          <Badge variant={item.enabled ? "success" : "secondary"}>
                            {item.enabled ? "Aktif" : "Nonaktif"}
                          </Badge>
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              </div>
            ) : (
              <div className="flex flex-col items-center justify-center gap-2 py-16 text-center">
                <Tags className="h-8 w-8 text-muted-foreground" />
                <p className="font-semibold">Belum ada klasifikasi surat</p>
                <p className="max-w-md text-sm text-muted-foreground">
                  Tambahkan kode klasifikasi atau impor dari berkas CSV.
                </p>
              </div>
            )}

            {data && data.meta.total > 0 && (
              <Pagination
                page={page}
                totalPages={data.meta.totalPages}
                total={data.meta.total}
                onChange={setPage}
              />
            )}
          </CardContent>
        </Card>
      </div>

      <div className="hidden print:block">
        <div className="mb-4 text-center">
          <h1 className="text-lg font-bold uppercase">Klasifikasi Surat Desa Mulyadadi</h1>
          <p className="text-sm">Kecamatan Cipari, Kabupaten Cilacap</p>
          <p className="text-xs text-muted-foreground">Dicetak pada {new Date().toLocaleDateString("id-ID")}</p>
        </div>
        <table className="w-full border-collapse text-xs">
          <thead>
            <tr>
              {["No", "Kode", "Nama", "Keterangan", "Status"].map((judul) => (
                <th key={judul} className="border border-slate-400 px-2 py-1 text-left">
                  {judul}
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {barisCetak.map((item, index) => (
              <tr key={item.id}>
                <td className="border border-slate-400 px-2 py-1">{index + 1}</td>
                <td className="border border-slate-400 px-2 py-1 font-mono">{item.kode}</td>
                <td className="border border-slate-400 px-2 py-1">{item.nama}</td>
                <td className="border border-slate-400 px-2 py-1">{item.uraian ?? "-"}</td>
                <td className="border border-slate-400 px-2 py-1">
                  {item.enabled ? "Aktif" : "Nonaktif"}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent className="max-w-xl">
          <DialogHeader>
            <DialogTitle>{editing ? "Ubah Klasifikasi" : "Tambah Klasifikasi"}</DialogTitle>
            <DialogDescription>
              Kode klasifikasi mengikuti pola tata naskah dinas, contoh 005 atau 110.1.
            </DialogDescription>
          </DialogHeader>
          <form onSubmit={save} className="space-y-4">
            <div className="space-y-2">
              <Label htmlFor="klasifikasi-kode">Kode</Label>
              <Input
                id="klasifikasi-kode"
                value={form.kode}
                onChange={(event) => setForm((current) => ({ ...current, kode: event.target.value }))}
                maxLength={50}
                placeholder="005"
                className="font-mono"
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="klasifikasi-nama">Nama</Label>
              <Input
                id="klasifikasi-nama"
                value={form.nama}
                onChange={(event) => setForm((current) => ({ ...current, nama: event.target.value }))}
                maxLength={200}
                placeholder="Undang-Undang"
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="klasifikasi-uraian">Keterangan</Label>
              <Textarea
                id="klasifikasi-uraian"
                value={form.uraian}
                onChange={(event) =>
                  setForm((current) => ({ ...current, uraian: event.target.value }))
                }
                rows={4}
                placeholder="Penjelasan penggunaan kode klasifikasi"
              />
            </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={importOpen} onOpenChange={setImportOpen}>
        <DialogContent className="max-w-xl">
          <DialogHeader>
            <DialogTitle>Impor Klasifikasi Surat</DialogTitle>
            <DialogDescription>
              Unggah berkas CSV dengan kolom Kode, Nama, Uraian. Kode yang sudah ada akan
              diperbarui.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <div className="space-y-2">
              <Label htmlFor="klasifikasi-impor">Berkas CSV</Label>
              <Input
                id="klasifikasi-impor"
                ref={fileRef}
                type="file"
                accept=".csv,text/csv"
                onChange={bacaImpor}
              />
              {importName && (
                <p className="text-xs text-muted-foreground">
                  {importName} · {importRows.length} baris siap diimpor
                </p>
              )}
            </div>
            {importRows.length > 0 && (
              <div className="max-h-56 overflow-y-auto rounded-lg border">
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead>Kode</TableHead>
                      <TableHead>Nama</TableHead>
                      <TableHead>Keterangan</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {importRows.slice(0, 10).map((row, index) => (
                      <TableRow key={`${row.kode}-${index}`}>
                        <TableCell className="font-mono">{row.kode}</TableCell>
                        <TableCell>{row.nama}</TableCell>
                        <TableCell className="max-w-[240px] truncate">{row.uraian || "-"}</TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              </div>
            )}
            <p className="text-xs text-muted-foreground">
              Contoh baris: 005,Undang-Undang,Naskah undang-undang yang diterima desa
            </p>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setImportOpen(false)}>
              Batal
            </Button>
            <Button onClick={prosesImpor} disabled={!importRows.length || importing}>
              {importing ? "Mengimpor…" : `Impor ${importRows.length || ""} Baris`}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={Boolean(deleteTarget)} onOpenChange={(open) => !open && setDeleteTarget(null)}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus klasifikasi?</DialogTitle>
            <DialogDescription>
              Klasifikasi “{deleteTarget?.kode} — {deleteTarget?.nama}” 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={bulkOpen} onOpenChange={setBulkOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>Hapus {selected.length} klasifikasi?</DialogTitle>
            <DialogDescription>Data yang dipilih akan dihapus permanen.</DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setBulkOpen(false)}>
              Batal
            </Button>
            <Button variant="destructive" onClick={removeSelected} disabled={deleting}>
              {deleting ? "Menghapus…" : "Hapus Semua"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
