/**
 * admin/ExamReview.tsx
 *
 * School-admin queue for teacher-submitted exam groups. The teacher creates
 * the exam content (questions, marks, duration); the admin decides WHEN,
 * WHERE, and TO WHOM by creating a schedule and publishing it. Students
 * only see exams whose schedule has been published
 * (exam_schedules.is_active = 1) per GET /api/exams/available.
 */

import { useEffect, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useExamStore } from '../../store/exams';
import api from '../../store/api';
import { useAuthStore } from '../../store/auth';
import { useToast } from '../../components/Toast';
import { useConfirmation } from '../../hooks/useConfirmation';
import {
  ChevronRight, Calendar, FileText, MapPin, Globe, X,
  CheckCircle2, XCircle, Loader2, AlertTriangle
} from 'lucide-react';

interface ClassOption { id: number; name: string; }
interface SubjectOption { id: number; name: string; class_id?: number; }

export default function ExamReview() {
  const { user } = useAuthStore();
  const isAdmin = user?.role === 'school_admin' || user?.role === 'systems_admin';
  const toast = useToast();
  const { confirm } = useConfirmation();
  const { pendingGroups, fetchPendingGroups, createSchedule, publishSchedule, rejectGroup, bulkRejectGroups } = useExamStore();
  const [loading, setLoading] = useState(true);
  const [reviewing, setReviewing] = useState<any | null>(null);
  // Bulk-reject state: which group ids are checked, and whether the
  // bulk-reject reason modal is open. The selected set lives in a Set
  // for O(1) toggle; we sync to an array only when calling the API.
  const [selected, setSelected] = useState<Set<number>>(new Set());
  const [bulkRejectOpen, setBulkRejectOpen] = useState(false);
  const [bulkRejectReason, setBulkRejectReason] = useState('');
  const [bulkRejectBusy, setBulkRejectBusy] = useState(false);

  const [searchParams] = useSearchParams();
  const paramId = searchParams.get('id');

  useEffect(() => {
    if (!isAdmin) return;
    let cancelled = false;
    (async () => {
      try {
        setLoading(true);
        await fetchPendingGroups();
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, [isAdmin, fetchPendingGroups]);

  useEffect(() => {
    if (paramId && pendingGroups.length > 0) {
      const match = pendingGroups.find((g) => String(g.id) === String(paramId));
      if (match) setReviewing(match);
    }
  }, [paramId, pendingGroups]);

  // Prune the selected set to only ids that are still in the queue
  // (a single reject or a refresh can drop a row, and the checkbox
  // should follow). Runs whenever the queue shape changes.
  useEffect(() => {
    setSelected(prev => {
      const stillThere = pendingGroups.filter(g => prev.has(g.id));
      if (stillThere.length === prev.size) return prev; // no-op
      return new Set(stillThere.map(g => g.id));
    });
  }, [pendingGroups]);

  const toggleOne = (id: number) => {
    setSelected(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  };

  const toggleAll = () => {
    setSelected(prev => {
      if (prev.size === pendingGroups.length) return new Set();
      return new Set(pendingGroups.map(g => g.id));
    });
  };

  const handleBulkReject = async () => {
    if (!bulkRejectReason.trim()) return;
    if (selected.size === 0) return;
    const ok = await confirm(
      `Reject ${selected.size} exam${selected.size === 1 ? '' : 's'}?`,
      `All ${selected.size} selected group(s) will be marked rejected with the reason you provided. The teachers will see this reason on next view.`,
      { confirmText: 'Reject all', variant: 'danger' }
    );
    if (!ok) return;
    setBulkRejectBusy(true);
    try {
      const result = await bulkRejectGroups([...selected], bulkRejectReason.trim());
      toast.success(
        `Rejected ${result.succeeded.length}` +
        (result.failed.length > 0 ? `, ${result.failed.length} failed` : '')
      );
      if (result.failed.length > 0) {
        console.warn('[bulk-reject] failures:', result.failed);
      }
      setBulkRejectOpen(false);
      setBulkRejectReason('');
    } catch (err: any) {
      toast.error(err?.response?.data?.error || err?.message || 'Bulk reject failed');
    } finally {
      setBulkRejectBusy(false);
    }
  };

  if (!isAdmin) {
    return (
      <div className="p-10 text-center text-text-muted">
        <AlertTriangle className="mx-auto mb-3 text-amber-500" />
        Only school_admin or systems_admin can review exam submissions.
      </div>
    );
  }

  return (
    <div className="space-y-8 animate-in fade-in duration-700 pb-10">
      <div className="flex flex-col md:flex-row items-start md:items-center justify-between gap-6">
        <div>
          <h1 className="text-3xl font-black text-text tracking-tight uppercase">Exam Review Queue</h1>
          <nav className="flex text-[0.65rem] font-black uppercase tracking-[2px] text-text-muted gap-2 items-center mt-1">
            <span>Administration</span>
            <ChevronRight size={12} className="text-text-muted/30" />
            <span className="text-primary">Pending Teacher Submissions</span>
          </nav>
        </div>
        <button
          onClick={async () => { setLoading(true); await fetchPendingGroups(); setLoading(false); }}
          className="px-6 py-3 bg-card border border-border text-text font-black text-[0.65rem] uppercase tracking-widest rounded-2xl hover:bg-muted transition-all active:scale-95"
        >
          Refresh
        </button>
      </div>

      <div className="bg-card border border-border rounded-[2.5rem] shadow-sm overflow-hidden">
        {loading ? (
          <div className="p-16 text-center text-text-muted">
            <Loader2 className="animate-spin mx-auto mb-3" />
            Loading pending submissions…
          </div>
        ) : pendingGroups.length === 0 ? (
          <div className="p-16 text-center text-text-muted">
            <CheckCircle2 className="mx-auto mb-3 text-emerald-500" size={32} />
            <p className="font-bold uppercase tracking-widest text-[0.7rem]">Queue clear — no teacher exams awaiting review.</p>
          </div>
        ) : (
          <>
          {selected.size > 0 && (
            <div className="flex items-center justify-between gap-4 px-6 py-3 bg-rose-50 border-b border-rose-200">
              <div className="text-[0.7rem] font-black uppercase tracking-widest text-rose-700">
                {selected.size} selected
              </div>
              <div className="flex items-center gap-2">
                <button
                  onClick={() => { setSelected(new Set()); setBulkRejectOpen(false); }}
                  className="px-4 py-2 text-[0.65rem] font-black uppercase tracking-widest text-text-muted hover:text-text"
                >
                  Clear
                </button>
                <button
                  onClick={() => setBulkRejectOpen(true)}
                  className="px-5 py-2 bg-rose-600 text-white rounded-xl font-black text-[0.65rem] uppercase tracking-widest hover:bg-rose-700 transition-all active:scale-95 flex items-center gap-2"
                >
                  <XCircle size={14} /> Bulk Reject ({selected.size})
                </button>
              </div>
            </div>
          )}
          <table className="w-full text-left">
            <thead>
              <tr className="bg-muted/80 border-b border-border">
                <th className="px-4 py-4 w-10">
                  <input
                    type="checkbox"
                    aria-label="Select all"
                    checked={pendingGroups.length > 0 && selected.size === pendingGroups.length}
                    onChange={toggleAll}
                    className="w-4 h-4 accent-primary cursor-pointer"
                  />
                </th>
                <th className="px-6 py-4 text-[0.65rem] font-black text-primary uppercase tracking-widest">Exam</th>
                <th className="px-6 py-4 text-[0.65rem] font-black text-primary uppercase tracking-widest">Type</th>
                <th className="px-6 py-4 text-[0.65rem] font-black text-primary uppercase tracking-widest text-right">Action</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-border">
              {pendingGroups.map((g) => (
                <tr key={g.id} className={`hover:bg-muted/30 transition-colors ${selected.has(g.id) ? 'bg-rose-50/40' : ''}`}>
                  <td className="px-4 py-4 w-10">
                    <input
                      type="checkbox"
                      aria-label={`Select ${g.name}`}
                      checked={selected.has(g.id)}
                      onChange={() => toggleOne(g.id)}
                      className="w-4 h-4 accent-primary cursor-pointer"
                    />
                  </td>
                  <td className="px-6 py-4">
                    <div className="flex items-center gap-3">
                      <div className="w-10 h-10 rounded-xl bg-amber-50 text-amber-600 border border-amber-100 flex items-center justify-center">
                        <FileText size={18} />
                      </div>
                      <div>
                        <div className="text-[0.9rem] font-bold text-text">{g.name}</div>
                        <div className="text-[0.6rem] text-text-muted font-black tracking-tighter uppercase mt-0.5">
                          ID: EXM-2026-{g.id} · {g.duration_minutes} MINS · {g.total_marks} MARKS
                        </div>
                      </div>
                    </div>
                  </td>
                  <td className="px-6 py-4">
                    <span className="px-2.5 py-1 rounded-lg text-[0.6rem] font-black uppercase tracking-widest border bg-blue-50 text-blue-600 border-blue-100">
                      {g.exam_type}
                    </span>
                  </td>
                  <td className="px-6 py-4 text-right">
                    <button
                      onClick={() => setReviewing(g)}
                      className="px-5 py-2 bg-primary text-white rounded-xl font-black text-[0.65rem] uppercase tracking-widest hover:bg-primary/90 transition-all active:scale-95 shadow-md shadow-blue-900/10"
                    >
                      Review
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
          </>
        )}
      </div>

      {/* Bulk-reject reason modal — single shared reason applied to all
          selected groups. Opened from the toolbar; the actual API call
          fires from handleBulkReject after the user confirms. */}
      {bulkRejectOpen && (
        <div className="fixed inset-0 bg-[#002147]/60 backdrop-blur-sm z-[160] flex items-center justify-center p-4">
          <div className="bg-card border border-border rounded-[2rem] w-full max-w-lg shadow-2xl overflow-hidden">
            <div className="px-8 py-6 bg-rose-50 border-b border-rose-200">
              <h2 className="text-xl font-black text-rose-700 uppercase tracking-tight">Bulk Reject</h2>
              <p className="text-[0.7rem] font-black text-rose-600/80 uppercase tracking-widest mt-1">
                {selected.size} group{selected.size === 1 ? '' : 's'} will be rejected with this reason
              </p>
            </div>
            <div className="p-8 space-y-4">
              <textarea
                value={bulkRejectReason}
                onChange={(e) => setBulkRejectReason(e.target.value)}
                rows={4}
                placeholder="Why are these submissions being rejected? (visible to all affected teachers)"
                className="w-full bg-card border border-rose-200 rounded-xl px-3 py-2.5 text-sm outline-none focus:border-rose-400 resize-none"
                autoFocus
              />
              <div className="flex flex-col-reverse md:flex-row items-stretch md:items-center justify-end gap-2">
                <button
                  type="button"
                  onClick={() => { setBulkRejectOpen(false); setBulkRejectReason(''); }}
                  className="px-5 py-2.5 bg-card border border-border text-text-muted rounded-xl font-black text-[0.65rem] uppercase tracking-widest hover:bg-muted"
                >
                  Cancel
                </button>
                <button
                  type="button"
                  disabled={!bulkRejectReason.trim() || bulkRejectBusy}
                  onClick={handleBulkReject}
                  className="px-6 py-2.5 bg-rose-600 text-white rounded-xl font-black text-[0.65rem] uppercase tracking-widest hover:bg-rose-700 transition-all active:scale-95 disabled:opacity-50 flex items-center justify-center gap-2"
                >
                  {bulkRejectBusy && <Loader2 size={14} className="animate-spin" />}
                  {bulkRejectBusy ? 'Rejecting…' : `Reject ${selected.size}`}
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {reviewing && (
        <ReviewModal
          group={reviewing}
          onClose={() => setReviewing(null)}
          onPublished={async () => { toast.success(`"${reviewing.name}" published — students can now see it`); setReviewing(null); await fetchPendingGroups(); }}
          onRejected={async () => { toast.info(`"${reviewing.name}" rejected`); setReviewing(null); await fetchPendingGroups(); }}
          createSchedule={createSchedule}
          publishSchedule={publishSchedule}
          rejectGroup={rejectGroup}
        />
      )}
    </div>
  );
}

function ReviewModal({
  group, onClose, onPublished, onRejected,
  createSchedule, publishSchedule, rejectGroup
}: any) {
  const [classes, setClasses] = useState<ClassOption[]>([]);
  const [subjects, setSubjects] = useState<SubjectOption[]>([]);
  const [loadingMeta, setLoadingMeta] = useState(true);
  const [submitting, setSubmitting] = useState<null | 'publish' | 'reject'>(null);
  const [error, setError] = useState<string | null>(null);
  const [showReject, setShowReject] = useState(false);
  const [rejectReason, setRejectReason] = useState('');

  const [form, setForm] = useState({
    class_id: group.class_id ? String(group.class_id) : '',
    subject_id: group.subject_id ? String(group.subject_id) : '',
    start_time: '',
    end_time: '',
    venue: '',
    is_online: false,
    instructions: '',
  });

  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const [clsRes, subRes] = await Promise.all([
          api.get('/classes'),
          api.get('/subjects'),
        ]);
        if (cancelled) return;
        setClasses(Array.isArray(clsRes.data) ? clsRes.data : (clsRes.data?.classes || []));
        setSubjects(Array.isArray(subRes.data) ? subRes.data : (subRes.data?.subjects || []));
      } catch (e) {
        setError('Failed to load classes/subjects.');
      } finally {
        if (!cancelled) setLoadingMeta(false);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  const filteredSubjects = form.class_id
    ? subjects.filter(s => !s.class_id || s.class_id === Number(form.class_id))
    : subjects;

  const handlePublish = async (e: React.FormEvent) => {
    e.preventDefault();
    setError(null);
    if (!form.class_id || !form.subject_id || !form.start_time || !form.end_time) {
      setError('Class, subject, start time, and end time are required.');
      return;
    }
    if (new Date(form.start_time) >= new Date(form.end_time)) {
      setError('Start time must be before end time.');
      return;
    }
    setSubmitting('publish');
    try {
      const schedule = await createSchedule({
        exam_group_id: group.id,
        class_id: Number(form.class_id),
        subject_id: Number(form.subject_id),
        start_time: new Date(form.start_time).toISOString(),
        end_time: new Date(form.end_time).toISOString(),
        duration_minutes: group.duration_minutes,
        venue: form.venue || null,
        is_online: form.is_online,
        instructions: form.instructions || null,
      });
      await publishSchedule(schedule.id);
      onPublished();
    } catch (err: any) {
      setError(err.response?.data?.error || err.message || 'Failed to publish exam.');
    } finally {
      setSubmitting(null);
    }
  };

  const handleReject = async () => {
    if (!rejectReason.trim()) {
      setError('Please provide a rejection reason.');
      return;
    }
    setSubmitting('reject');
    setError(null);
    try {
      await rejectGroup(group.id, rejectReason.trim());
      onRejected();
    } catch (err: any) {
      setError(err.response?.data?.error || err.message || 'Failed to reject exam.');
    } finally {
      setSubmitting(null);
    }
  };

  return (
    <div className="fixed inset-0 bg-[#002147]/60 backdrop-blur-sm z-[150] flex items-center justify-center p-4">
      <div className="bg-card border border-border rounded-[2.5rem] w-full max-w-2xl max-h-[90vh] overflow-hidden flex flex-col shadow-2xl">
        <div className="px-10 py-8 bg-muted/50 border-b border-border flex items-center justify-between shrink-0">
          <div>
            <h2 className="text-2xl font-black text-text tracking-tight uppercase">Review Exam</h2>
            <p className="text-xs font-bold text-text-muted uppercase tracking-widest mt-1">{group.name}</p>
          </div>
          <button onClick={onClose} className="w-10 h-10 flex items-center justify-center rounded-xl bg-card border border-border text-text-muted hover:text-rose-500 transition-all">
            <X size={20} />
          </button>
        </div>

        {loadingMeta ? (
          <div className="p-16 text-center text-text-muted">
            <Loader2 className="animate-spin mx-auto" />
          </div>
        ) : (
          <form onSubmit={handlePublish} className="p-10 overflow-y-auto flex-1 space-y-6">
            <div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-[0.65rem] font-black uppercase tracking-widest">
              <Pill label="Type" value={group.exam_type} />
              <Pill label="Duration" value={`${group.duration_minutes} min`} />
              <Pill label="Total Marks" value={String(group.total_marks)} />
              <Pill label="Pass Marks" value={String(group.passing_marks)} />
            </div>

            {group.description && (
              <p className="text-sm text-text-muted bg-muted/30 p-4 rounded-2xl border border-border">{group.description}</p>
            )}

            {error && (
              <div className="bg-rose-50 border border-rose-200 text-rose-700 text-sm p-3 rounded-xl">{error}</div>
            )}

            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              {(group.class_id || group.subject_id) && (
                <p className="md:col-span-2 text-[0.6rem] text-text-muted/80 font-bold uppercase tracking-widest flex items-center gap-1.5">
                  <FileText size={11} className="text-primary/70" /> Class &amp; subject pre-filled from teacher&apos;s submission — adjust if needed.
                </p>
              )}
              <Field label="Class *">
                <select required value={form.class_id} onChange={(e) => setForm({ ...form, class_id: e.target.value, subject_id: '' })}
                  className="w-full bg-card border border-border rounded-xl px-4 py-2.5 text-sm outline-none focus:border-primary">
                  <option value="">Select class…</option>
                  {classes.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
                </select>
              </Field>
              <Field label="Subject *">
                <select required value={form.subject_id} disabled={!form.class_id} onChange={(e) => setForm({ ...form, subject_id: e.target.value })}
                  className="w-full bg-card border border-border rounded-xl px-4 py-2.5 text-sm outline-none focus:border-primary disabled:opacity-50">
                  <option value="">Select subject…</option>
                  {filteredSubjects.map((s) => <option key={s.id} value={s.id}>{s.name}</option>)}
                </select>
              </Field>
              <Field label="Start Time *">
                <input type="datetime-local" required value={form.start_time} onChange={(e) => setForm({ ...form, start_time: e.target.value })}
                  className="w-full bg-card border border-border rounded-xl px-4 py-2.5 text-sm outline-none focus:border-primary" />
              </Field>
              <Field label="End Time *">
                <input type="datetime-local" required value={form.end_time} onChange={(e) => setForm({ ...form, end_time: e.target.value })}
                  className="w-full bg-card border border-border rounded-xl px-4 py-2.5 text-sm outline-none focus:border-primary" />
              </Field>
              <Field label="Venue">
                <div className="relative">
                  <MapPin size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-text-muted/50" />
                  <input type="text" value={form.venue} onChange={(e) => setForm({ ...form, venue: e.target.value })}
                    placeholder="e.g. Hall A or Online (Zoom link)"
                    className="w-full bg-card border border-border rounded-xl pl-9 pr-4 py-2.5 text-sm outline-none focus:border-primary" />
                </div>
              </Field>
              <Field label="Mode">
                <label className="flex items-center gap-3 bg-card border border-border rounded-xl px-4 py-2.5 cursor-pointer">
                  <input type="checkbox" checked={form.is_online} onChange={(e) => setForm({ ...form, is_online: e.target.checked })}
                    className="w-4 h-4 accent-primary" />
                  <Globe size={14} className="text-text-muted" />
                  <span className="text-sm">Online exam</span>
                </label>
              </Field>
            </div>

            <Field label="Instructions">
              <textarea value={form.instructions} onChange={(e) => setForm({ ...form, instructions: e.target.value })} rows={3}
                placeholder="Special instructions for students…"
                className="w-full bg-card border border-border rounded-xl px-4 py-2.5 text-sm outline-none focus:border-primary resize-none" />
            </Field>

            {showReject && (
              <div className="bg-rose-50 border border-rose-200 rounded-2xl p-4 space-y-2">
                <p className="text-[0.65rem] font-black uppercase tracking-widest text-rose-700">Rejection Reason</p>
                <textarea value={rejectReason} onChange={(e) => setRejectReason(e.target.value)} rows={2}
                  placeholder="Why are you rejecting this submission?"
                  className="w-full bg-card border border-rose-200 rounded-xl px-3 py-2 text-sm outline-none focus:border-rose-400 resize-none" />
              </div>
            )}

            <div className="flex flex-col-reverse md:flex-row items-stretch md:items-center justify-between gap-3 pt-2">
              <button type="button" onClick={() => setShowReject((v) => !v)}
                className="px-5 py-3 bg-card border border-rose-200 text-rose-600 rounded-xl font-black text-[0.65rem] uppercase tracking-widest hover:bg-rose-50 transition-all active:scale-95 flex items-center justify-center gap-2">
                <XCircle size={14} /> {showReject ? 'Cancel Reject' : 'Reject'}
              </button>
              {showReject ? (
                <button type="button" disabled={submitting !== null} onClick={handleReject}
                  className="px-6 py-3 bg-rose-600 text-white rounded-xl font-black text-[0.65rem] uppercase tracking-widest hover:bg-rose-700 transition-all active:scale-95 disabled:opacity-50 flex items-center justify-center gap-2">
                  {submitting === 'reject' && <Loader2 size={14} className="animate-spin" />}
                  Confirm Reject
                </button>
              ) : (
                <button type="submit" disabled={submitting !== null}
                  className="px-6 py-3 bg-primary text-white rounded-xl font-black text-[0.65rem] uppercase tracking-widest hover:bg-primary/90 transition-all shadow-xl shadow-blue-900/10 active:scale-95 disabled:opacity-50 flex items-center justify-center gap-2">
                  {submitting === 'publish' ? <Loader2 size={14} className="animate-spin" /> : <Calendar size={14} />}
                  {submitting === 'publish' ? 'Publishing…' : 'Approve & Publish'}
                </button>
              )}
            </div>
          </form>
        )}
      </div>
    </div>
  );
}

function Field({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div className="space-y-1.5">
      <label className="text-[0.65rem] font-black uppercase tracking-widest text-text-muted">{label}</label>
      {children}
    </div>
  );
}

function Pill({ label, value }: { label: string; value: string }) {
  return (
    <div className="bg-muted/30 border border-border rounded-xl px-3 py-2">
      <p className="text-[0.55rem] text-text-muted font-black tracking-widest">{label}</p>
      <p className="text-sm font-black text-text mt-0.5">{value}</p>
    </div>
  );
}