import { useEffect, useMemo, useRef, useState } from "react";
import { FormDialog, val } from "@/components/sip/FormDialog";
import { Section, DataTable } from "@/components/sip/Section";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Plus, Pencil, Trash2, Clock, BookOpen, Search, Download, Upload } from "lucide-react";
import { toast } from "sonner";
import {
  newId,
  useSip,
  HARI_LIST,
  JAM_KE_LIST,
  type JadwalMengajar as Jm,
  waliKelasOf,
} from "@/lib/sip-data";

const hariHariIni = () => {
  const d = new Date().toLocaleDateString("id-ID", { weekday: "long" });
  return d === "Jumat" || d === "Jum'at" ? "Jumat" : d;
};

const toMinutes = (s: string) => {
  const m = s.trim().match(/^(\d{1,2})[.:](\d{2})$/);
  if (!m) return null;
  return Number(m[1]) * 60 + Number(m[2]);
};

const parseRange = (pukul: string) => {
  const parts = pukul.split(/[-–]/);
  if (parts.length < 2) return null;
  const start = toMinutes(parts[0] ?? "");
  const end = toMinutes(parts[1] ?? "");
  if (start === null || end === null) return null;
  return { start, end };
};

export function JadwalMengajar({ context }: { context: string }) {
  const { currentUser, jadwalMengajar, setJadwalMengajar, kelasList, users } = useSip();
  const [now, setNow] = useState(() => new Date());
  const fileRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    const t = setInterval(() => setNow(new Date()), 30000);
    return () => clearInterval(t);
  }, []);

  const isOwner = context === "jadwal_mengajar_saya";
  const guruNama = currentUser?.nama ?? "";
  const mapelGuru = currentUser?.keterangan ?? "";

  const mine = useMemo(
    () => jadwalMengajar.filter((j) => j.guru === guruNama),
    [jadwalMengajar, guruNama],
  );

  const hari = hariHariIni();
  const menit = now.getHours() * 60 + now.getMinutes();
  const jamSekarang = now.toLocaleTimeString("id-ID", { hour: "2-digit", minute: "2-digit" });

  const hariIni = useMemo(
    () => jadwalMengajar.filter((j) => j.hari === hari),
    [jadwalMengajar, hari],
  );

  const sedangMengajar = useMemo(
    () =>
      hariIni.filter((j) => {
        const r = parseRange(j.pukul);
        return r ? menit >= r.start && menit < r.end : false;
      }),
    [hariIni, menit],
  );

  const berikutnya = useMemo(
    () =>
      hariIni
        .map((j) => ({ j, r: parseRange(j.pukul) }))
        .filter((x) => x.r && x.r.start > menit)
        .sort((a, b) => (a.r?.start ?? 0) - (b.r?.start ?? 0))
        .slice(0, 6),
    [hariIni, menit],
  );

  const guruAktif = useMemo(
    () => users.filter((u) => u.role === "Guru Mapel" && !u.nonaktif).map((u) => u.nama),
    [users],
  );

  const isKepsek = context === "kepsek_jadwal_mengajar";
  const [filterGuru, setFilterGuru] = useState("");
  const [filterKelas, setFilterKelas] = useState("");
  const [filterHari, setFilterHari] = useState("");


  const filteredJadwal = useMemo(() => {
    const q = filterGuru.trim().toLowerCase();
    return jadwalMengajar
      .filter(
        (j) =>
          (!q || j.guru.toLowerCase().includes(q)) &&
          (!filterKelas || j.kelas === filterKelas) &&
          (!filterHari || j.hari === filterHari),
      )
      .sort(
        (a, b) =>
          HARI_LIST.indexOf(a.hari as (typeof HARI_LIST)[number]) -
            HARI_LIST.indexOf(b.hari as (typeof HARI_LIST)[number]) ||
          Number(a.jam_ke) - Number(b.jam_ke),
      );
  }, [jadwalMengajar, filterGuru, filterKelas, filterHari]);

  const fields = (j?: Jm) => [
    { name: "hari", label: "Hari", type: "select" as const, options: [...HARI_LIST], defaultValue: j?.hari },
    { name: "jam_ke", label: "Jam ke-", type: "select" as const, options: JAM_KE_LIST, defaultValue: j?.jam_ke },
    {
      name: "pukul",
      label: "Pukul",
      placeholder: "07.00 - 08.30",
      defaultValue: j?.pukul,
    },
    { name: "mapel", label: "Mata Pelajaran", defaultValue: j?.mapel ?? mapelGuru },
    { name: "kelas", label: "Kelas", type: "select" as const, options: kelasList, defaultValue: j?.kelas },
  ];

  const save = (v: Record<string, string>, j?: Jm) => {
    const pukul = val(v, "pukul");
    if (!parseRange(pukul)) {
      toast.error("Format pukul tidak valid", { description: "Gunakan format 07.00 - 08.30" });
      return;
    }
    const data = {
      hari: val(v, "hari"),
      jam_ke: val(v, "jam_ke"),
      pukul,
      mapel: val(v, "mapel"),
      kelas: val(v, "kelas"),
    };
    if (j) {
      setJadwalMengajar((prev) => prev.map((x) => (x.id === j.id ? { ...x, ...data } : x)));
      toast.success("Jadwal mengajar diperbarui");
      return;
    }
    setJadwalMengajar((prev) => [...prev, { id: newId("JM"), guru: guruNama, ...data }]);
    toast.success("Jadwal mengajar ditambahkan");
  };

  const downloadTemplate = async () => {
    const XLSX = await import("xlsx");
    const ws = XLSX.utils.json_to_sheet([
      {
        Hari: "Senin",
        "Jam ke-": "1",
        Pukul: "07.00 - 08.30",
        "Mata Pelajaran": mapelGuru || "Matematika",
        Kelas: kelasList[0] ?? "VII A",
      },
    ]);
    ws["!cols"] = [{ wch: 10 }, { wch: 10 }, { wch: 18 }, { wch: 24 }, { wch: 12 }];
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "Jadwal Mengajar");
    XLSX.writeFile(wb, "template-jadwal-mengajar.xlsx");
    toast.success("Template Excel diunduh");
  };

  const handleUpload = async (file: File) => {
    try {
      const XLSX = await import("xlsx");
      const wb = XLSX.read(await file.arrayBuffer(), { type: "array" });
      const sheetName = wb.SheetNames[0];
      if (!sheetName) throw new Error("kosong");
      const rows = XLSX.utils.sheet_to_json<Record<string, unknown>>(wb.Sheets[sheetName]!);
      const parsed: Jm[] = [];
      for (const r of rows) {
        const get = (k: string) =>
          String((r[k] ?? r[k.toUpperCase()] ?? r[k.toLowerCase()] ?? "") as string | number).trim();
        const hari = get("Hari");
        const kelas = get("Kelas");
        const pukul = get("Pukul");
        if (!hari || !kelas || !parseRange(pukul)) continue;
        parsed.push({
          id: newId("JM"),
          guru: guruNama,
          hari,
          jam_ke: get("Jam ke-") || get("Jam Ke") || get("Jam"),
          pukul,
          mapel: get("Mata Pelajaran") || get("Mapel") || mapelGuru,
          kelas,
        });
      }
      if (parsed.length === 0) {
        toast.error("Tidak ada data valid", {
          description: "Gunakan template dan format pukul 07.00 - 08.30",
        });
        return;
      }
      setJadwalMengajar((prev) => [...prev, ...parsed]);
      toast.success(`${parsed.length} jadwal mengajar diimpor`);
    } catch {
      toast.error("Gagal membaca file", { description: "Pastikan file berformat .xlsx atau .xls" });
    }
  };

  if (isOwner) {
    return (
      <div className="space-y-6">
        <Section title={`Jadwal Mengajar Saya (${hari})`}>
          <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
            {hariIni.filter((j) => j.guru === guruNama).length === 0 ? (
              <p className="text-muted-foreground text-sm">Tidak ada jadwal mengajar hari ini.</p>
            ) : (
              hariIni
                .filter((j) => j.guru === guruNama)
                .map((j) => {
                  const r = parseRange(j.pukul);
                  const aktif = r ? menit >= r.start && menit < r.end : false;
                  return (
                    <div
                      key={j.id}
                      className={`rounded-xl border p-4 ${aktif ? "border-primary bg-primary/5" : "border-border"}`}
                    >
                      <div className="flex items-center justify-between">
                        <span className="font-semibold">{j.kelas}</span>
                        {aktif ? <Badge>Sedang berlangsung</Badge> : <Badge variant="secondary">Jam ke-{j.jam_ke}</Badge>}
                      </div>
                      <p className="mt-1 text-sm">{j.mapel}</p>
                      <p className="text-muted-foreground text-xs">{j.pukul}</p>
                    </div>
                  );
                })
            )}
          </div>
        </Section>

        <Section
          title="Daftar Jadwal Mengajar"
          action={
            <div className="flex w-full flex-wrap items-center gap-2 md:w-auto">
              <input
                ref={fileRef}
                type="file"
                accept=".xlsx,.xls"
                className="hidden"
                onChange={(e) => {
                  const f = e.target.files?.[0];
                  if (f) void handleUpload(f);
                  e.target.value = "";
                }}
              />
              <Button size="sm" variant="outline" onClick={() => void downloadTemplate()}>
                <Download className="mr-1 h-4 w-4" /> Template
              </Button>
              <Button size="sm" variant="outline" onClick={() => fileRef.current?.click()}>
                <Upload className="mr-1 h-4 w-4" /> Unggah Excel
              </Button>
              <FormDialog
                title="Tambah Jadwal Mengajar"
                description="Isi hari, jam ke-, pukul, mata pelajaran, dan kelas."
                fields={fields()}
                submitLabel="Simpan Jadwal"
                onSubmit={(v) => save(v)}
                trigger={
                  <Button size="sm">
                    <Plus className="mr-1 h-4 w-4" /> Tambah Jadwal
                  </Button>
                }
              />
            </div>
          }
        >
          <DataTable
            head={["Hari", "Jam ke-", "Pukul", "Mata Pelajaran", "Kelas", "Aksi"]}
            alignLast
            empty="Belum ada jadwal mengajar."
            rows={mine
              .slice()
              .sort(
                (a, b) =>
                  HARI_LIST.indexOf(a.hari as (typeof HARI_LIST)[number]) -
                    HARI_LIST.indexOf(b.hari as (typeof HARI_LIST)[number]) ||
                  Number(a.jam_ke) - Number(b.jam_ke),
              )
              .map((j) => [
                <span className="font-medium">{j.hari}</span>,
                <Badge variant="secondary">Jam ke-{j.jam_ke}</Badge>,
                j.pukul,
                j.mapel,
                <Badge variant="outline">{j.kelas}</Badge>,
                <div className="flex justify-center gap-1">
                  <FormDialog
                    title="Edit Jadwal Mengajar"
                    fields={fields(j)}
                    submitLabel="Update Jadwal"
                    onSubmit={(v) => save(v, j)}
                    trigger={
                      <Button size="icon" variant="ghost">
                        <Pencil className="h-4 w-4" />
                      </Button>
                    }
                  />
                  <Button
                    size="icon"
                    variant="ghost"
                    onClick={() => {
                      setJadwalMengajar((prev) => prev.filter((x) => x.id !== j.id));
                      toast.success("Jadwal mengajar dihapus");
                    }}
                  >
                    <Trash2 className="text-destructive h-4 w-4" />
                  </Button>
                </div>,
              ])}
          />
        </Section>
      </div>
    );
  }

  const kelasTampil = context === "wali_jadwal_mengajar" ? [waliKelasOf(currentUser)] : kelasList;
  const sedangFiltered = sedangMengajar.filter((j) => kelasTampil.includes(j.kelas));
  const hariIniFiltered = hariIni.filter((j) => kelasTampil.includes(j.kelas));

  return (
    <div className="space-y-6">
      <Section title={`Sedang Mengajar — ${hari}, ${jamSekarang} WIB`}>
        <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
          {kelasTampil.map((k) => {
            const aktif = sedangFiltered.find((j) => j.kelas === k);
            return (
              <div
                key={k}
                className={`rounded-xl border p-4 ${aktif ? "border-primary bg-primary/5" : "border-border bg-muted/30"}`}
              >
                <div className="flex items-center justify-between">
                  <span className="font-bold">{k}</span>
                  {aktif ? (
                    <Badge>Jam ke-{aktif.jam_ke}</Badge>
                  ) : (
                    <Badge variant="secondary">Kosong</Badge>
                  )}
                </div>
                {aktif ? (
                  <>
                    <p className="mt-2 flex items-center gap-1 text-sm font-semibold">
                      <BookOpen className="h-3.5 w-3.5" /> {aktif.mapel}
                    </p>
                    <p className="text-sm">{aktif.guru}</p>
                    <p className="text-muted-foreground flex items-center gap-1 text-xs">
                      <Clock className="h-3 w-3" /> {aktif.pukul}
                    </p>
                    {!guruAktif.includes(aktif.guru) ? (
                      <p className="text-destructive mt-1 text-xs">Akun guru nonaktif</p>
                    ) : null}
                  </>
                ) : (
                  <p className="text-muted-foreground mt-2 text-sm">
                    Tidak ada jam pelajaran saat ini.
                  </p>
                )}
              </div>
            );
          })}
        </div>
      </Section>

      <Section title="Jadwal Berikutnya Hari Ini">
        <DataTable
          head={["Pukul", "Jam ke-", "Kelas", "Mata Pelajaran", "Guru Pengajar"]}
          empty="Tidak ada jadwal berikutnya."
          rows={berikutnya
            .filter((x) => kelasTampil.includes(x.j.kelas))
            .map(({ j }) => [
              <span className="font-medium">{j.pukul}</span>,
              <Badge variant="secondary">Jam ke-{j.jam_ke}</Badge>,
              <Badge variant="outline">{j.kelas}</Badge>,
              j.mapel,
              j.guru,
            ])}
        />
      </Section>

      <Section title={`Seluruh Jadwal Hari ${hari}`}>
        <DataTable
          head={["Jam ke-", "Pukul", "Kelas", "Mata Pelajaran", "Guru Pengajar"]}
          empty="Belum ada jadwal untuk hari ini."
          rows={hariIniFiltered
            .slice()
            .sort((a, b) => Number(a.jam_ke) - Number(b.jam_ke))
            .map((j) => [
              <Badge variant="secondary">Jam ke-{j.jam_ke}</Badge>,
              j.pukul,
              <Badge variant="outline">{j.kelas}</Badge>,
              j.mapel,
              j.guru,
            ])}
        />
      </Section>

      {isKepsek ? (
        <Section title="Data Jadwal Mengajar">
          <div className="mb-4 flex flex-col gap-2 sm:flex-row sm:items-center">
            <div className="relative flex-1">
              <Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
              <Input
                value={filterGuru}
                onChange={(e) => setFilterGuru(e.target.value)}
                placeholder="Cari nama guru..."
                className="pl-9"
              />
            </div>
            <select
              value={filterKelas}
              onChange={(e) => setFilterKelas(e.target.value)}
              className="border-input bg-background h-9 rounded-md border px-3 text-sm"
            >
              <option value="">Semua Kelas</option>
              {kelasList.map((k) => (
                <option key={k} value={k}>
                  {k}
                </option>
              ))}
            </select>
            <select
              value={filterHari}
              onChange={(e) => setFilterHari(e.target.value)}
              className="border-input bg-background h-9 rounded-md border px-3 text-sm"
            >
              <option value="">Semua Hari</option>
              {HARI_LIST.map((h) => (
                <option key={h} value={h}>
                  {h}
                </option>
              ))}
            </select>
          </div>
          <DataTable
            head={["Hari", "Jam ke-", "Pukul", "Kelas", "Mata Pelajaran", "Guru Pengajar"]}
            empty="Tidak ada data jadwal mengajar yang cocok."
            rows={filteredJadwal.map((j) => [
              <span className="font-medium">{j.hari}</span>,
              <Badge variant="secondary">Jam ke-{j.jam_ke}</Badge>,
              j.pukul,
              <Badge variant="outline">{j.kelas}</Badge>,
              j.mapel,
              j.guru,
            ])}
          />
        </Section>
      ) : null}
    </div>
  );
}
