// admin-students.jsx — Dedicated Students tab in the admin dashboard.
// One row per student. Inline shows: name, hourly rate, classes left,
// assigned instructor(s), and "Recharge", "Edit", "Delete", "Magic link"
// buttons. Expanded shows full class history (past + future, paid/unpaid).
//
// Filters (2026-05-31): the roster got long, so the header carries a
// name/topic text search plus two combinable dropdowns — filter by the
// assigned instructor (with an explicit "No instructor" bucket for students
// nobody is teaching yet) and by topic of interest. All three compose
// (logical AND); a Clear button resets them. Pure client-side over data
// already in useAdminData() — no schema, no extra queries.

const AS_DAYS  = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'];
const ASfmt$ = v => v == null ? '—' : '$' + Number(v).toLocaleString();
const ASfmtH = h => h === 0 ? '12 AM' : h === 12 ? '12 PM' : h > 12 ? (h-12)+' PM' : h+' AM';
// Column-header label style for the minimal student table.
const ASHCol = { fontSize:10.5, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.05em', color:'oklch(56% 0.03 265)' };

// ── Confirm Delete ──────────────────────────────────────────────────────
const AdminStudents = () => {
  const data = window.useAdminData();
  const isMobile = window.useIsMobile();
  const [showAdd,  setShowAdd]  = React.useState(false);
  const [search,   setSearch]   = React.useState('');
  const [instructorFilter, setInstructorFilter] = React.useState('all');
  const [topicFilter,      setTopicFilter]      = React.useState('all');

  // Sentinels for the instructor <select>. Real instructor ids are UUIDs, so
  // these can never collide with an actual instructor id.
  const INSTR_ALL  = 'all';
  const INSTR_NONE = 'unassigned';

  const allStudents = data.students || [];
  const assignments = data.assignments || [];
  const instructors = data.instructors || [];

  // studentId -> Set of instructorIds the student is ACTIVELY assigned to.
  // Drives both the instructor filter and the "No instructor" bucket.
  const instrIdsByStudent = React.useMemo(() => {
    const m = new Map();
    for (const a of assignments) {
      if (a.active === false || !a.instructorId) continue;
      if (!m.has(a.studentId)) m.set(a.studentId, new Set());
      m.get(a.studentId).add(a.instructorId);
    }
    return m;
  }, [assignments]);

  // Instructor dropdown: only instructors who actually have at least one
  // actively-assigned student, each with that student count, sorted A→Z.
  const instructorOptions = React.useMemo(() => {
    const studentsByInstr = new Map(); // instructorId -> Set(studentId)
    for (const a of assignments) {
      if (a.active === false || !a.instructorId) continue;
      if (!studentsByInstr.has(a.instructorId)) studentsByInstr.set(a.instructorId, new Set());
      studentsByInstr.get(a.instructorId).add(a.studentId);
    }
    const nameById = new Map(instructors.map(i => [i.id, i.name]));
    return [...studentsByInstr.entries()]
      .map(([id, set]) => ({ id, name: nameById.get(id) || 'Unknown teacher', count: set.size }))
      .sort((a, b) => a.name.localeCompare(b.name));
  }, [assignments, instructors]);

  const unassignedCount = React.useMemo(
    () => allStudents.filter(s => !instrIdsByStudent.has(s.id)).length,
    [allStudents, instrIdsByStudent]
  );

  // Topic dropdown: every distinct topic across all students, with a count of
  // how many list it, sorted A→Z.
  const topicOptions = React.useMemo(() => {
    const counts = new Map();
    for (const s of allStudents) {
      for (const t of (s.topics || [])) {
        const key = String(t).trim();
        if (key) counts.set(key, (counts.get(key) || 0) + 1);
      }
    }
    return [...counts.entries()]
      .map(([topic, count]) => ({ topic, count }))
      .sort((a, b) => a.topic.localeCompare(b.topic));
  }, [allStudents]);

  // Apply search + instructor + topic together (logical AND).
  const students = allStudents.filter(s => {
    if (search) {
      const q = search.toLowerCase();
      const matches = s.name.toLowerCase().includes(q) ||
        (s.topics || []).join(' ').toLowerCase().includes(q);
      if (!matches) return false;
    }
    if (instructorFilter === INSTR_NONE) {
      if (instrIdsByStudent.has(s.id)) return false;
    } else if (instructorFilter !== INSTR_ALL) {
      const ids = instrIdsByStudent.get(s.id);
      if (!ids || !ids.has(instructorFilter)) return false;
    }
    if (topicFilter !== INSTR_ALL) {
      const topics = (s.topics || []).map(t => String(t).toLowerCase());
      if (!topics.includes(topicFilter.toLowerCase())) return false;
    }
    return true;
  });

  const filtersActive = !!search || instructorFilter !== INSTR_ALL || topicFilter !== INSTR_ALL;
  const clearFilters = () => { setSearch(''); setInstructorFilter(INSTR_ALL); setTopicFilter(INSTR_ALL); };

  // Headline metrics — computed on the FULL set so they stay stable while you
  // filter (the filter result count is shown in the controls row instead).
  const totalCredits = allStudents.reduce((sum, s) => sum + (s.classesBalance || 0), 0);
  const lowCount     = allStudents.filter(s => s.classesBalance <= 1).length;
  const today        = new Date(); today.setHours(0,0,0,0);
  const todayCount   = (data.bookings || []).filter(b => {
    const d = new Date(b.scheduledAt);
    return d >= today && d < new Date(today.getTime() + 86400000) && b.status !== 'cancelled';
  }).length;

  if (data.loading) {
    return <div style={{ padding:60, textAlign:'center', color:'oklch(55% 0.03 265)', fontSize:14 }}>Loading students…</div>;
  }

  // Shared style for the dark-panel form controls. Options need an explicit
  // light background + dark text or they render white-on-white in the native
  // dropdown.
  const ctrl = {
    padding:'8px 12px', borderRadius:8, border:'1px solid rgba(255,255,255,0.16)',
    background:'rgba(255,255,255,0.08)', color:'#fff', fontSize:12,
    fontFamily:"'Plus Jakarta Sans', sans-serif", outline:'none',
  };
  const opt = { color:'#1f2937', background:'#fff' };

  return (
    <div>
      <div style={{ background:'oklch(20% 0.07 265)', borderRadius:14, padding:'16px 22px', marginBottom:20 }}>
        <div style={{ display:'flex', gap:28, alignItems:'center', flexWrap:'wrap' }}>
          {[
            { label:'Total Students', value: allStudents.length },
            { label:'Classes Available', value: totalCredits },
            { label:'Low Balance (≤1)',  value: lowCount, alert: lowCount > 0 },
            { label:'Lessons Today',     value: todayCount },
          ].map(s => (
            <div key={s.label}>
              <div style={{ fontSize:10, color:'rgba(255,255,255,0.48)', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:4 }}>{s.label}</div>
              <div style={{ fontFamily:"'Cormorant Garamond', serif", fontSize:24, fontWeight:700, color: s.alert ? 'oklch(72% 0.17 80)' : '#fff' }}>{s.value}</div>
            </div>
          ))}
          <button onClick={() => setShowAdd(true)} style={{ marginLeft:'auto', background:'oklch(72% 0.17 80)', color:'oklch(18% 0.06 265)', border:'none', borderRadius:8, padding:'9px 18px', fontWeight:700, fontSize:13, cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif", whiteSpace:'nowrap' }}>+ Add Student</button>
        </div>

        {/* Filter controls — name/topic search + instructor + topic. All combine (AND). */}
        <div style={{ display:'flex', gap:8, alignItems:'center', flexWrap:'wrap', marginTop:16, paddingTop:14, borderTop:'1px solid rgba(255,255,255,0.1)' }}>
          <input value={search} onChange={e=>setSearch(e.target.value)} placeholder="Search name or topic…" style={{ ...ctrl, padding:'8px 14px', width:190 }} />

          <select value={instructorFilter} onChange={e=>setInstructorFilter(e.target.value)} title="Filter by assigned instructor" style={{ ...ctrl, cursor:'pointer', maxWidth:230 }}>
            <option value={INSTR_ALL}  style={opt}>All instructors</option>
            <option value={INSTR_NONE} style={opt}>⚠ No instructor ({unassignedCount})</option>
            {instructorOptions.map(o => (
              <option key={o.id} value={o.id} style={opt}>{o.name} ({o.count})</option>
            ))}
          </select>

          <select value={topicFilter} onChange={e=>setTopicFilter(e.target.value)} title="Filter by topic of interest" style={{ ...ctrl, cursor:'pointer', maxWidth:230 }}>
            <option value={INSTR_ALL} style={opt}>All topics</option>
            {topicOptions.map(o => (
              <option key={o.topic} value={o.topic} style={opt}>{o.topic} ({o.count})</option>
            ))}
          </select>

          {filtersActive && (
            <button onClick={clearFilters} style={{ background:'rgba(255,255,255,0.1)', color:'#fff', border:'1px solid rgba(255,255,255,0.18)', borderRadius:8, padding:'8px 12px', fontSize:12, fontWeight:600, cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif", whiteSpace:'nowrap' }}>Clear filters</button>
          )}

          <span style={{ fontSize:12, color:'rgba(255,255,255,0.6)', fontFamily:"'Plus Jakarta Sans', sans-serif", marginLeft:'auto', whiteSpace:'nowrap' }}>
            {filtersActive ? `Showing ${students.length} of ${allStudents.length}` : `${allStudents.length} students`}
          </span>
        </div>
      </div>

      {allStudents.length === 0 ? (
        <div style={{ padding:60, textAlign:'center', color:'oklch(55% 0.03 265)', fontSize:14, background:'#fff', borderRadius:14, border:'1px solid oklch(91% 0.01 265)' }}>
          No students yet. Click <strong>+ Add Student</strong> to create one.
        </div>
      ) : students.length === 0 ? (
        <div style={{ padding:48, textAlign:'center', color:'oklch(55% 0.03 265)', fontSize:14, background:'#fff', borderRadius:14, border:'1px solid oklch(91% 0.01 265)' }}>
          No students match these filters.{' '}
          <button onClick={clearFilters} style={{ background:'none', border:'none', color:'oklch(45% 0.13 265)', fontWeight:700, cursor:'pointer', fontSize:14, textDecoration:'underline', fontFamily:"'Plus Jakarta Sans', sans-serif", padding:0 }}>Clear filters</button>
        </div>
      ) : (
        <div style={{ background:'#fff', borderRadius:14, border:'1px solid oklch(91% 0.01 265)', overflow:'hidden', boxShadow:'0 1px 4px oklch(18% 0.06 265 / 0.04)' }}>
          {/* Column header — grid template MUST match ASCard's collapsed row (admin-students-card.jsx). */}
          <div style={{ display:'grid', gridTemplateColumns: isMobile ? 'minmax(0,1fr) 22px' : 'minmax(0,2.4fr) 70px minmax(0,1.6fr) 22px', alignItems:'center', gap:12, padding:'9px 16px', borderBottom:'1px solid oklch(92% 0.01 265)', background:'oklch(98.5% 0.005 265)' }}>
            <div style={ASHCol}>Student</div>
            {!isMobile && <div style={{ ...ASHCol, textAlign:'right' }}>Classes</div>}
            {!isMobile && <div style={ASHCol}>Instructor</div>}
            <div />
          </div>
          {students.map(s => <window.ASCard key={s.id} student={s} />)}
        </div>
      )}

      {showAdd && <window.ASAddStudent onClose={() => setShowAdd(false)} />}
    </div>
  );
};

// AdminEditStudentModal alias is published from admin-students-modals.jsx.
Object.assign(window, { AdminStudents });
