import { useRef, useState } from "react";
import { FormDialog, val } from "@/components/sip/FormDialog";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Plus, Pencil, Trash2, Download, Upload, ToggleLeft, ToggleRight, Eraser } from "lucide-react";
import { toast } from "sonner";
import { ROLES, newId, useSip, waliKelasOf, type Role, type User } from "@/lib/sip-data";
import { Section, DataTable } from "@/components/sip/Section";
import { FilterBar, RekapKelasTable, type ViewMode } from "@/components/sip/FilterBar";

const isOrtuRole = (r: string) => r === "Orang Tua";
const isGuruMapelRole = (r: string) => r === "Guru Mapel";
const isWaliRole = (r: string) => r === "Wali Kelas";

export function ManajemenAkun() {
  const { users, setUsers, masterKelas, setMasterKelas, kelasList, siswa, currentUser } = useSip();
  const fileRef = useRef<HTMLInputElement>(null);
  const [query, setQuery] = useState("");
  const [kelasFilter, setKelasFilter] = useState("");
  const [roleFilter, setRoleFilter] = useState("");
  const [view, setView] = useState<ViewMode>("rinci");

  const downloadTemplate = async () => {
    const XLSX = await import("xlsx");
    const ws = XLSX.utils.json_to_sheet([
      {
        Nama: "Budi Santoso, S.Pd",
        Username: "budi",
        Password: "edudigital",
        Role: "Guru Mapel",
        Keterangan: "Matematika",
        "Kelas Wali": kelasList[0] ?? "VII-A",
        "Nama Siswa": "",
      },
      {
        Nama: "Bapak Yanto",
        Username: "yanto",
        Password: "edudigital",
        Role: "Orang Tua",
        Keterangan: siswa[0]?.kelas ?? (kelasList[0] ?? "VII-A"),
        "Kelas Wali": "",
        "Nama Siswa": siswa[0]?.nama ?? "Andi Saputra",
      },
      {
        Nama: "Sri Wahyuni, S.Pd",
        Username: "sri",
        Password: "edudigital",
        Role: "Petugas Piket",
        Keterangan: "-",
        "Kelas Wali": "",
        "Nama Siswa": "",
      },
    ]);
    ws["!cols"] = [
      { wch: 26 },
      { wch: 16 },
      { wch: 16 },
      { wch: 18 },
      { wch: 20 },
      { wch: 14 },
      { wch: 24 },
    ];
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "Data Pengguna");
    XLSX.writeFile(wb, "template-data-pengguna.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: User[] = [];
      for (const r of rows) {
        const get = (k: string) =>
          String(
            (r[k] ?? r[k.toUpperCase()] ?? r[k.toLowerCase()] ?? "") as string | number,
          ).trim();
        const nama = get("Nama");
        const username = get("Username");
        const password = get("Password");
        let role = get("Role");
        if (!ROLES.includes(role as Role)) role = "Petugas Piket";
        if (!nama || !username || !password) continue;

        const anak = get("Nama Siswa");
        const match = siswa.find((s) => s.nama.toLowerCase() === anak.toLowerCase());
        const keterangan = get("Keterangan");

        const user: User = {
          id: newId("U"),
          nama,
          username,
          password,
          role: role as Role,
          keterangan: keterangan || (isOrtuRole(role) ? (match?.kelas ?? "-") : "-"),
        };
        if (isOrtuRole(role)) user.anak = anak || match?.nama || "";
        const kelasWali = get("Kelas Wali");
        if (isGuruMapelRole(role) && kelasWali) user.kelasWali = kelasWali;
        parsed.push(user);
      }
      if (parsed.length === 0) {
        toast.error("Tidak ada data valid", { description: "Gunakan template yang disediakan." });
        return;
      }
      setUsers((prev) => [...prev, ...parsed]);
      toast.success(`${parsed.length} akun berhasil diimpor & tersimpan`);
    } catch {
      toast.error("Gagal membaca file", { description: "Pastikan file berformat .xlsx atau .xls" });
    }
  };

  const userFields = (u?: User) => [
    { name: "nama", label: "Nama Lengkap", defaultValue: u?.nama },
    { name: "username", label: "Username", defaultValue: u?.username },
    {
      name: "password",
      label: u ? "Password Baru" : "Password",
      type: "password" as const,
      optional: !!u,
    },
    { name: "role", label: "Role", type: "select" as const, options: ROLES, defaultValue: u?.role },
    {
      name: "mapel",
      label: "Mata Pelajaran",
      defaultValue: u && isGuruMapelRole(u.role) ? (u.keterangan === "-" ? "" : u.keterangan) : "",
      showIf: (v: Record<string, string>) => isGuruMapelRole(v["role"] ?? ""),
    },
    {
      name: "kelasWali",
      label: "Merangkap Wali Kelas",
      type: "select" as const,
      options: kelasList,
      optional: true,
      defaultValue: u?.kelasWali ?? "",
      showIf: (v: Record<string, string>) => isGuruMapelRole(v["role"] ?? ""),
    },
    {
      name: "kelas",
      label: "Kelas",
      type: "select" as const,
      options: kelasList,
      defaultValue: u && (isWaliRole(u.role) || isOrtuRole(u.role)) ? u.keterangan : "",
      showIf: (v: Record<string, string>) =>
        isWaliRole(v["role"] ?? "") || isOrtuRole(v["role"] ?? ""),
    },
    {
      name: "anak",
      label: "Nama Siswa (Anak)",
      type: "select" as const,
      options: (values: Record<string, string>) =>
        siswa.filter((s) => s.kelas === values["kelas"]).map((s) => s.nama),
      defaultValue: u?.anak ?? "",
      showIf: (v: Record<string, string>) => isOrtuRole(v["role"] ?? ""),
    },
    {
      name: "keterangan",
      label: "Keterangan",
      optional: true,
      defaultValue: u?.keterangan === "-" ? "" : u?.keterangan,
      showIf: (v: Record<string, string>) => {
        const r = v["role"] ?? "";
        return !isGuruMapelRole(r) && !isWaliRole(r) && !isOrtuRole(r);
      },
    },
  ];

  const buildFromForm = (v: Record<string, string>) => {
    const role = val(v, "role") as Role;
    const keterangan = isGuruMapelRole(role)
      ? val(v, "mapel")
      : isWaliRole(role) || isOrtuRole(role)
        ? val(v, "kelas")
        : val(v, "keterangan");
    return {
      nama: val(v, "nama"),
      username: val(v, "username"),
      role,
      keterangan: keterangan || "-",
      anak: isOrtuRole(role) ? val(v, "anak") : "",
      kelasWali: isGuruMapelRole(role) ? val(v, "kelasWali") : "",
    };
  };

  const addUser = (v: Record<string, string>) => {
    const base = buildFromForm(v);
    setUsers((prev) => [...prev, { id: newId("U"), password: val(v, "password"), ...base }]);
    toast.success("Pengguna berhasil ditambahkan");
  };

  const editUser = (id: string, v: Record<string, string>) => {
    const base = buildFromForm(v);
    setUsers((prev) =>
      prev.map((u) =>
        u.id === id ? { ...u, ...base, password: val(v, "password") || u.password } : u,
      ),
    );
    toast.success("Data pengguna diperbarui");
  };

  const toggleAktif = (id: string) => {
    if (id === currentUser?.id) {
      toast.error("Ditolak", { description: "Tidak dapat menonaktifkan akun yang sedang login." });
      return;
    }
    let nonaktif = false;
    setUsers((prev) =>
      prev.map((u) => {
        if (u.id !== id) return u;
        nonaktif = !u.nonaktif;
        return { ...u, nonaktif };
      }),
    );
    toast.success(nonaktif ? "Akun dinonaktifkan" : "Akun diaktifkan kembali");
  };

  const deleteUser = (id: string) => {
    if (id === currentUser?.id) {
      toast.error("Ditolak", { description: "Tidak dapat menghapus akun yang sedang login." });
      return;
    }
    setUsers((prev) => prev.filter((u) => u.id !== id));
    toast.success("Pengguna dihapus");
  };

  const kelasDari = (u: User) => (isOrtuRole(u.role) || isWaliRole(u.role) ? u.keterangan : waliKelasOf(u));

  const q = query.trim().toLowerCase();
  const filteredUsers = users.filter(
    (u) =>
      (!roleFilter || u.role === roleFilter) &&
      (!kelasFilter || kelasDari(u) === kelasFilter) &&
      (!q ||
        u.nama.toLowerCase().includes(q) ||
        u.username.toLowerCase().includes(q) ||
        u.role.toLowerCase().includes(q) ||
        (u.anak ?? "").toLowerCase().includes(q) ||
        (u.kelasWali ?? "").toLowerCase().includes(q) ||
        u.keterangan.toLowerCase().includes(q)),
  );
  const kelasRekap = (kelasFilter ? [kelasFilter] : kelasList).filter(Boolean);

  const hapusSemuaFilter = () => {
    const target = filteredUsers.filter((u) => u.id !== currentUser?.id);
    if (target.length === 0) {
      toast.error("Tidak ada akun untuk dihapus");
      return;
    }
    const ids = new Set(target.map((u) => u.id));
    setUsers((prev) => prev.filter((u) => !ids.has(u.id)));
    toast.success(`${ids.size} akun dihapus`);
  };

  const waliOptions = users
    .filter((u) => u.role === "Wali Kelas" || u.role === "Guru Mapel")
    .map((u) => u.nama);

  const assignWali = (kelas: string, waliNama: string) => {
    setUsers((prev) =>
      prev.map((u) => {
        if (u.role === "Wali Kelas" && u.keterangan === kelas) return { ...u, keterangan: "-" };
        if (u.role === "Guru Mapel" && u.kelasWali === kelas) return { ...u, kelasWali: "" };
        return u;
      }),
    );
    if (waliNama) {
      setUsers((prev) =>
        prev.map((u) =>
          u.nama === waliNama
            ? u.role === "Guru Mapel"
              ? { ...u, kelasWali: kelas }
              : { ...u, keterangan: kelas }
            : u,
        ),
      );
    }
  };

  const addKelas = (v: Record<string, string>) => {
    const nama = val(v, "nama");
    setMasterKelas((prev) => (prev.includes(nama) ? prev : [...prev, nama]));
    assignWali(nama, val(v, "wali"));
    toast.success("Kelas berhasil ditambahkan");
  };

  const editKelas = (oldNama: string, v: Record<string, string>) => {
    const nama = val(v, "nama");
    setMasterKelas((prev) => {
      const next = prev.filter((k) => k !== oldNama);
      return next.includes(nama) ? next : [...next, nama];
    });
    setUsers((prev) =>
      prev.map((u) => {
        if (u.role === "Wali Kelas" && u.keterangan === oldNama) return { ...u, keterangan: "-" };
        if (u.role === "Guru Mapel" && u.kelasWali === oldNama) return { ...u, kelasWali: "" };
        return u;
      }),
    );
    assignWali(nama, val(v, "wali"));
    toast.success("Data kelas diperbarui");
  };

  const deleteKelas = (kelas: string) => {
    setMasterKelas((prev) => prev.filter((k) => k !== kelas));
    setUsers((prev) =>
      prev.map((u) => {
        if (u.role === "Wali Kelas" && u.keterangan === kelas) return { ...u, keterangan: "-" };
        if (u.role === "Guru Mapel" && u.kelasWali === kelas) return { ...u, kelasWali: "" };
        return u;
      }),
    );
    toast.success(`Kelas ${kelas} dihapus`);
  };

  return (
    <div className="space-y-6">
      <Section
        title="Daftar Pengguna Sistem"
        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>
            <Button
              size="sm"
              variant="destructive"
              disabled={filteredUsers.filter((u) => u.id !== currentUser?.id).length === 0}
              onClick={() => {
                const n = filteredUsers.filter((u) => u.id !== currentUser?.id).length;
                if (window.confirm(`Hapus ${n} akun sesuai filter/pencarian saat ini?`))
                  hapusSemuaFilter();
              }}
            >
              <Eraser className="mr-1 h-4 w-4" /> Hapus Semua (
              {filteredUsers.filter((u) => u.id !== currentUser?.id).length})
            </Button>
            <FormDialog
              title="Tambah Pengguna Baru"
              description="Satu formulir untuk semua role: guru mapel, wali kelas, orang tua, dan lainnya."
              fields={userFields()}
              submitLabel="Simpan Data"
              onSubmit={addUser}
              trigger={
                <Button size="sm">
                  <Plus className="mr-1 h-4 w-4" /> Tambah Akun
                </Button>
              }
            />
          </div>
        }
      >
        <FilterBar
          query={query}
          onQueryChange={setQuery}
          kelas={kelasFilter}
          onKelasChange={setKelasFilter}
          kelasList={kelasList}
          view={view}
          onViewChange={setView}
          placeholder="Cari nama / username / role / kelas / nama anak..."
        />
        <div className="mb-3 flex flex-wrap items-center gap-2">
          <span className="text-muted-foreground text-xs font-semibold">Filter role:</span>
          <select
            value={roleFilter}
            onChange={(e) => setRoleFilter(e.target.value)}
            className="border-input bg-background h-9 rounded-md border px-2 text-sm"
          >
            <option value="">Semua Role</option>
            {ROLES.map((r) => (
              <option key={r} value={r}>
                {r}
              </option>
            ))}
          </select>
        </div>
        {view === "ringkas" ? (
          <RekapKelasTable
            kelasList={kelasRekap}
            count={(k) => users.filter((u) => kelasDari(u) === k).length}
            label="Akun"
            extra={(k) => `Akun terkait kelas ${k}`}
          />
        ) : (
          <DataTable
            head={["Nama", "Username", "Role", "Keterangan", "Kelas / Anak", "Status", "Aksi"]}
            empty="Tidak ada akun yang cocok dengan pencarian."
            rows={filteredUsers.map((u) => [
              <span className={`font-medium ${u.nonaktif ? "text-muted-foreground line-through" : ""}`}>
                {u.nama}
              </span>,
              u.username,
              <div className="flex flex-wrap gap-1">
                <Badge variant="secondary">{u.role}</Badge>
                {u.role === "Guru Mapel" && u.kelasWali ? (
                  <Badge variant="outline">Wali {u.kelasWali}</Badge>
                ) : null}
              </div>,
              u.keterangan,
              u.role === "Orang Tua"
                ? `${u.anak || "-"} (${u.keterangan})`
                : waliKelasOf(u) || "-",
              <Badge variant={u.nonaktif ? "destructive" : "outline"}>
                {u.nonaktif ? "Nonaktif" : "Aktif"}
              </Badge>,
              <div className="flex justify-center gap-1">
                <FormDialog
                  title="Edit Pengguna"
                  fields={userFields(u)}
                  submitLabel="Update Data"
                  onSubmit={(v) => editUser(u.id, v)}
                  trigger={
                    <Button size="icon" variant="ghost">
                      <Pencil className="h-4 w-4" />
                    </Button>
                  }
                />
                <Button
                  size="icon"
                  variant="ghost"
                  title={u.nonaktif ? "Aktifkan akun" : "Nonaktifkan akun"}
                  onClick={() => toggleAktif(u.id)}
                >
                  {u.nonaktif ? (
                    <ToggleLeft className="text-muted-foreground h-4 w-4" />
                  ) : (
                    <ToggleRight className="text-primary h-4 w-4" />
                  )}
                </Button>
                <Button size="icon" variant="ghost" onClick={() => deleteUser(u.id)}>
                  <Trash2 className="text-destructive h-4 w-4" />
                </Button>
              </div>,
            ])}
            alignLast
          />
        )}
      </Section>

      <Section
        title="Manajemen Kelas & Wali Kelas"
        action={
          <FormDialog
            title="Tambah Kelas Baru"
            fields={[
              { name: "nama", label: "Nama Kelas", placeholder: "Contoh: VII-D" },
              { name: "wali", label: "Wali Kelas", type: "select", options: waliOptions, optional: true },
            ]}
            submitLabel="Simpan Kelas"
            onSubmit={addKelas}
            trigger={
              <Button size="sm" variant="secondary">
                <Plus className="mr-1 h-4 w-4" /> Tambah Kelas
              </Button>
            }
          />
        }
      >
        <DataTable
          head={["Nama Kelas", "Wali Kelas", "Aksi"]}
          rows={kelasList.map((k) => {
            const wali = users.find((u) => waliKelasOf(u) === k);
            return [
              <span className="text-primary font-semibold">{k}</span>,
              wali ? (
                <span>
                  {wali.nama}
                  {wali.role === "Guru Mapel" ? (
                    <Badge variant="secondary" className="ml-2">
                      Guru Mapel & Walas
                    </Badge>
                  ) : null}
                </span>
              ) : (
                <span className="text-muted-foreground italic">Belum ditentukan</span>
              ),
              <div className="flex justify-center gap-1">
                <FormDialog
                  title="Edit Kelas"
                  fields={[
                    { name: "nama", label: "Nama Kelas", defaultValue: k },
                    {
                      name: "wali",
                      label: "Wali Kelas",
                      type: "select",
                      options: waliOptions,
                      optional: true,
                      defaultValue: wali?.nama ?? "",
                    },
                  ]}
                  submitLabel="Update Data"
                  onSubmit={(v) => editKelas(k, v)}
                  trigger={
                    <Button size="icon" variant="ghost">
                      <Pencil className="h-4 w-4" />
                    </Button>
                  }
                />
                <Button size="icon" variant="ghost" onClick={() => deleteKelas(k)}>
                  <Trash2 className="text-destructive h-4 w-4" />
                </Button>
              </div>,
            ];
          })}
          alignLast
          empty="Tidak ada data kelas."
        />
      </Section>
      <p className="text-muted-foreground text-xs">
        Total kelas terdaftar: {masterKelas.length} kelas master.
      </p>
    </div>
  );
}
