"use client";

import { useEffect, useMemo, useState } from "react";
import { useLang } from "@/context/LanguageContext";
import {
  Alert,
  Button,
  DatePicker,
  EmptyState,
  Input,
  Modal,
  PageHeader,
  Pagination,
  Select,
  TimePicker,
  usePagination,
} from "@/components/ui";
import { api, useApi } from "@/lib/client";
import { formatDate } from "@/lib/utils";
import { IconEdit, IconPlus, IconTrash } from "@/components/icons";
import { emsConfirm } from "@/components/ConfirmDialog";

interface Program {
  id: number;
  name: string;
  nameBn: string | null;
  code: string;
  degreeLevel: string;
  faculty: string | null;
  department: string | null;
  durationYears: number;
  totalCredits: number;
  gradeScale: string;
  note: string | null;
  isActive: boolean;
  _count?: { terms: number; courses: number; students: number; exams: number };
}

interface Term {
  id: number;
  programId: number;
  name: string;
  nameBn: string | null;
  sequence: number;
  startDate: string | null;
  endDate: string | null;
  program: { id: number; name: string; nameBn: string | null };
  _count?: { courses: number; exams: number; students: number };
}

interface Course {
  id: number;
  programId: number;
  termId: number | null;
  code: string;
  name: string;
  nameBn: string | null;
  credits: number;
  courseType: string;
  fullMarks: number;
  passMarks: number;
  isActive: boolean;
  program: { id: number; name: string; nameBn: string | null };
  term: { id: number; name: string; nameBn: string | null } | null;
  _count?: { offerings: number; schedules: number };
}

interface Offering {
  id: number;
  courseId: number;
  sessionYear: string;
  section: string | null;
  staffId: number | null;
  maxSeats: number | null;
  course: { id: number; code: string; name: string; nameBn: string | null; credits: number; courseType: string; program: { id: number; name: string; nameBn: string | null } | null; term: { id: number; name: string; nameBn: string | null } | null };
  staff: { id: number; name: string; nameBn: string | null; designation: string } | null;
  _count?: { enrollments: number };
}

interface StaffMini {
  id: number;
  name: string;
  nameBn: string | null;
  designation: string;
  status: string;
}

type Tab = "programs" | "terms" | "courses" | "offerings" | "routine";

const DAYS = ["SAT", "SUN", "MON", "TUE", "WED", "THU", "FRI"];

interface Slot {
  id: number;
  offeringId: number;
  dayOfWeek: string;
  startTime: string;
  endTime: string;
  room: string | null;
  offering: {
    id: number; sessionYear: string; section: string | null;
    course: { id: number; code: string; name: string; nameBn: string | null; credits: number; program: { id: number; name: string; nameBn: string | null } | null; term: { id: number; name: string; nameBn: string | null } | null };
    staff: { id: number; name: string; nameBn: string | null } | null;
  };
}

const DEGREE_LEVELS = ["HSC", "DEGREE_PASS", "HONOURS", "BACHELORS", "MASTERS", "DIPLOMA"];
const COURSE_TYPES = ["THEORY", "LAB", "SESSIONAL", "THESIS", "PROJECT", "VIVA"];

const EMPTY_PROGRAM = {
  name: "", nameBn: "", code: "", degreeLevel: "BACHELORS", faculty: "", department: "",
  durationYears: "4", totalCredits: "0", gradeScale: "GPA4", note: "",
};
const EMPTY_TERM = { programId: "", name: "", nameBn: "", sequence: "", startDate: "", endDate: "" };
const EMPTY_COURSE = { programId: "", termId: "", code: "", name: "", nameBn: "", credits: "3", courseType: "THEORY", fullMarks: "100", passMarks: "40" };
const EMPTY_OFFERING = { courseId: "", sessionYear: "", section: "", staffId: "", maxSeats: "" };

/** College & University academic setup: degree programs, terms (year/semester),
    courses with credit hours and per-session offerings with teachers. */
export default function CampusAcademicPage() {
  const { t, locale } = useLang();
  const L = t.portal.campusAcademicPage;

  const [tab, setTab] = useState<Tab>("programs");
  const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null);
  const [saving, setSaving] = useState(false);

  const programsData = useApi<{ programs: Program[] }>("/api/portal/campus/programs");
  const termsData = useApi<{ terms: Term[] }>("/api/portal/campus/terms");
  const coursesData = useApi<{ courses: Course[] }>("/api/portal/campus/courses");
  const offeringsData = useApi<{ offerings: Offering[] }>("/api/portal/campus/offerings");
  const hrData = useApi<{ staff: StaffMini[] }>("/api/portal/hr");

  const programs = programsData.data?.programs ?? [];
  const terms = termsData.data?.terms ?? [];
  const courses = coursesData.data?.courses ?? [];
  const offerings = offeringsData.data?.offerings ?? [];
  const teachers = useMemo(() => (hrData.data?.staff ?? []).filter((s) => s.status === "ACTIVE"), [hrData.data]);

  // filters
  const [termProgram, setTermProgram] = useState("");
  const [courseProgram, setCourseProgram] = useState("");
  const [offeringProgram, setOfferingProgram] = useState("");

  // routine tab
  const [routineProgram, setRoutineProgram] = useState("");
  const [routineSession, setRoutineSession] = useState("");
  const slotsUrl =
    "/api/portal/campus/slots?" +
    new URLSearchParams(
      Object.entries({ programId: routineProgram, sessionYear: routineSession }).filter(([, v]) => v) as [string, string][]
    ).toString();
  const slotsData = useApi<{ slots: Slot[] }>(slotsUrl);
  const [slotModal, setSlotModal] = useState(false);
  const [slotForm, setSlotForm] = useState({ offeringId: "", dayOfWeek: "SUN", startTime: "10:00", endTime: "11:30", room: "" });

  // modals
  const [programModal, setProgramModal] = useState(false);
  const [editingProgram, setEditingProgram] = useState<Program | null>(null);
  const [programForm, setProgramForm] = useState({ ...EMPTY_PROGRAM });

  const [termModal, setTermModal] = useState(false);
  const [editingTerm, setEditingTerm] = useState<Term | null>(null);
  const [termForm, setTermForm] = useState({ ...EMPTY_TERM });

  const [courseModal, setCourseModal] = useState(false);
  const [editingCourse, setEditingCourse] = useState<Course | null>(null);
  const [courseForm, setCourseForm] = useState({ ...EMPTY_COURSE });

  const [offeringModal, setOfferingModal] = useState(false);
  const [editingOffering, setEditingOffering] = useState<Offering | null>(null);
  const [offeringForm, setOfferingForm] = useState({ ...EMPTY_OFFERING });

  const nm = (en: string | null | undefined, bn: string | null | undefined) =>
    locale === "bn" && bn ? bn : en ?? "—";

  const errorText = (err: unknown, fallback: string) => {
    const code = err instanceof Error ? err.message : "";
    if (code === "CODE_EXISTS" || code === "ID_EXISTS") return L.errCodeExists;
    if (code === "SEQUENCE_EXISTS") return L.errSequenceExists;
    if (code === "PROGRAM_IN_USE" || code === "TERM_IN_USE" || code === "COURSE_IN_USE") return L.errInUse;
    if (code === "OFFERING_EXISTS") return L.errOfferingExists;
    if (code === "PASS_EXCEEDS_MARKS") return L.errPassExceeds;
    if (code === "Invalid term") return L.errInvalidTerm;
    return fallback;
  };

  const filteredTerms = termProgram ? terms.filter((x) => x.programId === Number(termProgram)) : terms;
  const filteredCourses = courseProgram ? courses.filter((x) => x.programId === Number(courseProgram)) : courses;
  const filteredOfferings = offeringProgram
    ? offerings.filter((x) => x.course.program?.id === Number(offeringProgram))
    : offerings;

  const termsPager = usePagination(filteredTerms);
  const coursesPager = usePagination(filteredCourses);
  const offeringsPager = usePagination(filteredOfferings);

  // terms/courses modals: program dropdown resets when the program list loads
  useEffect(() => {
    if (programs.length > 0 && !termForm.programId && !editingTerm) {
      // leave empty — the admin picks
    }
  }, [programs, termForm.programId, editingTerm]);

  /* ------------------------------ programs ------------------------------ */

  function openProgramCreate() {
    setEditingProgram(null);
    setProgramForm({ ...EMPTY_PROGRAM });
    setProgramModal(true);
  }
  function openProgramEdit(p: Program) {
    setEditingProgram(p);
    setProgramForm({
      name: p.name, nameBn: p.nameBn ?? "", code: p.code, degreeLevel: p.degreeLevel,
      faculty: p.faculty ?? "", department: p.department ?? "",
      durationYears: String(p.durationYears), totalCredits: String(p.totalCredits),
      gradeScale: p.gradeScale, note: p.note ?? "",
    });
    setProgramModal(true);
  }
  async function submitProgram(e: React.FormEvent) {
    e.preventDefault();
    setSaving(true);
    try {
      await api(editingProgram ? `/api/portal/campus/programs/${editingProgram.id}` : "/api/portal/campus/programs", {
        method: editingProgram ? "PATCH" : "POST",
        body: JSON.stringify(programForm),
      });
      setProgramModal(false);
      setMessage({ type: "success", text: L.programSaved });
      programsData.reload();
      termsData.reload();
      coursesData.reload();
    } catch (err) {
      setMessage({ type: "error", text: errorText(err, L.programSaved) });
    } finally {
      setSaving(false);
    }
  }
  async function deleteProgram(p: Program) {
    if (!(await emsConfirm({ message: L.confirmDeleteProgram, danger: true }))) return;
    try {
      await api(`/api/portal/campus/programs/${p.id}`, { method: "DELETE" });
      setMessage({ type: "success", text: L.programDeleted });
      programsData.reload();
      termsData.reload();
      coursesData.reload();
    } catch (err) {
      setMessage({ type: "error", text: errorText(err, L.programDeleted) });
    }
  }

  /* -------------------------------- terms -------------------------------- */

  function openTermCreate() {
    setEditingTerm(null);
    setTermForm({ ...EMPTY_TERM });
    setTermModal(true);
  }
  function openTermEdit(x: Term) {
    setEditingTerm(x);
    setTermForm({
      programId: String(x.programId), name: x.name, nameBn: x.nameBn ?? "",
      sequence: String(x.sequence),
      startDate: x.startDate ? String(x.startDate).slice(0, 10) : "",
      endDate: x.endDate ? String(x.endDate).slice(0, 10) : "",
    });
    setTermModal(true);
  }
  async function submitTerm(e: React.FormEvent) {
    e.preventDefault();
    setSaving(true);
    try {
      await api(editingTerm ? `/api/portal/campus/terms/${editingTerm.id}` : "/api/portal/campus/terms", {
        method: editingTerm ? "PATCH" : "POST",
        body: JSON.stringify(termForm),
      });
      setTermModal(false);
      setMessage({ type: "success", text: L.termSaved });
      termsData.reload();
    } catch (err) {
      setMessage({ type: "error", text: errorText(err, L.termSaved) });
    } finally {
      setSaving(false);
    }
  }
  async function deleteTerm(x: Term) {
    if (!(await emsConfirm({ message: L.confirmDeleteTerm, danger: true }))) return;
    try {
      await api(`/api/portal/campus/terms/${x.id}`, { method: "DELETE" });
      setMessage({ type: "success", text: L.termDeleted });
      termsData.reload();
      coursesData.reload();
    } catch (err) {
      setMessage({ type: "error", text: errorText(err, L.termDeleted) });
    }
  }

  /* ------------------------------- courses ------------------------------- */

  function openCourseCreate() {
    setEditingCourse(null);
    setCourseForm({ ...EMPTY_COURSE, programId: courseProgram });
    setCourseModal(true);
  }
  function openCourseEdit(c: Course) {
    setEditingCourse(c);
    setCourseForm({
      programId: String(c.programId), termId: c.termId ? String(c.termId) : "",
      code: c.code, name: c.name, nameBn: c.nameBn ?? "",
      credits: String(c.credits), courseType: c.courseType,
      fullMarks: String(c.fullMarks), passMarks: String(c.passMarks),
    });
    setCourseModal(true);
  }
  async function submitCourse(e: React.FormEvent) {
    e.preventDefault();
    setSaving(true);
    try {
      await api(editingCourse ? `/api/portal/campus/courses/${editingCourse.id}` : "/api/portal/campus/courses", {
        method: editingCourse ? "PATCH" : "POST",
        body: JSON.stringify(courseForm),
      });
      setCourseModal(false);
      setMessage({ type: "success", text: L.courseSaved });
      coursesData.reload();
    } catch (err) {
      setMessage({ type: "error", text: errorText(err, L.courseSaved) });
    } finally {
      setSaving(false);
    }
  }
  async function deleteCourse(c: Course) {
    if (!(await emsConfirm({ message: L.confirmDeleteCourse, danger: true }))) return;
    try {
      await api(`/api/portal/campus/courses/${c.id}`, { method: "DELETE" });
      setMessage({ type: "success", text: L.courseDeleted });
      coursesData.reload();
    } catch (err) {
      setMessage({ type: "error", text: errorText(err, L.courseDeleted) });
    }
  }

  /* ------------------------------ offerings ------------------------------ */

  function openOfferingCreate() {
    setEditingOffering(null);
    setOfferingForm({ ...EMPTY_OFFERING });
    setOfferingModal(true);
  }
  function openOfferingEdit(o: Offering) {
    setEditingOffering(o);
    setOfferingForm({
      courseId: String(o.courseId), sessionYear: o.sessionYear, section: o.section ?? "",
      staffId: o.staffId ? String(o.staffId) : "", maxSeats: o.maxSeats ? String(o.maxSeats) : "",
    });
    setOfferingModal(true);
  }
  async function submitOffering(e: React.FormEvent) {
    e.preventDefault();
    setSaving(true);
    try {
      await api(editingOffering ? `/api/portal/campus/offerings/${editingOffering.id}` : "/api/portal/campus/offerings", {
        method: editingOffering ? "PATCH" : "POST",
        body: JSON.stringify(offeringForm),
      });
      setOfferingModal(false);
      setMessage({ type: "success", text: L.offeringSaved });
      offeringsData.reload();
    } catch (err) {
      setMessage({ type: "error", text: errorText(err, L.offeringSaved) });
    } finally {
      setSaving(false);
    }
  }
  async function deleteOffering(o: Offering) {
    if (!(await emsConfirm({ message: L.confirmDeleteOffering, danger: true }))) return;
    try {
      await api(`/api/portal/campus/offerings/${o.id}`, { method: "DELETE" });
      setMessage({ type: "success", text: L.offeringDeleted });
      offeringsData.reload();
    } catch (err) {
      setMessage({ type: "error", text: errorText(err, L.offeringDeleted) });
    }
  }

  const tabs: { id: Tab; label: string }[] = [
    { id: "programs", label: L.tabPrograms },
    { id: "terms", label: L.tabTerms },
    { id: "courses", label: L.tabCourses },
    { id: "offerings", label: L.tabOfferings },
    { id: "routine", label: L.tabRoutine },
  ];

  /* ------------------------------ routine ------------------------------ */

  function openSlotCreate() {
    setSlotForm({ offeringId: "", dayOfWeek: "SUN", startTime: "10:00", endTime: "11:30", room: "" });
    setSlotModal(true);
  }
  async function submitSlot(e: React.FormEvent) {
    e.preventDefault();
    setSaving(true);
    try {
      await api("/api/portal/campus/slots", { method: "POST", body: JSON.stringify(slotForm) });
      setSlotModal(false);
      setMessage({ type: "success", text: L.slotSaved });
      slotsData.reload();
    } catch (err) {
      const code = err instanceof Error ? err.message : "";
      setMessage({
        type: "error",
        text:
          code === "COURSE_CLASH" ? L.errCourseClash :
          code === "TEACHER_CLASH" ? L.errTeacherClash :
          code === "ROOM_CLASH" ? L.errRoomClash :
          L.slotSaved,
      });
    } finally {
      setSaving(false);
    }
  }
  async function deleteSlot(x: Slot) {
    if (!(await emsConfirm({ message: L.confirmDeleteSlot, danger: true }))) return;
    try {
      await api(`/api/portal/campus/slots/${x.id}`, { method: "DELETE" });
      setMessage({ type: "success", text: L.slotDeleted });
      slotsData.reload();
    } catch {
      setMessage({ type: "error", text: t.common.tryAgain });
    }
  }
  const slots = slotsData.data?.slots ?? [];
  const slotsByDay = DAYS.map((d) => ({ day: d, items: slots.filter((x) => x.dayOfWeek === d) })).filter((g) => g.items.length > 0);

  const programOptions = (value: string, onChange: (v: string) => void, label: string, required = false) => (
    <Select label={label} required={required} value={value} onChange={(e) => onChange(e.target.value)}>
      <option value="">—</option>
      {programs.map((p) => (
        <option key={p.id} value={p.id}>{nm(p.name, p.nameBn)}</option>
      ))}
    </Select>
  );

  return (
    <div>
      <PageHeader
        title={L.title}
        subtitle={L.subtitle}
        action={
          <Button
            onClick={() => {
              if (tab === "programs") openProgramCreate();
              else if (tab === "terms") openTermCreate();
              else if (tab === "courses") openCourseCreate();
              else if (tab === "routine") openSlotCreate();
              else openOfferingCreate();
            }}
          >
            <IconPlus className="svg-16" />
            <span className="ms-1">
              {tab === "programs" ? L.newProgram : tab === "terms" ? L.newTerm : tab === "courses" ? L.newCourse : tab === "routine" ? L.newSlot : L.newOffering}
            </span>
          </Button>
        }
      />

      {message && (
        <div className="mb-4">
          <Alert type={message.type} onClose={() => setMessage(null)}>{message.text}</Alert>
        </div>
      )}

      <ul className="nav nav-tabs mb-4">
        {tabs.map((x) => (
          <li className="nav-item" key={x.id}>
            <button className={`nav-link f-w-600 ${tab === x.id ? "active" : ""}`} type="button" onClick={() => setTab(x.id)}>
              {x.label}
            </button>
          </li>
        ))}
      </ul>

      {/* -------------------------- Programs tab -------------------------- */}
      {tab === "programs" && (
        <div className="card">
          {programsData.loading && !programsData.data ? (
            <div className="card-body text-center py-4"><span className="spinner-border text-primary" role="status" /></div>
          ) : programs.length === 0 ? (
            <div className="card-body"><EmptyState title={L.noPrograms} /></div>
          ) : (
            <div className="table-responsive">
              <table className="table table-hover align-middle mb-0">
                <thead className="ems-table-head">
                  <tr>
                    <th>{L.thProgram}</th>
                    <th>{L.thCode}</th>
                    <th>{L.thDegree}</th>
                    <th>{L.thDuration}</th>
                    <th>{L.fieldTotalCredits}</th>
                    <th>{L.thScale}</th>
                    <th className="text-center">{L.thTerms}</th>
                    <th className="text-center">{L.thCourses}</th>
                    <th className="text-center">{L.thStudents}</th>
                    <th className="text-center">{L.thExams}</th>
                    <th className="text-end">{t.common.actions}</th>
                  </tr>
                </thead>
                <tbody>
                  {programs.map((p) => (
                    <tr key={p.id}>
                      <td>
                        <p className="mb-0 f-w-700">{nm(p.name, p.nameBn)}</p>
                        <p className="mb-0 ems-fs-11 text-muted">{[p.faculty, p.department].filter(Boolean).join(" · ") || "—"}</p>
                      </td>
                      <td><span className="badge badge-secondary">{p.code}</span></td>
                      <td className="ems-fs-13">{L[`degree_${p.degreeLevel}` as keyof typeof L] ?? p.degreeLevel}</td>
                      <td className="text-center">{p.durationYears}</td>
                      <td className="text-center">{p.totalCredits > 0 ? p.totalCredits : "—"}</td>
                      <td className="ems-fs-12">{p.gradeScale === "GPA5" ? "GPA 5.00" : "GPA 4.00"}</td>
                      <td className="text-center f-w-700">{p._count?.terms ?? 0}</td>
                      <td className="text-center f-w-700">{p._count?.courses ?? 0}</td>
                      <td className="text-center f-w-700">{p._count?.students ?? 0}</td>
                      <td className="text-center f-w-700">{p._count?.exams ?? 0}</td>
                      <td className="text-end">
                        <button className="btn btn-sm btn-light me-1" onClick={() => openProgramEdit(p)} title={t.common.edit}><IconEdit className="svg-16" /></button>
                        <button className="btn btn-sm btn-light text-danger" onClick={() => deleteProgram(p)} title={t.common.delete}><IconTrash className="svg-16" /></button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      )}

      {/* ---------------------------- Terms tab ---------------------------- */}
      {tab === "terms" && (
        <div className="card">
          <div className="card-header">
            <div className="row g-2 align-items-end">
              <div className="col-md-4">
                <Select label={L.thProgram} wrapperClassName="form-group mb-0" value={termProgram} onChange={(e) => { setTermProgram(e.target.value); termsPager.setPage(1); }}>
                  <option value="">{L.allPrograms}</option>
                  {programs.map((p) => <option key={p.id} value={p.id}>{nm(p.name, p.nameBn)}</option>)}
                </Select>
              </div>
            </div>
          </div>
          {termsData.loading && !termsData.data ? (
            <div className="card-body text-center py-4"><span className="spinner-border text-primary" role="status" /></div>
          ) : filteredTerms.length === 0 ? (
            <div className="card-body"><EmptyState title={L.noTerms} /></div>
          ) : (
            <>
              <div className="table-responsive">
                <table className="table table-hover align-middle mb-0">
                  <thead className="ems-table-head">
                    <tr>
                      <th>{L.thProgram}</th>
                      <th>{L.thTerm}</th>
                      <th className="text-center">{L.thSequence}</th>
                      <th>{L.thStart}</th>
                      <th>{L.thEnd}</th>
                      <th className="text-center">{L.thCourses}</th>
                      <th className="text-end">{t.common.actions}</th>
                    </tr>
                  </thead>
                  <tbody>
                    {termsPager.paged.map((x) => (
                      <tr key={x.id}>
                        <td className="ems-fs-13">{nm(x.program.name, x.program.nameBn)}</td>
                        <td className="f-w-700">{nm(x.name, x.nameBn)}</td>
                        <td className="text-center">{x.sequence}</td>
                        <td className="ems-fs-12">{x.startDate ? formatDate(x.startDate, locale) : "—"}</td>
                        <td className="ems-fs-12">{x.endDate ? formatDate(x.endDate, locale) : "—"}</td>
                        <td className="text-center f-w-700">{x._count?.courses ?? 0}</td>
                        <td className="text-end">
                          <button className="btn btn-sm btn-light me-1" onClick={() => openTermEdit(x)} title={t.common.edit}><IconEdit className="svg-16" /></button>
                          <button className="btn btn-sm btn-light text-danger" onClick={() => deleteTerm(x)} title={t.common.delete}><IconTrash className="svg-16" /></button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <div className="card-footer">
                <Pagination page={termsPager.page} pageCount={termsPager.pageCount} total={termsPager.total} from={termsPager.from} to={termsPager.to} size={termsPager.size} onPageChange={termsPager.setPage} onSizeChange={termsPager.setSize} />
              </div>
            </>
          )}
        </div>
      )}

      {/* --------------------------- Courses tab --------------------------- */}
      {tab === "courses" && (
        <div className="card">
          <div className="card-header">
            <div className="row g-2 align-items-end">
              <div className="col-md-4">
                <Select label={L.thProgram} wrapperClassName="form-group mb-0" value={courseProgram} onChange={(e) => { setCourseProgram(e.target.value); coursesPager.setPage(1); }}>
                  <option value="">{L.allPrograms}</option>
                  {programs.map((p) => <option key={p.id} value={p.id}>{nm(p.name, p.nameBn)}</option>)}
                </Select>
              </div>
            </div>
          </div>
          {coursesData.loading && !coursesData.data ? (
            <div className="card-body text-center py-4"><span className="spinner-border text-primary" role="status" /></div>
          ) : filteredCourses.length === 0 ? (
            <div className="card-body"><EmptyState title={L.noCourses} /></div>
          ) : (
            <>
              <div className="table-responsive">
                <table className="table table-hover align-middle mb-0">
                  <thead className="ems-table-head">
                    <tr>
                      <th>{L.thCourse}</th>
                      <th>{L.thProgram}</th>
                      <th>{L.thTerm}</th>
                      <th className="text-center">{L.thCredits}</th>
                      <th>{L.thType}</th>
                      <th className="text-center">{L.thFull} / {L.thPass}</th>
                      <th className="text-center">{L.thOfferings}</th>
                      <th className="text-end">{t.common.actions}</th>
                    </tr>
                  </thead>
                  <tbody>
                    {coursesPager.paged.map((c) => (
                      <tr key={c.id}>
                        <td>
                          <p className="mb-0 f-w-700">{c.code} — {nm(c.name, c.nameBn)}</p>
                        </td>
                        <td className="ems-fs-13">{nm(c.program.name, c.program.nameBn)}</td>
                        <td className="ems-fs-13">{c.term ? nm(c.term.name, c.term.nameBn) : "—"}</td>
                        <td className="text-center f-w-700">{c.credits}</td>
                        <td><span className="badge badge-secondary">{L[`type_${c.courseType}` as keyof typeof L] ?? c.courseType}</span></td>
                        <td className="text-center">{c.fullMarks} / {c.passMarks}</td>
                        <td className="text-center f-w-700">{c._count?.offerings ?? 0}</td>
                        <td className="text-end">
                          <button className="btn btn-sm btn-light me-1" onClick={() => openCourseEdit(c)} title={t.common.edit}><IconEdit className="svg-16" /></button>
                          <button className="btn btn-sm btn-light text-danger" onClick={() => deleteCourse(c)} title={t.common.delete}><IconTrash className="svg-16" /></button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <div className="card-footer">
                <Pagination page={coursesPager.page} pageCount={coursesPager.pageCount} total={coursesPager.total} from={coursesPager.from} to={coursesPager.to} size={coursesPager.size} onPageChange={coursesPager.setPage} onSizeChange={coursesPager.setSize} />
              </div>
            </>
          )}
        </div>
      )}

      {/* -------------------------- Offerings tab -------------------------- */}
      {tab === "offerings" && (
        <div className="card">
          <div className="card-header">
            <div className="row g-2 align-items-end">
              <div className="col-md-4">
                <Select label={L.thProgram} wrapperClassName="form-group mb-0" value={offeringProgram} onChange={(e) => { setOfferingProgram(e.target.value); offeringsPager.setPage(1); }}>
                  <option value="">{L.allPrograms}</option>
                  {programs.map((p) => <option key={p.id} value={p.id}>{nm(p.name, p.nameBn)}</option>)}
                </Select>
              </div>
            </div>
          </div>
          {offeringsData.loading && !offeringsData.data ? (
            <div className="card-body text-center py-4"><span className="spinner-border text-primary" role="status" /></div>
          ) : filteredOfferings.length === 0 ? (
            <div className="card-body"><EmptyState title={L.noOfferings} /></div>
          ) : (
            <>
              <div className="table-responsive">
                <table className="table table-hover align-middle mb-0">
                  <thead className="ems-table-head">
                    <tr>
                      <th>{L.thCourse}</th>
                      <th>{L.thProgram}</th>
                      <th>{L.thTerm}</th>
                      <th>{L.thSession}</th>
                      <th>{L.thSection}</th>
                      <th>{L.thTeacher}</th>
                      <th className="text-center">{L.thSeats}</th>
                      <th className="text-center">{L.thEnrolled}</th>
                      <th className="text-end">{t.common.actions}</th>
                    </tr>
                  </thead>
                  <tbody>
                    {offeringsPager.paged.map((o) => (
                      <tr key={o.id}>
                        <td className="f-w-700">{o.course.code} — {nm(o.course.name, o.course.nameBn)}</td>
                        <td className="ems-fs-13">{o.course.program ? nm(o.course.program.name, o.course.program.nameBn) : "—"}</td>
                        <td className="ems-fs-13">{o.course.term ? nm(o.course.term.name, o.course.term.nameBn) : "—"}</td>
                        <td><span className="badge badge-info">{o.sessionYear}</span></td>
                        <td>{o.section ? <span className="badge badge-secondary">{o.section}</span> : "—"}</td>
                        <td className="ems-fs-13">{o.staff ? nm(o.staff.name, o.staff.nameBn) : <span className="text-muted">{L.noTeacher}</span>}</td>
                        <td className="text-center">{o.maxSeats ?? "—"}</td>
                        <td className="text-center f-w-700">
                          {o._count?.enrollments ?? 0}
                          {o.maxSeats ? <span className="text-muted"> / {o.maxSeats}</span> : null}
                        </td>
                        <td className="text-end">
                          <button className="btn btn-sm btn-light me-1" onClick={() => openOfferingEdit(o)} title={t.common.edit}><IconEdit className="svg-16" /></button>
                          <button className="btn btn-sm btn-light text-danger" onClick={() => deleteOffering(o)} title={t.common.delete}><IconTrash className="svg-16" /></button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <div className="card-footer">
                <Pagination page={offeringsPager.page} pageCount={offeringsPager.pageCount} total={offeringsPager.total} from={offeringsPager.from} to={offeringsPager.to} size={offeringsPager.size} onPageChange={offeringsPager.setPage} onSizeChange={offeringsPager.setSize} />
              </div>
            </>
          )}
        </div>
      )}

      {/* -------------------------- Routine tab -------------------------- */}
      {tab === "routine" && (
        <div className="card">
          <div className="card-header">
            <div className="row g-2 align-items-end">
              <div className="col-md-4">
                <Select label={L.thProgram} wrapperClassName="form-group mb-0" value={routineProgram} onChange={(e) => setRoutineProgram(e.target.value)}>
                  <option value="">{L.allPrograms}</option>
                  {programs.map((p) => <option key={p.id} value={p.id}>{nm(p.name, p.nameBn)}</option>)}
                </Select>
              </div>
              <div className="col-md-3">
                <Input label={L.fieldSession} placeholder={L.sessionPlaceholder} value={routineSession} onChange={(e) => setRoutineSession(e.target.value)} />
              </div>
            </div>
          </div>
          {slotsData.loading && !slotsData.data ? (
            <div className="card-body text-center py-4"><span className="spinner-border text-primary" role="status" /></div>
          ) : slots.length === 0 ? (
            <div className="card-body"><EmptyState title={L.noSlots} /></div>
          ) : (
            <div className="table-responsive">
              <table className="table table-hover align-middle mb-0">
                <thead className="ems-table-head">
                  <tr>
                    <th>{L.fieldDay}</th>
                    <th>{L.thTime}</th>
                    <th>{L.thCourse}</th>
                    <th>{L.thTerm}</th>
                    <th>{L.thSection}</th>
                    <th>{L.thTeacher}</th>
                    <th>{L.thRoom}</th>
                    <th className="text-end">{t.common.actions}</th>
                  </tr>
                </thead>
                <tbody>
                  {slotsByDay.flatMap((g) =>
                    g.items.map((x, i) => (
                      <tr key={x.id}>
                        {i === 0 ? (
                          <td rowSpan={g.items.length} className="f-w-700 align-middle" style={{ width: 110 }}>
                            {t.days[g.day as keyof typeof t.days] ?? g.day}
                          </td>
                        ) : null}
                        <td className="ems-fs-12">{x.startTime} → {x.endTime}</td>
                        <td className="f-w-700">{x.offering.course.code} — {nm(x.offering.course.name, x.offering.course.nameBn)}</td>
                        <td className="ems-fs-12">{x.offering.course.term ? nm(x.offering.course.term.name, x.offering.course.term.nameBn) : "—"}</td>
                        <td>{x.offering.section ? <span className="badge badge-secondary">{x.offering.section}</span> : "—"}</td>
                        <td className="ems-fs-12">{x.offering.staff ? nm(x.offering.staff.name, x.offering.staff.nameBn) : <span className="text-muted">{L.noTeacher}</span>}</td>
                        <td>{x.room ?? "—"}</td>
                        <td className="text-end">
                          <button className="btn btn-sm btn-light text-danger" onClick={() => deleteSlot(x)} title={t.common.delete}><IconTrash className="svg-16" /></button>
                        </td>
                      </tr>
                    ))
                  )}
                </tbody>
              </table>
            </div>
          )}
        </div>
      )}

      {/* ------------------------- Program modal ------------------------- */}
      <Modal open={programModal} onClose={() => setProgramModal(false)} title={editingProgram ? L.editProgram : L.newProgram} wide>
        <form className="theme-form" onSubmit={submitProgram}>
          <div className="row">
            <div className="col-md-6"><Input label={L.fieldName} required value={programForm.name} onChange={(e) => setProgramForm({ ...programForm, name: e.target.value })} /></div>
            <div className="col-md-6"><Input label={L.fieldNameBn} value={programForm.nameBn} onChange={(e) => setProgramForm({ ...programForm, nameBn: e.target.value })} /></div>
            <div className="col-md-4"><Input label={L.fieldCode} required value={programForm.code} onChange={(e) => setProgramForm({ ...programForm, code: e.target.value })} /></div>
            <div className="col-md-4">
              <Select label={L.fieldDegree} value={programForm.degreeLevel} onChange={(e) => setProgramForm({ ...programForm, degreeLevel: e.target.value })}>
                {DEGREE_LEVELS.map((d) => <option key={d} value={d}>{L[`degree_${d}` as keyof typeof L]}</option>)}
              </Select>
            </div>
            <div className="col-md-4">
              <Select label={L.fieldScale} value={programForm.gradeScale} onChange={(e) => setProgramForm({ ...programForm, gradeScale: e.target.value })}>
                <option value="GPA4">{L.scaleGpa4}</option>
                <option value="GPA5">{L.scaleGpa5}</option>
              </Select>
            </div>
            <div className="col-md-6"><Input label={L.fieldFaculty} value={programForm.faculty} onChange={(e) => setProgramForm({ ...programForm, faculty: e.target.value })} /></div>
            <div className="col-md-6"><Input label={L.fieldDepartment} value={programForm.department} onChange={(e) => setProgramForm({ ...programForm, department: e.target.value })} /></div>
            <div className="col-md-3"><Input label={L.fieldDuration} type="number" min={1} required value={programForm.durationYears} onChange={(e) => setProgramForm({ ...programForm, durationYears: e.target.value })} /></div>
            <div className="col-md-3"><Input label={L.fieldTotalCredits} type="number" min={0} step="0.5" value={programForm.totalCredits} onChange={(e) => setProgramForm({ ...programForm, totalCredits: e.target.value })} /></div>
          </div>
          <div className="d-flex justify-content-end gap-2 mt-3">
            <Button type="button" variant="secondary" onClick={() => setProgramModal(false)}>{t.common.cancel}</Button>
            <Button type="submit" disabled={saving}>{t.common.save}</Button>
          </div>
        </form>
      </Modal>

      {/* --------------------------- Term modal --------------------------- */}
      <Modal open={termModal} onClose={() => setTermModal(false)} title={editingTerm ? L.editTerm : L.newTerm} wide>
        <form className="theme-form" onSubmit={submitTerm}>
          <div className="row">
            <div className="col-md-4">{programOptions(termForm.programId, (v) => setTermForm({ ...termForm, programId: v }), L.thProgram, true)}</div>
            <div className="col-md-4"><Input label={L.fieldTerm} required value={termForm.name} onChange={(e) => setTermForm({ ...termForm, name: e.target.value })} /></div>
            <div className="col-md-4"><Input label={L.fieldTermBn} value={termForm.nameBn} onChange={(e) => setTermForm({ ...termForm, nameBn: e.target.value })} /></div>
            <div className="col-md-4"><Input label={L.fieldSequence} type="number" min={1} required value={termForm.sequence} onChange={(e) => setTermForm({ ...termForm, sequence: e.target.value })} /></div>
            <div className="col-md-4"><DatePicker label={L.thStart} value={termForm.startDate} onChange={(e) => setTermForm({ ...termForm, startDate: e.target.value })} /></div>
            <div className="col-md-4"><DatePicker label={L.thEnd} value={termForm.endDate} onChange={(e) => setTermForm({ ...termForm, endDate: e.target.value })} /></div>
          </div>
          <div className="d-flex justify-content-end gap-2 mt-3">
            <Button type="button" variant="secondary" onClick={() => setTermModal(false)}>{t.common.cancel}</Button>
            <Button type="submit" disabled={saving}>{t.common.save}</Button>
          </div>
        </form>
      </Modal>

      {/* -------------------------- Course modal -------------------------- */}
      <Modal open={courseModal} onClose={() => setCourseModal(false)} title={editingCourse ? L.editCourse : L.newCourse} wide>
        <form className="theme-form" onSubmit={submitCourse}>
          <div className="row">
            <div className="col-md-4">{programOptions(courseForm.programId, (v) => setCourseForm({ ...courseForm, programId: v, termId: "" }), L.thProgram, true)}</div>
            <div className="col-md-4">
              <Select label={L.fieldTerm} value={courseForm.termId} onChange={(e) => setCourseForm({ ...courseForm, termId: e.target.value })}>
                <option value="">—</option>
                {terms.filter((x) => String(x.programId) === courseForm.programId).map((x) => (
                  <option key={x.id} value={x.id}>{nm(x.name, x.nameBn)}</option>
                ))}
              </Select>
            </div>
            <div className="col-md-4"><Input label={L.fieldCourseCode} required value={courseForm.code} onChange={(e) => setCourseForm({ ...courseForm, code: e.target.value })} /></div>
            <div className="col-md-6"><Input label={L.fieldCourseName} required value={courseForm.name} onChange={(e) => setCourseForm({ ...courseForm, name: e.target.value })} /></div>
            <div className="col-md-6"><Input label={L.fieldCourseNameBn} value={courseForm.nameBn} onChange={(e) => setCourseForm({ ...courseForm, nameBn: e.target.value })} /></div>
            <div className="col-md-3"><Input label={L.fieldCredits} type="number" min={0} step="0.5" value={courseForm.credits} onChange={(e) => setCourseForm({ ...courseForm, credits: e.target.value })} /></div>
            <div className="col-md-3">
              <Select label={L.fieldCourseType} value={courseForm.courseType} onChange={(e) => setCourseForm({ ...courseForm, courseType: e.target.value })}>
                {COURSE_TYPES.map((c) => <option key={c} value={c}>{L[`type_${c}` as keyof typeof L]}</option>)}
              </Select>
            </div>
            <div className="col-md-3"><Input label={L.fieldFull} type="number" min={1} value={courseForm.fullMarks} onChange={(e) => setCourseForm({ ...courseForm, fullMarks: e.target.value })} /></div>
            <div className="col-md-3"><Input label={L.fieldPass} type="number" min={0} value={courseForm.passMarks} onChange={(e) => setCourseForm({ ...courseForm, passMarks: e.target.value })} /></div>
          </div>
          <div className="d-flex justify-content-end gap-2 mt-3">
            <Button type="button" variant="secondary" onClick={() => setCourseModal(false)}>{t.common.cancel}</Button>
            <Button type="submit" disabled={saving}>{t.common.save}</Button>
          </div>
        </form>
      </Modal>

      {/* ------------------------- Offering modal ------------------------- */}
      <Modal open={offeringModal} onClose={() => setOfferingModal(false)} title={editingOffering ? L.editOffering : L.newOffering} wide>
        <form className="theme-form" onSubmit={submitOffering}>
          <div className="row">
            <div className="col-md-6">
              <Select label={L.fieldCourse} required value={offeringForm.courseId} onChange={(e) => setOfferingForm({ ...offeringForm, courseId: e.target.value })}>
                <option value="">—</option>
                {courses.map((c) => (
                  <option key={c.id} value={c.id}>{c.code} — {nm(c.name, c.nameBn)} ({nm(c.program.name, c.program.nameBn)})</option>
                ))}
              </Select>
            </div>
            <div className="col-md-3"><Input label={L.fieldSession} required placeholder={L.sessionPlaceholder} value={offeringForm.sessionYear} onChange={(e) => setOfferingForm({ ...offeringForm, sessionYear: e.target.value })} /></div>
            <div className="col-md-3"><Input label={L.fieldSection} value={offeringForm.section} onChange={(e) => setOfferingForm({ ...offeringForm, section: e.target.value })} /></div>
            <div className="col-md-4">
              <Select label={L.fieldTeacher} value={offeringForm.staffId} onChange={(e) => setOfferingForm({ ...offeringForm, staffId: e.target.value })}>
                <option value="">{L.noTeacher}</option>
                {teachers.map((s) => (
                  <option key={s.id} value={s.id}>{nm(s.name, s.nameBn)}{s.designation ? ` — ${s.designation}` : ""}</option>
                ))}
              </Select>
            </div>
            <div className="col-md-3"><Input label={L.fieldSeats} type="number" min={1} value={offeringForm.maxSeats} onChange={(e) => setOfferingForm({ ...offeringForm, maxSeats: e.target.value })} /></div>
          </div>
          <div className="d-flex justify-content-end gap-2 mt-3">
            <Button type="button" variant="secondary" onClick={() => setOfferingModal(false)}>{t.common.cancel}</Button>
            <Button type="submit" disabled={saving}>{t.common.save}</Button>
          </div>
        </form>
      </Modal>

      {/* -------------------------- Slot modal -------------------------- */}
      <Modal open={slotModal} onClose={() => setSlotModal(false)} title={L.newSlot} wide>
        <form className="theme-form" onSubmit={submitSlot}>
          <div className="row">
            <div className="col-md-6">
              <Select label={L.fieldOffering} required value={slotForm.offeringId} onChange={(e) => setSlotForm({ ...slotForm, offeringId: e.target.value })}>
                <option value="">—</option>
                {offerings
                  .filter((o) => (!routineProgram || o.course.program?.id === Number(routineProgram)) && (!routineSession || o.sessionYear === routineSession))
                  .map((o) => (
                    <option key={o.id} value={o.id}>
                      {o.course.code} — {nm(o.course.name, o.course.nameBn)} ({o.sessionYear}{o.section ? ` · ${o.section}` : ""})
                    </option>
                  ))}
              </Select>
            </div>
            <div className="col-md-3">
              <Select label={L.fieldDay} required value={slotForm.dayOfWeek} onChange={(e) => setSlotForm({ ...slotForm, dayOfWeek: e.target.value })}>
                {DAYS.map((d) => <option key={d} value={d}>{t.days[d as keyof typeof t.days]}</option>)}
              </Select>
            </div>
            <div className="col-md-3"><Input label={L.fieldRoom} value={slotForm.room} onChange={(e) => setSlotForm({ ...slotForm, room: e.target.value })} /></div>
            <div className="col-md-3"><TimePicker label={t.portal.campusExamsPage.fieldStart} value={slotForm.startTime} onChange={(e) => setSlotForm({ ...slotForm, startTime: e.target.value })} /></div>
            <div className="col-md-3"><TimePicker label={t.portal.campusExamsPage.fieldEnd} value={slotForm.endTime} onChange={(e) => setSlotForm({ ...slotForm, endTime: e.target.value })} /></div>
          </div>
          <div className="d-flex justify-content-end gap-2 mt-3">
            <Button type="button" variant="secondary" onClick={() => setSlotModal(false)}>{t.common.cancel}</Button>
            <Button type="submit" disabled={saving}>{t.common.save}</Button>
          </div>
        </form>
      </Modal>
    </div>
  );
}
