import { useMemo, useState, type ReactNode } from "react";
import { FormDialog, val } from "@/components/sip/FormDialog";
import { Section, DataTable } from "@/components/sip/Section";
import { SearchToggleBar, SummaryCards, type ViewMode } from "@/components/sip/FilterBar";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Label } from "@/components/ui/label";
import { Plus, Trash2, Pencil, Paperclip, Image as ImageIcon, Trophy } from "lucide-react";
import { useServerFn } from "@tanstack/react-start";
import { parseDriveFolderId } from "@/lib/drive";
import { uploadToDrive } from "@/lib/drive.functions";
import { toast } from "sonner";
import {
  JENIS_PRESTASI,
  TINGKAT_PRESTASI,
  newId,
  todayISO,
  useSip,
  type JenisPrestasi,
  type TingkatPrestasi,
  type Prestasi,
  type Siswa,
} from "@/lib/sip-data";

const selectClass =
  "border-input bg-background focus-visible:ring-ring h-10 w-full rounded-md border px-3 text-sm focus-visible:ring-2 focus-visible:outline-none";

function EditDialog({
  record,
  onUpdate,
  kelasList,
  siswa,
  trigger,
}: {
  record: Prestasi;
  onUpdate: (id: string, values: Record<string, string>) => void;
  kelasList: string[];
  siswa: Siswa[];
  trigger: ReactNode;
}) {
  return (
    <FormDialog
      title="Edit Prestasi Siswa"
      description="Perbarui data prestasi siswa. Kosongkan unggahan file jika ingin mempertahankan bukti yang sudah ada."
      fields={[
        { name: "kelas", label: "Kelas", type: "select", options: kelasList, defaultValue: record.kelas },
        {
          name: "nama",
          label: "Nama Siswa",
          type: "select",
          options: (values) => siswa.filter((s) => s.kelas === values["kelas"]).map((s) => s.nama),
          defaultValue: record.nama,
        },
        { name: "jenis", label: "Jenis Prestasi", type: "select", options: [...JENIS_PRESTASI], defaultValue: record.jenis },
        { name: "tingkat", label: "Tingkat Prestasi", type: "select", options: [...TINGKAT_PRESTASI], defaultValue: record.tingkat },
        { name: "kegiatan", label: "Nama Lomba / Kegiatan", placeholder: "Contoh: Olimpiade IPA", defaultValue: record.kegiatan },
        { name: "peringkat", label: "Prestasi yang Diperoleh", placeholder: "Contoh: Juara 1", defaultValue: record.peringkat },
        { name: "penyelenggara", label: "Penyelenggara", placeholder: "Contoh: Dinas Pendidikan", defaultValue: record.penyelenggara },
        { name: "tanggal", label: "Tanggal Perolehan", type: "date", defaultValue: record.tanggal },
        { name: "keterangan", label: "Keterangan", type: "textarea", optional: true, defaultValue: record.keterangan },
        {
          name: "sertifikat",
          label: `Unggah Sertifikat / Piagam${record.sertifikatUrl ? " (sudah ada)" : ""}`,
          type: "file",
          optional: true,
        },
        {
          name: "foto",
          label: `Unggah Foto Penyerahan${record.fotoUrl ? " (sudah ada)" : ""}`,
          type: "file",
          optional: true,
        },
      ]}
      submitLabel="Simpan Perubahan"
      onSubmit={(v) => onUpdate(record.id, v)}
      trigger={trigger}
    />
  );
}

export function PrestasiSiswa() {
  const { prestasi, setPrestasi, kelasList, siswa, currentUser, drivePrestasiUrl } = useSip();
  const upload = useServerFn(uploadToDrive);

  const [query, setQuery] = useState("");
  const [view, setView] = useState<ViewMode>("rinci");
  const [fKelas, setFKelas] = useState("");
  const [fJenis, setFJenis] = useState("");
  const [fTingkat, setFTingkat] = useState("");

  const filtered = useMemo(() => {
    const q = query.trim().toLowerCase();
    return [...prestasi]
      .sort((a, b) => (a.tanggal < b.tanggal ? 1 : -1))
      .filter((p) => {
        if (fKelas && p.kelas !== fKelas) return false;
        if (fJenis && p.jenis !== fJenis) return false;
        if (fTingkat && p.tingkat !== fTingkat) return false;
        if (!q) return true;
        return [p.nama, p.kelas, p.kegiatan, p.peringkat, p.penyelenggara, p.tingkat, p.jenis]
          .join(" ")
          .toLowerCase()
          .includes(q);
      });
  }, [prestasi, query, fKelas, fJenis, fTingkat]);

  const ringkasItems = Array.from(
    filtered.reduce((m, p) => m.set(p.tingkat, (m.get(p.tingkat) ?? 0) + 1), new Map<string, number>()),
  )
    .sort((a, b) => b[1] - a[1])
    .map(([k, v]) => ({ label: k, value: v }));

  const uploadBerkas = async (id: string, key: "sertifikatUrl" | "fotoUrl", dataUrl: string, nama: string) => {
    const folderId = parseDriveFolderId(drivePrestasiUrl);
    if (!folderId) {
      toast.error("Folder Google Drive prestasi siswa belum diatur oleh admin");
      return;
    }
    try {
      const res = await upload({
        data: { folderId, name: `Prestasi_${Date.now()}_${nama}`, dataUrl },
      });
      setPrestasi((prev) => prev.map((x) => (x.id === id ? { ...x, [key]: res.webViewLink } : x)));
      toast.success("Berkas terunggah ke Google Drive");
    } catch (err) {
      toast.error("Berkas gagal diunggah ke Google Drive", { description: String(err) });
    }
  };

  const handleEdit = async (id: string, v: Record<string, string>) => {
    setPrestasi((prev) =>
      prev.map((x) =>
        x.id === id
          ? {
              ...x,
              tanggal: val(v, "tanggal") || x.tanggal,
              nama: val(v, "nama"),
              kelas: val(v, "kelas"),
              jenis: (val(v, "jenis") || x.jenis) as JenisPrestasi,
              tingkat: (val(v, "tingkat") || x.tingkat) as TingkatPrestasi,
              kegiatan: val(v, "kegiatan"),
              peringkat: val(v, "peringkat"),
              penyelenggara: val(v, "penyelenggara"),
              keterangan: val(v, "keterangan") || "-",
            }
          : x,
      ),
    );
    toast.success("Data prestasi diperbarui");

    const sertifikat = v["sertifikat"] ?? "";
    if (sertifikat)
      await uploadBerkas(id, "sertifikatUrl", sertifikat, v["sertifikat__nama"] ?? "sertifikat");
    const foto = v["foto"] ?? "";
    if (foto) await uploadBerkas(id, "fotoUrl", foto, v["foto__nama"] ?? "foto");
  };

  const tambah = (
    <FormDialog
      title="Catat Prestasi Siswa"
      description="Data prestasi otomatis tampil di akun orang tua siswa bersangkutan."
      fields={[
        { name: "kelas", label: "Kelas", type: "select", options: kelasList },
        {
          name: "nama",
          label: "Nama Siswa",
          type: "select",
          options: (values) => siswa.filter((s) => s.kelas === values["kelas"]).map((s) => s.nama),
        },
        { name: "jenis", label: "Jenis Prestasi", type: "select", options: [...JENIS_PRESTASI] },
        { name: "tingkat", label: "Tingkat Prestasi", type: "select", options: [...TINGKAT_PRESTASI] },
        { name: "kegiatan", label: "Nama Lomba / Kegiatan", placeholder: "Contoh: Olimpiade IPA" },
        { name: "peringkat", label: "Prestasi yang Diperoleh", placeholder: "Contoh: Juara 1" },
        { name: "penyelenggara", label: "Penyelenggara", placeholder: "Contoh: Dinas Pendidikan" },
        { name: "tanggal", label: "Tanggal Perolehan", type: "date", defaultValue: todayISO() },
        { name: "keterangan", label: "Keterangan", type: "textarea", optional: true },
        {
          name: "sertifikat",
          label: "Unggah Sertifikat / Piagam / Surat Keterangan",
          type: "file",
          optional: true,
        },
        {
          name: "foto",
          label: "Unggah Foto Penyerahan Piala / Piagam",
          type: "file",
          optional: true,
        },
      ]}
      submitLabel="Simpan Prestasi"
      onSubmit={async (v) => {
        const id = newId("PR");
        setPrestasi((prev) => [
          ...prev,
          {
            id,
            tanggal: val(v, "tanggal") || todayISO(),
            nama: val(v, "nama"),
            kelas: val(v, "kelas"),
            jenis: (val(v, "jenis") || "Akademik") as JenisPrestasi,
            tingkat: (val(v, "tingkat") || "Tingkat Sekolah") as TingkatPrestasi,
            kegiatan: val(v, "kegiatan"),
            peringkat: val(v, "peringkat"),
            penyelenggara: val(v, "penyelenggara"),
            keterangan: val(v, "keterangan") || "-",
            pencatat: `${currentUser?.nama ?? "-"} · ${currentUser?.role ?? "-"}`,
          },
        ]);
        toast.success("Prestasi siswa tercatat & terkirim ke orang tua");

        const sertifikat = v["sertifikat"] ?? "";
        if (sertifikat)
          await uploadBerkas(id, "sertifikatUrl", sertifikat, v["sertifikat__nama"] ?? "sertifikat");
        const foto = v["foto"] ?? "";
        if (foto) await uploadBerkas(id, "fotoUrl", foto, v["foto__nama"] ?? "foto");
      }}
      trigger={
        <Button size="sm">
          <Plus className="mr-1 h-4 w-4" /> Catat Prestasi
        </Button>
      }
    />
  );

  return (
    <div className="space-y-6">
      <div className="surface-card flex flex-wrap items-center justify-between gap-3 p-5">
        <div className="flex items-start gap-3">
          <Trophy className="text-primary mt-0.5 h-6 w-6" />
          <div>
            <h3 className="text-lg font-bold">Dokumentasi Prestasi Siswa</h3>
            <p className="text-muted-foreground text-sm">
              Prestasi akademik maupun non-akademik lengkap dengan bukti sertifikat dan foto
              penyerahan penghargaan.
            </p>
          </div>
        </div>
        {tambah}
      </div>

      <div className="surface-card grid gap-3 p-5 md:grid-cols-3">
        <div className="grid gap-2">
          <Label htmlFor="p-kelas">Kelas</Label>
          <select id="p-kelas" className={selectClass} value={fKelas} onChange={(e) => setFKelas(e.target.value)}>
            <option value="">Semua Kelas</option>
            {kelasList.map((k) => (
              <option key={k} value={k}>
                {k}
              </option>
            ))}
          </select>
        </div>
        <div className="grid gap-2">
          <Label htmlFor="p-jenis">Jenis Prestasi</Label>
          <select id="p-jenis" className={selectClass} value={fJenis} onChange={(e) => setFJenis(e.target.value)}>
            <option value="">Semua Jenis</option>
            {JENIS_PRESTASI.map((j) => (
              <option key={j} value={j}>
                {j}
              </option>
            ))}
          </select>
        </div>
        <div className="grid gap-2">
          <Label htmlFor="p-tingkat">Tingkat</Label>
          <select
            id="p-tingkat"
            className={selectClass}
            value={fTingkat}
            onChange={(e) => setFTingkat(e.target.value)}
          >
            <option value="">Semua Tingkat</option>
            {TINGKAT_PRESTASI.map((t) => (
              <option key={t} value={t}>
                {t}
              </option>
            ))}
          </select>
        </div>
      </div>

      <Section title={`Data Siswa Berprestasi (${filtered.length})`}>
        <SearchToggleBar
          query={query}
          onQueryChange={setQuery}
          view={view}
          onViewChange={setView}
          placeholder="Cari nama / kelas / lomba / penyelenggara..."
        />
        {view === "ringkas" ? (
          <SummaryCards total={filtered.length} totalLabel="Total Prestasi" items={ringkasItems} />
        ) : (
          <DataTable
            head={[
              "Tanggal",
              "Nama Siswa",
              "Kelas",
              "Jenis",
              "Kegiatan",
              "Tingkat",
              "Prestasi",
              "Penyelenggara",
              "Bukti",
              "Aksi",
            ]}
            empty="Belum ada data prestasi siswa."
            alignLast
            rows={filtered.map((p) => [
              <span className="text-muted-foreground whitespace-nowrap">{p.tanggal}</span>,
              <span className="font-semibold">{p.nama}</span>,
              <Badge variant="secondary">{p.kelas}</Badge>,
              <Badge variant="outline">{p.jenis}</Badge>,
              p.kegiatan,
              <Badge variant="secondary">{p.tingkat}</Badge>,
              <span className="font-semibold">{p.peringkat}</span>,
              p.penyelenggara,
              <div className="flex flex-wrap gap-2">
                {p.sertifikatUrl ? (
                  <a
                    href={p.sertifikatUrl}
                    target="_blank"
                    rel="noreferrer"
                    className="text-primary inline-flex items-center gap-1 text-xs font-medium underline"
                  >
                    <Paperclip className="h-3.5 w-3.5" /> Sertifikat
                  </a>
                ) : null}
                {p.fotoUrl ? (
                  <a
                    href={p.fotoUrl}
                    target="_blank"
                    rel="noreferrer"
                    className="text-primary inline-flex items-center gap-1 text-xs font-medium underline"
                  >
                    <ImageIcon className="h-3.5 w-3.5" /> Foto
                  </a>
                ) : null}
                {!p.sertifikatUrl && !p.fotoUrl ? (
                  <span className="text-muted-foreground text-xs">-</span>
                ) : null}
              </div>,
              <div className="flex items-center gap-1">
                <EditDialog
                  record={p}
                  onUpdate={handleEdit}
                  kelasList={kelasList}
                  siswa={siswa}
                  trigger={
                    <Button size="icon" variant="ghost" title="Edit">
                      <Pencil className="h-4 w-4" />
                    </Button>
                  }
                />
                <Button
                  size="icon"
                  variant="ghost"
                  title="Hapus"
                  onClick={() => {
                    setPrestasi((prev) => prev.filter((x) => x.id !== p.id));
                    toast.success("Data prestasi dihapus");
                  }}
                >
                  <Trash2 className="text-destructive h-4 w-4" />
                </Button>
              </div>,
            ])}
          />
        )}
      </Section>
    </div>
  );
}
