import { useEffect, useMemo, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  Plus,
  Search,
  Trash2,
  Pencil,
  Users,
  GraduationCap,
  BookOpen,
  Layers,
  UserPlus,
  UserMinus,
  Loader2,
  Sparkles,
  CheckCircle2,
  Circle,
  Settings2,
} from "lucide-react";

import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import { Textarea } from "@/components/ui/textarea";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";

import { classroomsService } from "@/services/classrooms.service";
import { useStudents, useTeachers, useCourses } from "@/hooks/queries";
import { lmsService } from "@/services";
import { useToast } from "@/hooks/use-toast";
import { useAuth } from "@/contexts/AuthContext";
import type { Classroom, LmsBranch } from "@/types";

type ClassroomForm = {
  name: string;
  code: string;
  capacity: string;
  notes: string;
  branch_id: string;
  active: boolean;
};

const EMPTY_FORM: ClassroomForm = {
  name: "",
  code: "",
  capacity: "30",
  notes: "",
  branch_id: "",
  active: true,
};

export default function ClassroomsPage() {
  const { toast } = useToast();
  const qc = useQueryClient();
  const { selectedEntity } = useAuth();

  const [search, setSearch] = useState("");
  const [createOpen, setCreateOpen] = useState(false);
  const [editing, setEditing] = useState<Classroom | null>(null);
  const [form, setForm] = useState<ClassroomForm>(EMPTY_FORM);
  const [activeId, setActiveId] = useState<number | null>(null);

  // Reference data
  const studentsQ = useStudents({ size: 500 });
  const teachersQ = useTeachers({ size: 500 });
  const coursesQ = useCourses({ size: 500 });

  const branchesQ = useQuery({
    queryKey: ["lms-branches", selectedEntity?.id ?? 0],
    queryFn: async () => (await lmsService.listBranches({ size: 200, active: true })).items,
  });

  const classroomsQ = useQuery({
    queryKey: ["lms-classrooms", selectedEntity?.id ?? 0, search],
    queryFn: async () =>
      (await classroomsService.list({ size: 200, search: search.trim() || undefined })).items,
  });

  const detailQ = useQuery({
    queryKey: ["lms-classroom-detail", activeId],
    queryFn: () => classroomsService.getById(activeId as number),
    enabled: !!activeId,
  });

  // ── Mutations ──────────────────────────────────────────────────────
  const createMut = useMutation({
    mutationFn: () =>
      classroomsService.create({
        name: form.name,
        code: form.code || undefined,
        capacity: Number(form.capacity || 30),
        notes: form.notes || undefined,
        branch_id: form.branch_id ? Number(form.branch_id) : null,
        active: form.active,
      }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["lms-classrooms"] });
      setCreateOpen(false);
      setForm(EMPTY_FORM);
      toast({ title: "Classroom created" });
    },
    onError: (e: Error) =>
      toast({ title: "Error", description: e.message, variant: "destructive" }),
  });

  const updateMut = useMutation({
    mutationFn: () =>
      classroomsService.update(editing!.id, {
        name: form.name,
        code: form.code || undefined,
        capacity: Number(form.capacity || 30),
        notes: form.notes || undefined,
        branch_id: form.branch_id ? Number(form.branch_id) : null,
        active: form.active,
      }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["lms-classrooms"] });
      qc.invalidateQueries({ queryKey: ["lms-classroom-detail"] });
      setEditing(null);
      setForm(EMPTY_FORM);
      toast({ title: "Classroom updated" });
    },
    onError: (e: Error) =>
      toast({ title: "Error", description: e.message, variant: "destructive" }),
  });

  const deleteMut = useMutation({
    mutationFn: (id: number) => classroomsService.delete(id),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["lms-classrooms"] });
      if (activeId) setActiveId(null);
      toast({ title: "Classroom deleted" });
    },
    onError: (e: Error) =>
      toast({ title: "Error", description: e.message, variant: "destructive" }),
  });

  const setStudentsMut = useMutation({
    mutationFn: ({ id, ids }: { id: number; ids: number[] }) =>
      classroomsService.setStudents(id, ids, "set"),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["lms-classrooms"] });
      qc.invalidateQueries({ queryKey: ["lms-classroom-detail"] });
      toast({ title: "Roster updated" });
    },
  });

  const setTeachersMut = useMutation({
    mutationFn: ({ id, ids }: { id: number; ids: number[] }) =>
      classroomsService.setTeachers(id, ids, "set"),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["lms-classrooms"] });
      qc.invalidateQueries({ queryKey: ["lms-classroom-detail"] });
      toast({ title: "Homeroom teachers updated" });
    },
  });

  const assignCourseMut = useMutation({
    mutationFn: ({
      id,
      payload,
    }: {
      id: number;
      payload: { course_id: number; section_id?: number; term_key?: string };
    }) => classroomsService.assignCourse(id, payload),
    onSuccess: (res) => {
      qc.invalidateQueries({ queryKey: ["lms-classrooms"] });
      qc.invalidateQueries({ queryKey: ["lms-classroom-detail"] });
      qc.invalidateQueries({ queryKey: ["lms", "batches"] });
      toast({
        title: "Course assigned",
        description: `Batch "${res.batch.name}" — ${res.batch.student_count} student(s) enrolled`,
      });
    },
    onError: (e: Error) =>
      toast({ title: "Error", description: e.message, variant: "destructive" }),
  });

  const detachCourseMut = useMutation({
    mutationFn: ({ id, courseId }: { id: number; courseId: number }) =>
      classroomsService.detachCourse(id, courseId),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["lms-classroom-detail"] });
      toast({ title: "Course detached", description: "Existing batch & enrollments are kept." });
    },
  });

  // ── Derived data ──────────────────────────────────────────────────
  const items = classroomsQ.data ?? [];
  const branches = branchesQ.data ?? [];
  const allStudents = studentsQ.data?.items ?? [];
  const allTeachers = teachersQ.data?.items ?? [];
  const allCourses = coursesQ.data?.items ?? [];
  const detail = detailQ.data;

  const filtered = useMemo(() => {
    const q = search.toLowerCase();
    return items.filter(
      (c) =>
        c.name.toLowerCase().includes(q) ||
        c.code.toLowerCase().includes(q) ||
        (c.branch_name || "").toLowerCase().includes(q),
    );
  }, [items, search]);

  function startEdit(c: Classroom) {
    setEditing(c);
    setForm({
      name: c.name,
      code: c.code,
      capacity: String(c.capacity || 30),
      notes: c.notes || "",
      branch_id: c.branch_id ? String(c.branch_id) : "",
      active: c.active,
    });
  }

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold tracking-tight">Classrooms</h1>
          <p className="text-muted-foreground">
            Homerooms — assign students, teachers and courses. Assigning a course auto-creates a
            batch and enrolls the classroom roster.
          </p>
        </div>
        <Button size="sm" onClick={() => { setEditing(null); setForm(EMPTY_FORM); setCreateOpen(true); }}>
          <Plus className="h-4 w-4 mr-1" /> New Classroom
        </Button>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-[360px_1fr] gap-4">
        {/* Left list */}
        <Card className="border-0 shadow-sm">
          <CardContent className="p-3 space-y-3">
            <div className="relative">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
              <Input
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                placeholder="Search classrooms…"
                className="pl-9"
              />
            </div>

            {classroomsQ.isLoading ? (
              <div className="py-10 flex justify-center">
                <Loader2 className="h-5 w-5 animate-spin text-muted-foreground" />
              </div>
            ) : filtered.length === 0 ? (
              <div className="py-10 text-center text-sm text-muted-foreground">
                No classrooms yet.
              </div>
            ) : (
              <div className="space-y-1 max-h-[60vh] overflow-y-auto">
                {filtered.map((c) => (
                  <button
                    key={c.id}
                    onClick={() => setActiveId(c.id)}
                    className={`w-full text-left p-3 rounded-md border transition-colors ${
                      activeId === c.id
                        ? "border-primary bg-primary/5"
                        : "border-transparent hover:bg-muted/40"
                    }`}
                  >
                    <div className="flex items-center justify-between">
                      <span className="font-medium truncate">{c.name}</span>
                      <Badge variant="secondary" className="ml-2 shrink-0">{c.code}</Badge>
                    </div>
                    <div className="text-xs text-muted-foreground mt-1 flex flex-wrap gap-2">
                      {c.branch_name && <span>· {c.branch_name}</span>}
                      <span>· {c.student_count} students</span>
                      <span>· {c.course_count} courses</span>
                      <span>· {c.batch_count} batches</span>
                    </div>
                  </button>
                ))}
              </div>
            )}
          </CardContent>
        </Card>

        {/* Right detail */}
        <Card className="border-0 shadow-sm">
          <CardContent className="p-4">
            {!activeId ? (
              <div className="py-20 text-center text-sm text-muted-foreground">
                Select a classroom on the left to manage its roster, teachers, courses and batches.
              </div>
            ) : detailQ.isLoading || !detail ? (
              <div className="py-20 flex justify-center">
                <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
              </div>
            ) : (
              <div className="space-y-4">
                <div className="flex items-start justify-between gap-2">
                  <div>
                    <div className="flex items-center gap-2">
                      <h2 className="text-xl font-semibold">{detail.name}</h2>
                      <Badge variant="secondary">{detail.code}</Badge>
                      {!detail.active && <Badge variant="outline">Inactive</Badge>}
                    </div>
                    <div className="text-sm text-muted-foreground mt-1">
                      {detail.branch_name ? `Branch: ${detail.branch_name} · ` : ""}
                      Capacity: {detail.capacity}
                    </div>
                  </div>
                  <div className="flex gap-1">
                    <Button variant="outline" size="sm" onClick={() => startEdit(detail)}>
                      <Pencil className="h-3.5 w-3.5 mr-1" /> Edit
                    </Button>
                    <Button
                      variant="outline"
                      size="sm"
                      className="text-destructive"
                      onClick={() => {
                        if (window.confirm(`Delete "${detail.name}"?`))
                          deleteMut.mutate(detail.id);
                      }}
                    >
                      <Trash2 className="h-3.5 w-3.5 mr-1" /> Delete
                    </Button>
                  </div>
                </div>

                <WorkflowGuide
                  hasRoster={detail.student_count > 0}
                  hasTeachers={detail.teacher_count > 0}
                  hasCourses={detail.course_count > 0}
                  hasBatches={detail.batch_count > 0}
                />

                <Tabs defaultValue="roster">
                  <TabsList>
                    <TabsTrigger value="roster">
                      <Users className="h-3.5 w-3.5 mr-1" /> 1. Roster
                      <Badge variant="secondary" className="ml-2">{detail.student_count}</Badge>
                    </TabsTrigger>
                    <TabsTrigger value="teachers">
                      <GraduationCap className="h-3.5 w-3.5 mr-1" /> 2. Faculty
                      <Badge variant="secondary" className="ml-2">{detail.teacher_count}</Badge>
                    </TabsTrigger>
                    <TabsTrigger value="courses">
                      <BookOpen className="h-3.5 w-3.5 mr-1" /> 3. Courses
                      <Badge variant="secondary" className="ml-2">{detail.course_count}</Badge>
                    </TabsTrigger>
                    <TabsTrigger value="batches">
                      <Layers className="h-3.5 w-3.5 mr-1" /> 4. Batches
                      <Badge variant="secondary" className="ml-2">{detail.batch_count}</Badge>
                    </TabsTrigger>
                  </TabsList>

                  {/* Roster ------------------------------------------ */}
                  <TabsContent value="roster" className="mt-4">
                    <RosterPanel
                      classroomId={detail.id}
                      currentIds={detail.student_ids}
                      allStudents={allStudents}
                      onSave={(ids) => setStudentsMut.mutate({ id: detail.id, ids })}
                      saving={setStudentsMut.isPending}
                    />
                  </TabsContent>

                  {/* Faculty ----------------------------------------- */}
                  <TabsContent value="teachers" className="mt-4">
                    <FacultyPanel
                      classroomId={detail.id}
                      currentIds={detail.teacher_ids}
                      allTeachers={allTeachers}
                      onSave={(ids) => setTeachersMut.mutate({ id: detail.id, ids })}
                      saving={setTeachersMut.isPending}
                    />
                  </TabsContent>

                  {/* Courses ----------------------------------------- */}
                  <TabsContent value="courses" className="mt-4">
                    <CoursesPanel
                      classroom={detail}
                      allCourses={allCourses}
                      onAssign={(payload) =>
                        assignCourseMut.mutate({ id: detail.id, payload })
                      }
                      onDetach={(courseId) =>
                        detachCourseMut.mutate({ id: detail.id, courseId })
                      }
                      assigning={assignCourseMut.isPending}
                    />
                  </TabsContent>

                  {/* Batches ----------------------------------------- */}
                  <TabsContent value="batches" className="mt-4">
                    <BatchesPanel
                      batches={detail.batches ?? []}
                      classroomStudentIds={detail.student_ids}
                      classroomTeacherIds={detail.teacher_ids}
                      allStudents={allStudents}
                      allTeachers={allTeachers}
                      onChanged={() => {
                        qc.invalidateQueries({ queryKey: ["lms-classroom-detail"] });
                        qc.invalidateQueries({ queryKey: ["lms", "batches"] });
                      }}
                    />
                  </TabsContent>
                </Tabs>
              </div>
            )}
          </CardContent>
        </Card>
      </div>

      {/* Create / Edit dialog */}
      <Dialog
        open={createOpen || !!editing}
        onOpenChange={(v) => {
          if (!v) {
            setCreateOpen(false);
            setEditing(null);
            setForm(EMPTY_FORM);
          }
        }}
      >
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>{editing ? "Edit Classroom" : "Create Classroom"}</DialogTitle>
            <DialogDescription>
              A classroom is a homeroom: a physical room hosting a group of students, with
              homeroom teachers and the courses they study.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-3">
            <div className="space-y-1">
              <Label>Name</Label>
              <Input
                value={form.name}
                onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}
                placeholder="e.g. Grade 7-A"
              />
            </div>
            <div className="grid grid-cols-2 gap-2">
              <div className="space-y-1">
                <Label>Code</Label>
                <Input
                  value={form.code}
                  onChange={(e) => setForm((f) => ({ ...f, code: e.target.value }))}
                  placeholder="G7A"
                />
              </div>
              <div className="space-y-1">
                <Label>Capacity</Label>
                <Input
                  type="number"
                  min={1}
                  value={form.capacity}
                  onChange={(e) => setForm((f) => ({ ...f, capacity: e.target.value }))}
                />
              </div>
            </div>
            <div className="space-y-1">
              <Label>Branch</Label>
              <Select
                value={form.branch_id || "none"}
                onValueChange={(v) =>
                  setForm((f) => ({ ...f, branch_id: v === "none" ? "" : v }))
                }
              >
                <SelectTrigger>
                  <SelectValue placeholder="No branch" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="none">No branch</SelectItem>
                  {branches.map((b: LmsBranch) => (
                    <SelectItem key={b.id} value={String(b.id)}>{b.name}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-1">
              <Label>Notes</Label>
              <Textarea
                value={form.notes}
                onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}
                rows={2}
              />
            </div>
            <label className="flex items-center gap-2 text-sm">
              <Checkbox
                checked={form.active}
                onCheckedChange={(v) => setForm((f) => ({ ...f, active: !!v }))}
              />
              Active
            </label>
          </div>
          <DialogFooter>
            <Button
              variant="outline"
              onClick={() => {
                setCreateOpen(false);
                setEditing(null);
              }}
            >
              Cancel
            </Button>
            <Button
              disabled={!form.name || createMut.isPending || updateMut.isPending}
              onClick={() => (editing ? updateMut.mutate() : createMut.mutate())}
            >
              {(createMut.isPending || updateMut.isPending) && (
                <Loader2 className="h-3.5 w-3.5 mr-1 animate-spin" />
              )}
              {editing ? "Save" : "Create"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════
// Sub-panels
// ════════════════════════════════════════════════════════════════════════

interface RosterPanelProps {
  classroomId: number;
  currentIds: number[];
  allStudents: { id: number; name: string; email: string }[];
  onSave: (ids: number[]) => void;
  saving: boolean;
}

function RosterPanel({ currentIds, allStudents, onSave, saving }: RosterPanelProps) {
  const [picker, setPicker] = useState(false);
  const [draft, setDraft] = useState<number[]>(currentIds);
  const [q, setQ] = useState("");

  const inRoster = allStudents.filter((s) => currentIds.includes(s.id));
  const candidates = allStudents.filter((s) =>
    `${s.name} ${s.email}`.toLowerCase().includes(q.toLowerCase()),
  );

  function openPicker() {
    setDraft(currentIds);
    setPicker(true);
  }

  function toggle(id: number) {
    setDraft((d) => (d.includes(id) ? d.filter((x) => x !== id) : [...d, id]));
  }

  function remove(id: number) {
    onSave(currentIds.filter((x) => x !== id));
  }

  return (
    <div className="space-y-3">
      <div className="flex justify-between">
        <p className="text-sm text-muted-foreground">
          Students in the homeroom roster. New batches auto-enroll everyone here.
        </p>
        <Button size="sm" onClick={openPicker}>
          <UserPlus className="h-3.5 w-3.5 mr-1" /> Manage Roster
        </Button>
      </div>

      {inRoster.length === 0 ? (
        <div className="py-8 text-center text-sm text-muted-foreground border rounded-md border-dashed">
          No students yet. Click <strong>Manage Roster</strong> to add some.
        </div>
      ) : (
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>Name</TableHead>
              <TableHead>Email</TableHead>
              <TableHead className="w-[80px]" />
            </TableRow>
          </TableHeader>
          <TableBody>
            {inRoster.map((s) => (
              <TableRow key={s.id}>
                <TableCell className="font-medium">{s.name}</TableCell>
                <TableCell className="text-muted-foreground">{s.email}</TableCell>
                <TableCell>
                  <Button
                    size="icon"
                    variant="ghost"
                    className="h-7 w-7 text-destructive"
                    onClick={() => remove(s.id)}
                  >
                    <UserMinus className="h-4 w-4" />
                  </Button>
                </TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      )}

      <Dialog open={picker} onOpenChange={setPicker}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Manage Roster</DialogTitle>
            <DialogDescription>
              Pick the students that belong to this classroom.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-2">
            <div className="relative">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
              <Input
                value={q}
                onChange={(e) => setQ(e.target.value)}
                placeholder="Search…"
                className="pl-9"
              />
            </div>
            <div className="max-h-[40vh] overflow-y-auto space-y-1">
              {candidates.map((s) => (
                <label
                  key={s.id}
                  className="flex items-center gap-2 p-2 rounded hover:bg-muted/40 cursor-pointer"
                >
                  <Checkbox
                    checked={draft.includes(s.id)}
                    onCheckedChange={() => toggle(s.id)}
                  />
                  <div className="flex-1 min-w-0">
                    <p className="text-sm font-medium truncate">{s.name}</p>
                    <p className="text-xs text-muted-foreground">{s.email}</p>
                  </div>
                </label>
              ))}
            </div>
            <p className="text-xs text-muted-foreground">{draft.length} selected</p>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setPicker(false)}>Cancel</Button>
            <Button
              disabled={saving}
              onClick={() => {
                onSave(draft);
                setPicker(false);
              }}
            >
              {saving && <Loader2 className="h-3.5 w-3.5 mr-1 animate-spin" />}
              Save Roster
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

interface FacultyPanelProps {
  classroomId: number;
  currentIds: number[];
  allTeachers: { id: number; name: string; email: string }[];
  onSave: (ids: number[]) => void;
  saving: boolean;
}

function FacultyPanel({ currentIds, allTeachers, onSave, saving }: FacultyPanelProps) {
  const [picker, setPicker] = useState(false);
  const [draft, setDraft] = useState<number[]>(currentIds);

  const list = allTeachers.filter((t) => currentIds.includes(t.id));

  function toggle(id: number) {
    setDraft((d) => (d.includes(id) ? d.filter((x) => x !== id) : [...d, id]));
  }

  return (
    <div className="space-y-3">
      <div className="flex justify-between">
        <p className="text-sm text-muted-foreground">
          Homeroom teachers. They are the default teachers used when assigning a course.
          Per-batch teachers can be different.
        </p>
        <Button
          size="sm"
          onClick={() => {
            setDraft(currentIds);
            setPicker(true);
          }}
        >
          <UserPlus className="h-3.5 w-3.5 mr-1" /> Manage Faculty
        </Button>
      </div>
      {list.length === 0 ? (
        <div className="py-8 text-center text-sm text-muted-foreground border rounded-md border-dashed">
          No homeroom teachers assigned yet.
        </div>
      ) : (
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>Name</TableHead>
              <TableHead>Email</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {list.map((t) => (
              <TableRow key={t.id}>
                <TableCell className="font-medium">{t.name}</TableCell>
                <TableCell className="text-muted-foreground">{t.email}</TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      )}
      <Dialog open={picker} onOpenChange={setPicker}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Manage Faculty</DialogTitle>
          </DialogHeader>
          <div className="max-h-[40vh] overflow-y-auto space-y-1">
            {allTeachers.map((t) => (
              <label
                key={t.id}
                className="flex items-center gap-2 p-2 rounded hover:bg-muted/40 cursor-pointer"
              >
                <Checkbox checked={draft.includes(t.id)} onCheckedChange={() => toggle(t.id)} />
                <div className="flex-1 min-w-0">
                  <p className="text-sm font-medium truncate">{t.name}</p>
                  <p className="text-xs text-muted-foreground">{t.email}</p>
                </div>
              </label>
            ))}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setPicker(false)}>Cancel</Button>
            <Button
              disabled={saving}
              onClick={() => {
                onSave(draft);
                setPicker(false);
              }}
            >
              {saving && <Loader2 className="h-3.5 w-3.5 mr-1 animate-spin" />}
              Save Faculty
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

interface CoursesPanelProps {
  classroom: Classroom;
  allCourses: { id: number; title: string; code: string }[];
  onAssign: (payload: { course_id: number; section_id?: number; term_key?: string }) => void;
  onDetach: (courseId: number) => void;
  assigning: boolean;
}

function CoursesPanel({ classroom, allCourses, onAssign, onDetach, assigning }: CoursesPanelProps) {
  const [pickerOpen, setPickerOpen] = useState(false);
  const [picked, setPicked] = useState<string>("");
  const [pickedSection, setPickedSection] = useState<string>("");
  const [termKey, setTermKey] = useState("");

  const assignedIds = new Set(classroom.course_ids);
  const candidates = allCourses.filter((c) => !assignedIds.has(c.id));
  const assigned = classroom.courses ?? [];
  const sectionsQ = useQuery({
    queryKey: ["course-sections", picked],
    queryFn: () => lmsService.listCourseSections(Number(picked)),
    enabled: !!picked,
  });
  const sections = sectionsQ.data?.items ?? [];

  return (
    <div className="space-y-3">
      <div className="flex justify-between">
        <p className="text-sm text-muted-foreground">
          Assigning a course creates a batch and enrolls the {classroom.student_count} student(s)
          on the roster automatically.
        </p>
        <Button
          size="sm"
          onClick={() => {
            setPicked("");
            setPickedSection("");
            setTermKey("");
            setPickerOpen(true);
          }}
        >
          <Sparkles className="h-3.5 w-3.5 mr-1" /> Assign Course
        </Button>
      </div>
      {assigned.length === 0 ? (
        <div className="py-8 text-center text-sm text-muted-foreground border rounded-md border-dashed">
          No courses assigned yet.
        </div>
      ) : (
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>Course</TableHead>
              <TableHead>Code</TableHead>
              <TableHead className="w-[80px]" />
            </TableRow>
          </TableHeader>
          <TableBody>
            {assigned.map((c) => (
              <TableRow key={c.id}>
                <TableCell className="font-medium">{c.name}</TableCell>
                <TableCell className="text-muted-foreground">{c.code}</TableCell>
                <TableCell>
                  <Button
                    size="icon"
                    variant="ghost"
                    className="h-7 w-7 text-destructive"
                    onClick={() => {
                      if (
                        window.confirm(
                          "Detach course from classroom? Existing batches & enrollments are kept.",
                        )
                      )
                        onDetach(c.id);
                    }}
                  >
                    <Trash2 className="h-4 w-4" />
                  </Button>
                </TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      )}

      <Dialog open={pickerOpen} onOpenChange={setPickerOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Assign Course</DialogTitle>
            <DialogDescription>
              The classroom roster ({classroom.student_count} students) will be auto-enrolled
              into a new batch for the chosen course.
            </DialogDescription>
          </DialogHeader>
          <Select value={picked} onValueChange={setPicked}>
            <SelectTrigger>
              <SelectValue placeholder="Select a course…" />
            </SelectTrigger>
            <SelectContent>
              {candidates.length === 0 ? (
                <div className="px-2 py-3 text-xs text-muted-foreground">
                  All courses already assigned.
                </div>
              ) : (
                candidates.map((c) => (
                  <SelectItem key={c.id} value={String(c.id)}>
                    {c.title} {c.code ? `· ${c.code}` : ""}
                  </SelectItem>
                ))
              )}
            </SelectContent>
          </Select>
          <div className="space-y-1">
            <Label>Section (optional)</Label>
            <Select
              value={pickedSection || "none"}
              onValueChange={(v) => setPickedSection(v === "none" ? "" : v)}
              disabled={!picked}
            >
              <SelectTrigger>
                <SelectValue placeholder="Auto (whole course)" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="none">Auto (whole course)</SelectItem>
                {sections.map((s) => (
                  <SelectItem key={s.id} value={String(s.id)}>
                    {s.name} {s.code ? `· ${s.code}` : ""}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-1">
            <Label>Term Key (optional)</Label>
            <Input
              value={termKey}
              onChange={(e) => setTermKey(e.target.value)}
              placeholder="e.g. 2026-T1"
            />
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setPickerOpen(false)}>Cancel</Button>
            <Button
              disabled={!picked || assigning}
              onClick={() => {
                onAssign({
                  course_id: Number(picked),
                  section_id: pickedSection ? Number(pickedSection) : undefined,
                  term_key: termKey.trim() || undefined,
                });
                setPickerOpen(false);
              }}
            >
              {assigning && <Loader2 className="h-3.5 w-3.5 mr-1 animate-spin" />}
              Assign + Cascade
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

interface BatchesPanelProps {
  batches: NonNullable<Classroom["batches"]>;
  classroomStudentIds: number[];
  classroomTeacherIds: number[];
  allStudents: { id: number; name: string; email: string }[];
  allTeachers: { id: number; name: string; email: string }[];
  onChanged: () => void;
}

function BatchesPanel({
  batches,
  classroomStudentIds,
  classroomTeacherIds,
  allStudents,
  allTeachers,
  onChanged,
}: BatchesPanelProps) {
  const [managing, setManaging] = useState<NonNullable<Classroom["batches"]>[number] | null>(null);

  if (!batches.length) {
    return (
      <div className="py-8 text-center text-sm text-muted-foreground border rounded-md border-dashed">
        No batches yet. Assign a course in the <strong>Courses</strong> tab to create the first one.
      </div>
    );
  }
  return (
    <div className="space-y-3">
      <p className="text-sm text-muted-foreground">
        Each batch is one (course × section × term) for this classroom. The roster and homeroom
        teachers cascade automatically — use <strong>Manage</strong> to override per batch (e.g. a
        single student in a different section, or a different teacher per section).
      </p>

      <Table>
        <TableHeader>
          <TableRow>
            <TableHead>Batch</TableHead>
            <TableHead>Course</TableHead>
            <TableHead>Section</TableHead>
            <TableHead>Students</TableHead>
            <TableHead>Teachers</TableHead>
            <TableHead>Dates</TableHead>
            <TableHead className="w-[120px]" />
          </TableRow>
        </TableHeader>
        <TableBody>
          {batches.map((b) => (
            <TableRow key={b.id}>
              <TableCell>
                <div className="font-medium">{b.name}</div>
                <div className="text-xs text-muted-foreground">{b.code}</div>
              </TableCell>
              <TableCell>{b.course_name || "—"}</TableCell>
              <TableCell>
                {b.course_section_name
                  ? `${b.course_section_name}${b.course_section_code ? ` (${b.course_section_code})` : ""}`
                  : "—"}
              </TableCell>
              <TableCell>{b.student_count}</TableCell>
              <TableCell>{b.teacher_ids?.length ?? 0}</TableCell>
              <TableCell className="text-sm text-muted-foreground">
                {b.start_date && b.end_date ? `${b.start_date} → ${b.end_date}` : "—"}
              </TableCell>
              <TableCell>
                <Button size="sm" variant="outline" onClick={() => setManaging(b)}>
                  <Settings2 className="h-3.5 w-3.5 mr-1" /> Manage
                </Button>
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>

      {managing && (
        <BatchManagerDialog
          batch={managing}
          classroomStudentIds={classroomStudentIds}
          classroomTeacherIds={classroomTeacherIds}
          allStudents={allStudents}
          allTeachers={allTeachers}
          onClose={() => setManaging(null)}
          onChanged={onChanged}
        />
      )}
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════
// Per-batch manager: enroll specific students + assign per-batch teachers
// ════════════════════════════════════════════════════════════════════════

interface BatchManagerDialogProps {
  batch: NonNullable<Classroom["batches"]>[number];
  classroomStudentIds: number[];
  classroomTeacherIds: number[];
  allStudents: { id: number; name: string; email: string }[];
  allTeachers: { id: number; name: string; email: string }[];
  onClose: () => void;
  onChanged: () => void;
}

function BatchManagerDialog({
  batch,
  classroomStudentIds,
  classroomTeacherIds,
  allStudents,
  allTeachers,
  onClose,
  onChanged,
}: BatchManagerDialogProps) {
  const { toast } = useToast();
  const qc = useQueryClient();
  const [tab, setTab] = useState<"students" | "teachers">("students");

  // Live enrollments for this batch (students)
  const enrolledQ = useQuery({
    queryKey: ["batch-students", batch.id],
    queryFn: () => lmsService.getBatchStudents(batch.id),
  });
  const teachersQ = useQuery({
    queryKey: ["batch-teachers", batch.id],
    queryFn: () => lmsService.getBatchTeachers(batch.id),
  });

  const enrolledIds = useMemo(
    () => (enrolledQ.data?.data ?? []).map((s) => s.id),
    [enrolledQ.data],
  );
  const enrolledTeacherIds = useMemo(
    () => (teachersQ.data?.items ?? []).map((t) => t.id),
    [teachersQ.data],
  );

  const [studentDraft, setStudentDraft] = useState<number[]>([]);
  const [teacherDraft, setTeacherDraft] = useState<number[]>([]);
  const [studentSearch, setStudentSearch] = useState("");
  const [teacherSearch, setTeacherSearch] = useState("");

  useEffect(() => setStudentDraft(enrolledIds), [enrolledIds]);
  useEffect(() => setTeacherDraft(enrolledTeacherIds), [enrolledTeacherIds]);

  const studentSaveMut = useMutation({
    mutationFn: async () => {
      const toAdd = studentDraft.filter((id) => !enrolledIds.includes(id));
      const toRemove = enrolledIds.filter((id) => !studentDraft.includes(id));
      if (toAdd.length) await lmsService.addStudentsToBatch(batch.id, toAdd);
      if (toRemove.length) await lmsService.removeStudentsFromBatch(batch.id, toRemove);
      return { added: toAdd.length, removed: toRemove.length };
    },
    onSuccess: (res) => {
      qc.invalidateQueries({ queryKey: ["batch-students", batch.id] });
      onChanged();
      toast({
        title: "Batch roster updated",
        description: `${res.added} added, ${res.removed} removed`,
      });
    },
    onError: (e: Error) =>
      toast({ title: "Error", description: e.message, variant: "destructive" }),
  });

  const teacherSaveMut = useMutation({
    mutationFn: () => lmsService.setBatchTeachers(batch.id, teacherDraft, "set"),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["batch-teachers", batch.id] });
      onChanged();
      toast({ title: "Batch teachers updated" });
    },
    onError: (e: Error) =>
      toast({ title: "Error", description: e.message, variant: "destructive" }),
  });

  const studentCandidates = allStudents.filter((s) =>
    `${s.name} ${s.email}`.toLowerCase().includes(studentSearch.toLowerCase()),
  );
  const teacherCandidates = allTeachers.filter((t) =>
    `${t.name} ${t.email}`.toLowerCase().includes(teacherSearch.toLowerCase()),
  );

  function toggle<T extends number>(setter: (fn: (d: T[]) => T[]) => void) {
    return (id: T) => setter((d) => (d.includes(id) ? d.filter((x) => x !== id) : [...d, id]));
  }

  return (
    <Dialog open onOpenChange={(v) => !v && onClose()}>
      <DialogContent className="max-w-2xl">
        <DialogHeader>
          <DialogTitle>{batch.name}</DialogTitle>
          <DialogDescription>
            <span className="text-xs">
              {batch.course_name || "—"}
              {batch.course_section_name ? ` · Section ${batch.course_section_name}` : ""}
              {batch.term_key ? ` · ${batch.term_key}` : ""}
            </span>
          </DialogDescription>
        </DialogHeader>

        <Tabs value={tab} onValueChange={(v) => setTab(v as "students" | "teachers")}>
          <TabsList>
            <TabsTrigger value="students">
              <Users className="h-3.5 w-3.5 mr-1" /> Students
              <Badge variant="secondary" className="ml-2">{studentDraft.length}</Badge>
            </TabsTrigger>
            <TabsTrigger value="teachers">
              <GraduationCap className="h-3.5 w-3.5 mr-1" /> Teachers
              <Badge variant="secondary" className="ml-2">{teacherDraft.length}</Badge>
            </TabsTrigger>
          </TabsList>

          {/* Students -------------------------------------------------- */}
          <TabsContent value="students" className="mt-3 space-y-2">
            <div className="text-xs text-muted-foreground">
              Pick the students enrolled in this batch. By default the homeroom roster cascades
              here automatically; this override lets you (de)select per batch — useful when a
              section has only a subset of the classroom.
              <Button
                variant="link"
                size="sm"
                className="px-1 h-auto"
                onClick={() => setStudentDraft(classroomStudentIds)}
              >
                reset to classroom roster
              </Button>
            </div>
            <div className="relative">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
              <Input
                value={studentSearch}
                onChange={(e) => setStudentSearch(e.target.value)}
                placeholder="Search students…"
                className="pl-9"
              />
            </div>
            <div className="max-h-[40vh] overflow-y-auto space-y-1 border rounded-md p-1">
              {studentCandidates.map((s) => (
                <label
                  key={s.id}
                  className="flex items-center gap-2 p-2 rounded hover:bg-muted/40 cursor-pointer"
                >
                  <Checkbox
                    checked={studentDraft.includes(s.id)}
                    onCheckedChange={() => toggle<number>(setStudentDraft)(s.id)}
                  />
                  <div className="flex-1 min-w-0">
                    <p className="text-sm font-medium truncate">{s.name}</p>
                    <p className="text-xs text-muted-foreground">{s.email}</p>
                  </div>
                  {classroomStudentIds.includes(s.id) && (
                    <Badge variant="outline" className="text-[10px]">on roster</Badge>
                  )}
                </label>
              ))}
            </div>
            <div className="flex justify-end">
              <Button
                size="sm"
                disabled={studentSaveMut.isPending || enrolledQ.isLoading}
                onClick={() => studentSaveMut.mutate()}
              >
                {studentSaveMut.isPending && (
                  <Loader2 className="h-3.5 w-3.5 mr-1 animate-spin" />
                )}
                Save Batch Students
              </Button>
            </div>
          </TabsContent>

          {/* Teachers -------------------------------------------------- */}
          <TabsContent value="teachers" className="mt-3 space-y-2">
            <div className="text-xs text-muted-foreground">
              Pick the teachers actually teaching this batch. Defaults to the classroom's homeroom
              teachers when the batch is created.
              <Button
                variant="link"
                size="sm"
                className="px-1 h-auto"
                onClick={() => setTeacherDraft(classroomTeacherIds)}
              >
                reset to homeroom teachers
              </Button>
            </div>
            <div className="relative">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
              <Input
                value={teacherSearch}
                onChange={(e) => setTeacherSearch(e.target.value)}
                placeholder="Search teachers…"
                className="pl-9"
              />
            </div>
            <div className="max-h-[40vh] overflow-y-auto space-y-1 border rounded-md p-1">
              {teacherCandidates.map((t) => (
                <label
                  key={t.id}
                  className="flex items-center gap-2 p-2 rounded hover:bg-muted/40 cursor-pointer"
                >
                  <Checkbox
                    checked={teacherDraft.includes(t.id)}
                    onCheckedChange={() => toggle<number>(setTeacherDraft)(t.id)}
                  />
                  <div className="flex-1 min-w-0">
                    <p className="text-sm font-medium truncate">{t.name}</p>
                    <p className="text-xs text-muted-foreground">{t.email}</p>
                  </div>
                  {classroomTeacherIds.includes(t.id) && (
                    <Badge variant="outline" className="text-[10px]">homeroom</Badge>
                  )}
                </label>
              ))}
            </div>
            <div className="flex justify-end">
              <Button
                size="sm"
                disabled={teacherSaveMut.isPending || teachersQ.isLoading}
                onClick={() => teacherSaveMut.mutate()}
              >
                {teacherSaveMut.isPending && (
                  <Loader2 className="h-3.5 w-3.5 mr-1 animate-spin" />
                )}
                Save Batch Teachers
              </Button>
            </div>
          </TabsContent>
        </Tabs>

        <DialogFooter>
          <Button variant="outline" onClick={onClose}>
            Close
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

// ════════════════════════════════════════════════════════════════════════
// 4-step workflow guide (cascade order)
// ════════════════════════════════════════════════════════════════════════

interface WorkflowGuideProps {
  hasRoster: boolean;
  hasTeachers: boolean;
  hasCourses: boolean;
  hasBatches: boolean;
}

function WorkflowGuide({ hasRoster, hasTeachers, hasCourses, hasBatches }: WorkflowGuideProps) {
  const steps: { label: string; done: boolean; hint: string }[] = [
    {
      label: "Add roster",
      done: hasRoster,
      hint: "Pick the students belonging to this homeroom",
    },
    {
      label: "Add homeroom teachers",
      done: hasTeachers,
      hint: "Default teachers used when assigning a course",
    },
    {
      label: "Assign course + section",
      done: hasCourses,
      hint: "Server creates a batch and auto-enrolls roster + teachers",
    },
    {
      label: "Tune per-batch",
      done: hasBatches,
      hint: "Override which students/teachers actually attend each batch",
    },
  ];
  return (
    <div className="rounded-md border bg-muted/30 p-3">
      <div className="text-xs font-medium text-muted-foreground mb-2">
        Assignment workflow — each step cascades to the next:
      </div>
      <ol className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-2">
        {steps.map((s, i) => (
          <li
            key={s.label}
            className="flex items-start gap-2 rounded-md border bg-background p-2"
          >
            {s.done ? (
              <CheckCircle2 className="h-4 w-4 mt-0.5 text-emerald-600 shrink-0" />
            ) : (
              <Circle className="h-4 w-4 mt-0.5 text-muted-foreground shrink-0" />
            )}
            <div className="min-w-0">
              <div className="text-xs font-medium">
                {i + 1}. {s.label}
              </div>
              <div className="text-[11px] text-muted-foreground leading-snug">
                {s.hint}
              </div>
            </div>
          </li>
        ))}
      </ol>
    </div>
  );
}
