/**
 * ClassDetail — Phase 1 PR 3 (2026-07-22).
 *
 * 5 tabs:
 *   1. Overview    — quick stats + description
 *   2. Roster      — active students + Bulk assign + per-row Transfer / Withdraw
 *   3. Teachers    — form tutor + active covers (from PR 1 user_roles)
 *   4. Subjects    — per-subject teacher assignment
 *   5. Cohorts     — cohorts this class is linked to (from PR 2)
 *
 * Read access: any authenticated user. Write access (admin only) is
 * gated by `canManage` derived from user.role; principal is read-only
 * on this page by policy.
 */

import React, { useEffect, useMemo, useState } from 'react';
import { useParams, useNavigate, Link } from 'react-router-dom';
import {
  ArrowLeft, Users, BookOpen, GraduationCap, Plus, Trash2, X, Loader2,
  UserCheck, Calendar, ArrowRightLeft, RefreshCw,
} from 'lucide-react';
import api from '../../store/api';
import { useClassDetailStore, useClassDetailStore as useCDS } from '../../store/classDetail';
import { useAuthStore } from '../../store/auth';
import CoverAssignmentForm from '../../components/CoverAssignmentForm';

type Tab = 'overview' | 'roster' | 'teachers' | 'subjects' | 'cohorts';

export default function ClassDetailPage() {
  const { id } = useParams<{ id: string }>();
  const classId = Number(id);
  const navigate = useNavigate();
  const { user } = useAuthStore();
  const { detailById, loading, error, fetchDetail } = useClassDetailStore((s) => ({
    detailById: s.detailById,
    loading: s.loading,
    error: s.error,
    fetchDetail: s.fetchDetail,
  }));

  const [tab, setTab] = useState<Tab>('overview');
  const [showBulkAssign, setShowBulkAssign] = useState(false);
  const [showCoverForm, setShowCoverForm] = useState(false);
  const [editingSubjectId, setEditingSubjectId] = useState<number | null>(null);

  useEffect(() => {
    if (classId) fetchDetail(classId);
  }, [classId, fetchDetail]);

  const detail = detailById[classId];
  const canManage =
    user?.role === 'school_admin' || user?.role === 'systems_admin';

  if (loading && !detail) {
    return <div className="text-center text-text-muted py-12">Loading…</div>;
  }
  if (error) {
    return <div className="bg-rose-500/10 border border-rose-500/30 text-rose-500 rounded-xl px-4 py-3 text-sm">{error}</div>;
  }
  if (!detail) {
    return <div className="text-center text-text-muted py-12">Class not found.</div>;
  }

  const tabs: { key: Tab; label: string; count?: number }[] = [
    { key: 'overview', label: 'Overview' },
    { key: 'roster', label: 'Roster', count: detail.students.length },
    { key: 'teachers', label: 'Teachers' },
    { key: 'subjects', label: 'Subjects', count: detail.subjects.length },
    { key: 'cohorts', label: 'Cohorts', count: detail.cohorts.length },
  ];

  return (
    <div className="space-y-6 animate-in fade-in duration-500">
      <div className="flex items-center gap-3">
        <button onClick={() => navigate('/classes')} className="p-2 rounded-lg hover:bg-background-alt" title="Back">
          <ArrowLeft size={18} />
        </button>
        <div className="flex-1 min-w-0">
          <div className="text-xs font-black uppercase tracking-wider text-text-muted mb-1">
            {detail.section ? `Section ${detail.section}` : 'Class'} · capacity {detail.capacity ?? '—'}
          </div>
          <h1 className="text-3xl font-black text-text truncate">{detail.name}</h1>
        </div>
        <button
          onClick={() => fetchDetail(classId)}
          className="p-2 rounded-lg hover:bg-background-alt text-text-muted"
          title="Refresh"
        >
          <RefreshCw size={16} />
        </button>
      </div>

      {/* Tabs */}
      <div className="flex gap-1 border-b border-border overflow-x-auto">
        {tabs.map((t) => (
          <button
            key={t.key}
            onClick={() => setTab(t.key)}
            className={`px-4 py-2 text-sm font-bold uppercase tracking-wider border-b-2 whitespace-nowrap ${
              tab === t.key ? 'border-primary text-primary' : 'border-transparent text-text-muted hover:text-text'
            }`}
          >
            {t.label}
            {t.count !== undefined && ` (${t.count})`}
          </button>
        ))}
      </div>

      {tab === 'overview' && <OverviewTab detail={detail} />}
      {tab === 'roster' && (
        <RosterTab
          detail={detail}
          canManage={canManage}
          onBulkAssign={() => setShowBulkAssign(true)}
        />
      )}
      {tab === 'teachers' && (
        <TeachersTab
          detail={detail}
          canManage={canManage}
          onAddCover={() => setShowCoverForm(true)}
        />
      )}
      {tab === 'subjects' && (
        <SubjectsTab
          detail={detail}
          canManage={canManage}
          editingSubjectId={editingSubjectId}
          setEditingSubjectId={setEditingSubjectId}
        />
      )}
      {tab === 'cohorts' && <CohortsTab detail={detail} />}

      {showBulkAssign && (
        <BulkAssignModal
          classId={classId}
          existingIds={detail.students.map((s) => s.id)}
          onClose={() => setShowBulkAssign(false)}
        />
      )}
      {showCoverForm && (
        <CoverAssignmentForm
          mode="cover"
          fixedClassId={classId}
          onClose={() => setShowCoverForm(false)}
          onGranted={() => fetchDetail(classId)}
        />
      )}
    </div>
  );
}

// ============== Tabs ==============

function OverviewTab({ detail }: { detail: NonNullable<ReturnType<typeof useCDS.getState>['detailById'][number]> }) {
  return (
    <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
      <StatCard icon={Users} label="Students" value={detail.students.length} />
      <StatCard icon={UserCheck} label="Form tutor" value={detail.class_teacher_name || '—'} textValue />
      <StatCard icon={BookOpen} label="Subjects" value={detail.subjects.length} />
      <StatCard icon={GraduationCap} label="Cohorts" value={detail.cohorts.length} />
      {detail.description && (
        <div className="md:col-span-3 bg-card border border-border rounded-2xl p-5">
          <div className="text-xs font-black uppercase tracking-wider text-text-muted mb-2">Description</div>
          <p className="text-sm text-text-secondary whitespace-pre-wrap">{detail.description}</p>
        </div>
      )}
    </div>
  );
}

function StatCard({ icon: Icon, label, value, textValue }: { icon: any; label: string; value: number | string; textValue?: boolean }) {
  return (
    <div className="bg-card border border-border rounded-2xl p-5">
      <div className="flex items-center gap-3">
        <div className="w-10 h-10 rounded-xl bg-primary/10 text-primary flex items-center justify-center">
          <Icon size={20} />
        </div>
        <div className="min-w-0 flex-1">
          <div className={`font-black text-text ${textValue ? 'text-base truncate' : 'text-2xl'}`}>
            {value}
          </div>
          <div className="text-xs text-text-muted uppercase tracking-wider font-bold">{label}</div>
        </div>
      </div>
    </div>
  );
}

function RosterTab({
  detail, canManage, onBulkAssign,
}: {
  detail: NonNullable<ReturnType<typeof useCDS.getState>['detailById'][number]>;
  canManage: boolean;
  onBulkAssign: () => void;
}) {
  const { fetchDetail } = useClassDetailStore((s) => ({ fetchDetail: s.fetchDetail }));
  const classId = detail.id;
  const [transferTarget, setTransferTarget] = useState<{ enrollmentId: number; studentName: string } | null>(null);
  const [classes, setClasses] = useState<any[]>([]);

  const loadClasses = async () => {
    const { data } = await api.get('/classes', { params: { limit: 200 } });
    setClasses(Array.isArray(data) ? data : []);
  };

  const handleTransfer = async (newClassId: number) => {
    if (!transferTarget) return;
    try {
      await useClassDetailStore.getState().transferStudent(transferTarget.enrollmentId, newClassId);
      await fetchDetail(classId);
      setTransferTarget(null);
    } catch (err: any) {
      alert(err.message);
    }
  };

  const handleWithdraw = async (enrollmentId: number) => {
    if (!confirm('Withdraw this student from the class?')) return;
    try {
      await useClassDetailStore.getState().withdrawStudent(enrollmentId);
      await fetchDetail(classId);
    } catch (err: any) {
      alert(err.message);
    }
  };

  return (
    <div className="bg-card border border-border rounded-2xl p-5 space-y-3">
      <div className="flex items-center justify-between">
        <h2 className="text-lg font-black text-text">Roster</h2>
        {canManage && (
          <button
            onClick={onBulkAssign}
            className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold bg-primary text-white"
          >
            <Plus size={12} /> Bulk assign
          </button>
        )}
      </div>
      {detail.students.length === 0 ? (
        <div className="text-center text-text-muted py-6 text-sm">No active students. Use Bulk assign to add some.</div>
      ) : (
        <div className="space-y-1">
          {detail.students.map((s) => (
            <div key={s.id} className="flex items-center justify-between p-2 rounded-lg hover:bg-background-alt">
              <div className="min-w-0 flex-1">
                <div className="font-bold text-sm text-text">
                  {s.first_name} {s.last_name}
                  <span className="ml-2 text-xs text-text-muted">{s.roll_number ? `roll ${s.roll_number}` : s.email}</span>
                </div>
              </div>
              {canManage && (
                <div className="flex items-center gap-1">
                  <button
                    onClick={() => {
                      setTransferTarget({ enrollmentId: s.enrollment_id, studentName: `${s.first_name} ${s.last_name}` });
                      loadClasses();
                    }}
                    className="p-2 text-text-secondary hover:bg-background-alt rounded-lg"
                    title="Transfer to another class"
                  >
                    <ArrowRightLeft size={14} />
                  </button>
                  <button
                    onClick={() => handleWithdraw(s.enrollment_id)}
                    className="p-2 text-rose-500 hover:bg-rose-500/10 rounded-lg"
                    title="Withdraw from class"
                  >
                    <Trash2 size={14} />
                  </button>
                </div>
              )}
            </div>
          ))}
        </div>
      )}

      {transferTarget && (
        <ModalShell title={`Transfer ${transferTarget.studentName}`} onClose={() => setTransferTarget(null)}>
          <div className="space-y-3">
            <p className="text-sm text-text-secondary">Pick the destination class. The current enrollment will be marked transferred and a new active row will be created.</p>
            <div className="max-h-64 overflow-y-auto border border-border rounded-xl divide-y divide-border/50">
              {classes.filter((c) => c.id !== classId).map((c) => (
                <button
                  key={c.id}
                  onClick={() => handleTransfer(c.id)}
                  className="w-full text-left p-2 hover:bg-background-alt"
                >
                  <div className="font-bold text-sm text-text">{c.name}{c.section ? ` ${c.section}` : ''}</div>
                </button>
              ))}
            </div>
          </div>
        </ModalShell>
      )}
    </div>
  );
}

function TeachersTab({
  detail, canManage, onAddCover,
}: {
  detail: NonNullable<ReturnType<typeof useCDS.getState>['detailById'][number]>;
  canManage: boolean;
  onAddCover: () => void;
}) {
  const { setFormTeacher, fetchDetail } = useClassDetailStore((s) => ({
    setFormTeacher: s.setFormTeacher,
    fetchDetail: s.fetchDetail,
  }));
  const [teachers, setTeachers] = useState<any[]>([]);
  const [editing, setEditing] = useState(false);

  useEffect(() => {
    api.get('/users', { params: { role: 'teacher', limit: 200 } })
      .then((r) => setTeachers(r.data.users || r.data || []))
      .catch(() => setTeachers([]));
  }, []);

  const handleChange = async (teacherId: number | null) => {
    try {
      await setFormTeacher(detail.id, teacherId);
      setEditing(false);
    } catch (err: any) {
      alert(err.message);
    }
  };

  return (
    <div className="space-y-4">
      <div className="bg-card border border-border rounded-2xl p-5 space-y-3">
        <div className="flex items-center justify-between">
          <h2 className="text-lg font-black text-text">Form tutor</h2>
          {canManage && !editing && (
            <button
              onClick={() => setEditing(true)}
              className="text-xs font-bold text-primary hover:underline"
            >
              Change
            </button>
          )}
        </div>
        {editing ? (
          <div className="space-y-2">
            <select
              defaultValue={detail.class_teacher_id ?? ''}
              onChange={(e) => handleChange(e.target.value ? Number(e.target.value) : null)}
              className="w-full px-3 py-2 rounded-xl border border-border bg-background text-text text-sm"
            >
              <option value="">— No form tutor —</option>
              {teachers.map((t) => (
                <option key={t.id} value={t.id}>
                  {t.first_name} {t.last_name}
                </option>
              ))}
            </select>
            <button
              onClick={() => setEditing(false)}
              className="text-xs font-bold text-text-muted hover:underline"
            >
              Cancel
            </button>
          </div>
        ) : detail.teachers.class_teacher ? (
          <div className="text-sm">
            <div className="font-bold text-text">{detail.teachers.class_teacher.name}</div>
            <div className="text-xs text-text-muted">{detail.teachers.class_teacher.email}</div>
          </div>
        ) : (
          <div className="text-sm text-text-muted">No form tutor assigned.</div>
        )}
      </div>

      <div className="bg-card border border-border rounded-2xl p-5 space-y-3">
        <div className="flex items-center justify-between">
          <h2 className="text-lg font-black text-text">Active covers</h2>
          {canManage && (
            <button
              onClick={onAddCover}
              className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold bg-primary text-white"
            >
              <Plus size={12} /> Add cover
            </button>
          )}
        </div>
        {detail.teachers.active_covers.length === 0 ? (
          <div className="text-center text-text-muted py-4 text-sm">No active covers for this class.</div>
        ) : (
          <div className="space-y-2">
            {detail.teachers.active_covers.map((c) => (
              <div key={c.id} className="flex items-center justify-between p-2 rounded-lg bg-background-alt">
                <div>
                  <div className="font-bold text-sm text-text">{c.user_name}</div>
                  <div className="text-xs text-text-muted">{c.role} · {c.reason || 'no reason'}</div>
                </div>
                <div className="text-xs text-text-muted flex items-center gap-1">
                  <Calendar size={12} />
                  {c.expires_at ? new Date(c.expires_at).toLocaleDateString() : 'no end'}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

function SubjectsTab({
  detail, canManage, editingSubjectId, setEditingSubjectId,
}: {
  detail: NonNullable<ReturnType<typeof useCDS.getState>['detailById'][number]>;
  canManage: boolean;
  editingSubjectId: number | null;
  setEditingSubjectId: (id: number | null) => void;
}) {
  const { setSubjectTeacher, fetchDetail } = useClassDetailStore((s) => ({
    setSubjectTeacher: s.setSubjectTeacher,
    fetchDetail: s.fetchDetail,
  }));
  const [teachers, setTeachers] = useState<any[]>([]);

  useEffect(() => {
    api.get('/users', { params: { role: 'teacher', limit: 200 } })
      .then((r) => setTeachers(r.data.users || r.data || []))
      .catch(() => setTeachers([]));
  }, []);

  const handleChange = async (subjectId: number, teacherId: number | null) => {
    try {
      await setSubjectTeacher(detail.id, subjectId, teacherId);
      setEditingSubjectId(null);
    } catch (err: any) {
      alert(err.message);
    }
  };

  return (
    <div className="bg-card border border-border rounded-2xl p-5 space-y-3">
      <h2 className="text-lg font-black text-text">Subjects &amp; subject teachers</h2>
      {detail.subjects.length === 0 ? (
        <div className="text-center text-text-muted py-6 text-sm">No subjects bound to this class yet.</div>
      ) : (
        <div className="space-y-1">
          {detail.subjects.map((s) => (
            <div key={s.id} className="flex items-center justify-between p-2 rounded-lg hover:bg-background-alt">
              <div className="min-w-0 flex-1">
                <div className="font-bold text-sm text-text">{s.name}{s.code ? ` (${s.code})` : ''}</div>
              </div>
              {editingSubjectId === s.id && canManage ? (
                <select
                  defaultValue={s.teacher_id ?? ''}
                  onChange={(e) => handleChange(s.id, e.target.value ? Number(e.target.value) : null)}
                  className="px-2 py-1 rounded-lg border border-border bg-background text-text text-xs"
                >
                  <option value="">— Unassigned —</option>
                  {teachers.map((t) => (
                    <option key={t.id} value={t.id}>
                      {t.first_name} {t.last_name}
                    </option>
                  ))}
                </select>
              ) : (
                <div className="flex items-center gap-2">
                  <span className="text-xs text-text-muted">
                    {s.teacher_name || 'Unassigned'}
                  </span>
                  {canManage && (
                    <button
                      onClick={() => setEditingSubjectId(s.id)}
                      className="text-xs font-bold text-primary hover:underline"
                    >
                      Change
                    </button>
                  )}
                </div>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function CohortsTab({ detail }: { detail: NonNullable<ReturnType<typeof useCDS.getState>['detailById'][number]> }) {
  return (
    <div className="bg-card border border-border rounded-2xl p-5 space-y-3">
      <h2 className="text-lg font-black text-text">Cohorts this class is linked to</h2>
      {detail.cohorts.length === 0 ? (
        <div className="text-center text-text-muted py-6 text-sm">This class isn't part of any cohort yet.</div>
      ) : (
        <div className="space-y-1">
          {detail.cohorts.map((c) => (
            <Link
              key={c.id}
              to={`/admin/cohorts/${c.id}`}
              className="flex items-center justify-between p-2 rounded-lg hover:bg-background-alt"
            >
              <div>
                <div className="font-bold text-sm text-text">{c.name}</div>
                <div className="text-xs text-text-muted">
                  {c.programme} · {c.level || '—'} · {c.academic_year || 'no year'}
                </div>
              </div>
            </Link>
          ))}
        </div>
      )}
    </div>
  );
}

// ============== Modals ==============

function ModalShell({ title, onClose, children }: { title: string; onClose: () => void; children: React.ReactNode }) {
  return (
    <div className="fixed inset-0 z-50 bg-black/40 flex items-center justify-center p-4" onClick={onClose}>
      <div
        className="bg-card border border-border rounded-2xl shadow-2xl w-full max-w-2xl p-6 relative max-h-[90vh] overflow-y-auto"
        onClick={(e) => e.stopPropagation()}
      >
        <button onClick={onClose} className="absolute top-4 right-4 text-text-muted hover:text-text">
          <X size={18} />
        </button>
        <h2 className="text-lg font-black text-text mb-4">{title}</h2>
        {children}
      </div>
    </div>
  );
}

function BulkAssignModal({
  classId, existingIds, onClose,
}: {
  classId: number;
  existingIds: number[];
  onClose: () => void;
}) {
  const { bulkEnrol, fetchDetail } = useClassDetailStore((s) => ({ bulkEnrol: s.bulkEnrol, fetchDetail: s.fetchDetail }));
  const [students, setStudents] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);
  const [search, setSearch] = useState('');
  const [selected, setSelected] = useState<Set<number>>(new Set());
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    setLoading(true);
    api.get('/users', { params: { role: 'student', limit: 500 } })
      .then((r) => {
        const list = (r.data.users || r.data || []).filter((u: any) => !existingIds.includes(u.id));
        setStudents(list);
      })
      .catch(() => setStudents([]))
      .finally(() => setLoading(false));
  }, [existingIds]);

  const filtered = students.filter((u) => {
    if (!search) return true;
    const q = search.toLowerCase();
    return u.first_name?.toLowerCase().includes(q) || u.last_name?.toLowerCase().includes(q) || u.email?.toLowerCase().includes(q);
  });

  const handleSubmit = async () => {
    if (selected.size === 0) return setError('Pick at least one student');
    setSubmitting(true);
    setError(null);
    try {
      const result = await bulkEnrol(classId, Array.from(selected));
      await fetchDetail(classId);
      const summary = `Added ${result.added.length}, skipped ${result.skipped.length}, errors ${result.errors.length}`;
      if (result.added.length === 0 && result.skipped.length > 0) {
        setError(`No new students added. ${result.skipped.length} already enrolled.`);
        setSubmitting(false);
        return;
      }
      alert(summary);
      onClose();
    } catch (err: any) {
      setError(err.message);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <ModalShell title="Bulk assign students" onClose={onClose}>
      <div className="relative mb-3">
        <input
          type="text"
          placeholder="Search students…"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          className="w-full px-3 py-2 rounded-xl border border-border bg-background text-text text-sm"
        />
      </div>
      <div className="max-h-80 overflow-y-auto border border-border rounded-xl divide-y divide-border/50">
        {loading ? (
          <div className="p-4 text-center text-text-muted text-sm flex items-center justify-center gap-2">
            <Loader2 size={14} className="animate-spin" /> Loading…
          </div>
        ) : filtered.length === 0 ? (
          <div className="p-4 text-center text-text-muted text-sm">No matching students.</div>
        ) : (
          filtered.map((u) => {
            const checked = selected.has(u.id);
            return (
              <label key={u.id} className="flex items-center gap-3 p-2 hover:bg-background-alt cursor-pointer">
                <input
                  type="checkbox"
                  checked={checked}
                  onChange={(e) => {
                    const next = new Set(selected);
                    if (e.target.checked) next.add(u.id);
                    else next.delete(u.id);
                    setSelected(next);
                  }}
                  className="w-4 h-4"
                />
                <div className="min-w-0 flex-1">
                  <div className="font-bold text-sm text-text truncate">
                    {u.first_name} {u.last_name}
                  </div>
                  <div className="text-xs text-text-muted truncate">{u.email}</div>
                </div>
              </label>
            );
          })
        )}
      </div>
      {error && <div className="text-sm text-rose-500 mt-2">{error}</div>}
      <div className="flex items-center justify-end gap-2 mt-4">
        <span className="text-xs text-text-muted mr-auto">{selected.size} selected</span>
        <button onClick={onClose} className="px-4 py-2 rounded-xl text-sm font-bold text-text-secondary hover:bg-background-alt">
          Cancel
        </button>
        <button
          onClick={handleSubmit}
          disabled={submitting || selected.size === 0}
          className="px-4 py-2 rounded-xl text-sm font-bold bg-primary text-white disabled:opacity-50"
        >
          {submitting ? 'Adding…' : `Add ${selected.size}`}
        </button>
      </div>
    </ModalShell>
  );
}
