/* screens-admin.jsx — CMS Editor UI for Authors */
const { useState: aState, useEffect: aEffect } = React;

// --- Dashboard Chart Components ---
function StatCard({ label, value, subtext, hue = 'lime' }) {
  return (
    <div className="card card-pad" style={{ flex: 1, background: 'var(--surface-2)', border: 'none' }}>
      <div className="muted" style={{ fontSize: 13, textTransform: 'uppercase', letterSpacing: 1 }}>{label}</div>
      <div style={{ fontSize: 36, fontWeight: 800, color: hue.startsWith('#') ? hue : `var(--${hue}-strong)` }}>{value}</div>
      {subtext && <div className="muted" style={{ fontSize: 13, marginTop: 4 }}>{subtext}</div>}
    </div>
  );
}

function DonutChart({ data, size = 160, thickness = 24 }) {
  const total = data.reduce((sum, d) => sum + d.value, 0) || 1;
  let currentAngle = -90;
  const radius = (size - thickness) / 2;
  const cx = size / 2, cy = size / 2;
  const circum = 2 * Math.PI * radius;

  return (
    <div className="row gap-24" style={{ alignItems: 'center' }}>
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        <circle cx={cx} cy={cy} r={radius} fill="none" stroke="var(--surface-1)" strokeWidth={thickness} />
        {data.map((d, i) => {
          if (d.value === 0) return null;
          const pct = d.value / total;
          const strokeDasharray = `${pct * circum} ${circum}`;
          const offset = (currentAngle + 90) / 360 * circum;
          currentAngle += pct * 360;
          return (
            <circle key={i} cx={cx} cy={cy} r={radius} fill="none" stroke={d.color} strokeWidth={thickness}
              strokeDasharray={strokeDasharray} strokeDashoffset={-offset} strokeLinecap="round"
              style={{ transition: 'stroke-dasharray 1s ease-out' }} />
          );
        })}
      </svg>
      <div className="stack gap-10">
        {data.map((d, i) => (
          <div key={i} className="row gap-10" style={{ fontSize: 14 }}>
            <div style={{ width: 12, height: 12, borderRadius: '50%', background: d.color }}></div>
            <span style={{ color: 'var(--text-muted)' }}>{d.label}</span>
            <strong>{d.value}</strong>
          </div>
        ))}
      </div>
    </div>
  );
}

function BarGraph({ data, height = 180, labelColor = 'var(--text-muted)', barColor = 'var(--lime)' }) {
  const maxVal = Math.max(...data.map(d => d.max || d.value), 1);
  return (
    <div className="row" style={{ height, alignItems: 'flex-end', gap: 16, paddingTop: 20 }}>
      {data.map((d, i) => {
        const pct = (d.value / maxVal) * 100;
        return (
          <div key={i} className="col" style={{ flex: 1, alignItems: 'center', gap: 8 }}>
            <div style={{ width: '100%', height: '100%', background: 'var(--surface-1)', borderRadius: '4px 4px 0 0', position: 'relative', display: 'flex', alignItems: 'flex-end' }}>
              <div style={{ width: '100%', height: `${pct}%`, background: barColor, borderRadius: '4px 4px 0 0', transition: 'height 1s ease-out' }}></div>
              <div style={{ position: 'absolute', top: -20, width: '100%', textAlign: 'center', fontSize: 12, fontWeight: 600 }}>{d.value}</div>
            </div>
            <div style={{ fontSize: 12, color: labelColor, textAlign: 'center', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '100%' }}>{d.label}</div>
          </div>
        );
      })}
    </div>
  );
}

// --- Learner Insights chart components ---

function NPSDisplay({ score, stats }) {
  if (!stats || stats.total === 0) return (
    <div style={{ padding: '32px 20px', textAlign: 'center' }}>
      <p style={{ fontSize: 14, color: 'var(--text-muted)', marginBottom: 6 }}>No NPS responses yet.</p>
      <p style={{ fontSize: 12, color: 'var(--text-muted)' }}>Appears after learners complete a module.</p>
    </div>
  );
  const clr = score >= 50 ? '#16A34A' : score >= 0 ? '#D97706' : '#DC2626';
  const pPct = Math.round((stats.promoters / stats.total) * 100);
  const aPct = Math.round((stats.passives / stats.total) * 100);
  const dPct = 100 - pPct - aPct;
  return (
    <div style={{ textAlign: 'center' }}>
      <div style={{ fontSize: 62, fontWeight: 900, color: clr, lineHeight: 1, marginBottom: 4 }}>
        {score > 0 ? '+' : ''}{score}
      </div>
      <p style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 18 }}>
        Net Promoter Score
      </p>
      <div style={{ display: 'flex', height: 9, borderRadius: 5, overflow: 'hidden', marginBottom: 10, gap: 2 }}>
        {pPct > 0 && <div style={{ flex: pPct, background: '#16A34A', borderRadius: 5 }} />}
        {aPct > 0 && <div style={{ flex: aPct, background: '#D97706', borderRadius: 5 }} />}
        {dPct > 0 && <div style={{ flex: dPct, background: '#DC2626', borderRadius: 5 }} />}
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, fontWeight: 700 }}>
        <span style={{ color: '#16A34A' }}>{pPct}% Promoters</span>
        <span style={{ color: '#D97706' }}>{aPct}% Passives</span>
        <span style={{ color: '#DC2626' }}>{dPct}% Detractors</span>
      </div>
      <p style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 10 }}>{stats.total} response{stats.total !== 1 ? 's' : ''}</p>
    </div>
  );
}

function SatisfactionDisplay({ avg, count }) {
  if (avg === null) return (
    <div style={{ padding: '32px 20px', textAlign: 'center' }}>
      <p style={{ fontSize: 14, color: 'var(--text-muted)', marginBottom: 6 }}>No ratings yet.</p>
      <p style={{ fontSize: 12, color: 'var(--text-muted)' }}>Appears after learners rate lessons.</p>
    </div>
  );
  const stars = [1, 2, 3, 4, 5];
  return (
    <div style={{ textAlign: 'center' }}>
      <div style={{ fontSize: 58, fontWeight: 900, color: '#D97706', lineHeight: 1, marginBottom: 4 }}>
        {avg.toFixed(1)}
      </div>
      <div style={{ fontSize: 28, letterSpacing: 3, marginBottom: 10 }}>
        {stars.map(n => <span key={n} style={{ opacity: n <= Math.round(avg) ? 1 : 0.22 }}>⭐</span>)}
      </div>
      <p style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 6 }}>
        Avg Lesson Rating
      </p>
      <p style={{ fontSize: 12, color: 'var(--text-muted)' }}>{count} rating{count !== 1 ? 's' : ''}</p>
    </div>
  );
}

function ConfidenceGrowthPanel({ data }) {
  if (!data || (data.preAvg === null && data.postAvg === null)) return (
    <div style={{ padding: '32px 20px', textAlign: 'center' }}>
      <p style={{ fontSize: 14, color: 'var(--text-muted)', marginBottom: 6 }}>No confidence data yet.</p>
      <p style={{ fontSize: 12, color: 'var(--text-muted)' }}>Appears when learners start and complete the course.</p>
    </div>
  );
  const preW  = data.preAvg  ? (data.preAvg  / 5) * 100 : 0;
  const postW = data.postAvg ? (data.postAvg / 5) * 100 : 0;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      {data.growth !== null && (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 8 }}>
          <span style={{ fontSize: 13, color: 'var(--text-muted)' }}>Average across {Math.max(data.preCount, data.postCount)} learner{Math.max(data.preCount, data.postCount) !== 1 ? 's' : ''}</span>
          <span style={{ fontSize: 15, fontWeight: 800, color: data.growth >= 0 ? 'var(--lime-strong)' : '#DC2626' }}>
            {data.growth >= 0 ? '+' : ''}{data.growth.toFixed(1)} pts growth
          </span>
        </div>
      )}
      {data.preAvg !== null && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <span style={{ fontSize: 11, fontWeight: 800, color: 'var(--text-muted)', width: 72, flex: 'none' }}>BEFORE COURSE</span>
          <div style={{ flex: 1, height: 10, background: 'var(--border)', borderRadius: 5, overflow: 'hidden' }}>
            <div style={{ height: '100%', width: preW + '%', background: '#93C5FD', borderRadius: 5, transition: 'width .7s' }} />
          </div>
          <span style={{ fontSize: 13, fontWeight: 700, color: '#93C5FD', width: 32, textAlign: 'right' }}>{data.preAvg.toFixed(1)}<span style={{ fontSize: 10, fontWeight: 500 }}>/5</span></span>
        </div>
      )}
      {data.postAvg !== null && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <span style={{ fontSize: 11, fontWeight: 800, color: 'var(--text-muted)', width: 72, flex: 'none' }}>AFTER COURSE</span>
          <div style={{ flex: 1, height: 10, background: 'var(--border)', borderRadius: 5, overflow: 'hidden' }}>
            <div style={{ height: '100%', width: postW + '%', background: 'var(--lime)', borderRadius: 5, transition: 'width .7s' }} />
          </div>
          <span style={{ fontSize: 13, fontWeight: 700, color: 'var(--lime-strong)', width: 32, textAlign: 'right' }}>{data.postAvg.toFixed(1)}<span style={{ fontSize: 10, fontWeight: 500 }}>/5</span></span>
        </div>
      )}
      {data.preAvg === null && <p style={{ fontSize: 13, color: 'var(--text-muted)', marginTop: 4 }}>Pre-course data not yet collected.</p>}
      {data.postAvg === null && <p style={{ fontSize: 13, color: 'var(--text-muted)', marginTop: 4 }}>Post-course data not yet collected — appears when learners complete the full course.</p>}
    </div>
  );
}

// --- Data Dashboard ---
function DataDashboard() {
  const [data, setData] = aState(null);
  const [loading, setLoading] = aState(true);

  const fetchData = async () => {
    if (!window.supabaseClient) return;
    setLoading(true);
    const db = window.supabaseClient;
    
    const [ { data: profiles }, { data: progress }, { data: lessons }, { data: attendance }, { data: answers }, { data: confidence }, { data: experiences } ] = await Promise.all([
      db.from('profiles').select('*').eq('role', 'learner'),
      db.from('lesson_progress').select('*'),
      db.from('lessons').select('id, title, minutes'),
      db.from('session_attendance').select('*'),
      db.from('assessment_answers').select('question_id, is_correct'),
      db.from('confidence_checks').select('*'),
      db.from('experience_responses').select('*'),
    ]);

    const learners = profiles || [];
    const totalLearners = learners.length;
    
    // Ghost Math
    const ghosts = learners.filter(l => l.enrolled_at && !l.first_login_at).length;
    const active = totalLearners - ghosts;

    // Resumption Math
    let gapSum = 0, gapCount = 0;
    learners.forEach(l => {
      if (l.first_login_at && l.last_login_at) {
        const diffDays = (new Date(l.last_login_at) - new Date(l.first_login_at)) / (1000 * 60 * 60 * 24);
        if (diffDays > 0) { gapSum += diffDays; gapCount++; }
      }
    });
    const avgResumptionDays = gapCount ? (gapSum / gapCount).toFixed(1) : 0;

    // Median Progress Math
    const progs = learners.map(l => {
      const userProgs = (progress||[]).filter(p => p.user_id === l.id);
      if(!userProgs.length) return 0;
      return userProgs.reduce((sum, p) => sum + p.progress, 0) / userProgs.length;
    }).sort((a,b) => a-b);
    
    let medianProg = 0;
    if (progs.length) {
      const mid = Math.floor(progs.length / 2);
      medianProg = progs.length % 2 !== 0 ? progs[mid] : ((progs[mid - 1] + progs[mid]) / 2);
    }

    // Per-lesson Completion Math
    const lessonStats = (lessons||[]).map(les => {
      const p = (progress||[]).filter(x => x.lesson_id === les.id);
      const completions = p.filter(x => x.completed_at).length;
      return { label: les.title.substring(0,12)+'...', value: completions, max: totalLearners || 1 };
    }).slice(0, 8);

    // Live vs Async Math
    let liveCount = 0, asyncCount = 0;
    (attendance||[]).forEach(a => {
      if (a.attended_live) liveCount++;
      if (a.watched_recording) asyncCount++;
    });

    // Question Performance Math
    const qMap = {};
    (answers||[]).forEach(a => {
      if (!qMap[a.question_id]) qMap[a.question_id] = { total: 0, correct: 0 };
      qMap[a.question_id].total++;
      if (a.is_correct) qMap[a.question_id].correct++;
    });
    const qStats = Object.keys(qMap).map((k, i) => {
      const pct = Math.round((qMap[k].correct / qMap[k].total) * 100);
      return { label: `Q${i+1}`, value: pct, max: 100 };
    });

    /* ── NPS (course-level: module_id = 'course') ── */
    const npsResponses = (experiences || []).filter(r => r.response_type === 'nps' && r.module_id === 'course');
    const npsPromoters  = npsResponses.filter(r => r.score >= 9).length;
    const npsPassives   = npsResponses.filter(r => r.score >= 7 && r.score <= 8).length;
    const npsDetractors = npsResponses.filter(r => r.score <= 6).length;
    const npsScore = npsResponses.length
      ? Math.round(((npsPromoters - npsDetractors) / npsResponses.length) * 100)
      : null;

    /* ── Lesson pulse (per-lesson star ratings) ── */
    const pulses = (experiences || []).filter(r => r.response_type === 'lesson_pulse');
    const avgLessonRating = pulses.length
      ? pulses.reduce((s, r) => s + r.score, 0) / pulses.length
      : null;

    /* ── Course satisfaction (end-of-course rating) ── */
    const satResponses = (experiences || []).filter(r => r.response_type === 'satisfaction' && r.module_id === 'course');
    const avgCourseSat = satResponses.length
      ? satResponses.reduce((s, r) => s + r.score, 0) / satResponses.length
      : null;

    /* ── Confidence growth (course-level: module_id = 'course') ── */
    const coursePreArr  = (confidence || []).filter(c => c.module_id === 'course' && c.type === 'pre').map(c => c.score);
    const coursePostArr = (confidence || []).filter(c => c.module_id === 'course' && c.type === 'post').map(c => c.score);
    const coursePreAvg  = coursePreArr.length  ? coursePreArr.reduce((a, b) => a + b, 0)  / coursePreArr.length  : null;
    const coursePostAvg = coursePostArr.length ? coursePostArr.reduce((a, b) => a + b, 0) / coursePostArr.length : null;
    const confidenceData = {
      preAvg: coursePreAvg, postAvg: coursePostAvg,
      preCount: coursePreArr.length, postCount: coursePostArr.length,
      growth: (coursePreAvg !== null && coursePostAvg !== null) ? coursePostAvg - coursePreAvg : null,
    };

    setData({ learners, totalLearners, ghosts, active, avgResumptionDays, medianProg: Math.round(medianProg), lessonStats, liveCount, asyncCount, qStats,
      npsScore, npsStats: { total: npsResponses.length, promoters: npsPromoters, passives: npsPassives, detractors: npsDetractors },
      avgLessonRating, lessonRatingCount: pulses.length,
      avgCourseSat, courseSatCount: satResponses.length,
      confidenceData });
    setLoading(false);
  };

  aEffect(() => { fetchData(); }, []);

  const seedMockData = async () => {
    const db = window.supabaseClient;
    setLoading(true);
    // Insert mock profiles
    const id1 = '11111111-1111-1111-1111-111111111111', id2 = '22222222-2222-2222-2222-222222222222', id3 = '33333333-3333-3333-3333-333333333333';
    await db.from('profiles').upsert([
      { id: id1, name: 'Alice Active', first_name: 'Alice', role: 'learner', streak: 4, enrolled_at: new Date().toISOString(), first_login_at: new Date().toISOString(), last_login_at: new Date(Date.now() + 86400000*3).toISOString() },
      { id: id2, name: 'Ghost George', first_name: 'George', role: 'learner', streak: 0, enrolled_at: new Date().toISOString(), first_login_at: null, last_login_at: null },
      { id: id3, name: 'Bob Busy', first_name: 'Bob', role: 'learner', streak: 12, enrolled_at: new Date().toISOString(), first_login_at: new Date(Date.now() - 86400000*10).toISOString(), last_login_at: new Date().toISOString() }
    ]);
    
    // Insert mock attendance
    await db.from('live_sessions').upsert([{ id: id1, title: 'Orientation', scheduled_for: new Date().toISOString() }]);
    await db.from('session_attendance').upsert([{ session_id: id1, user_id: id1, attended_live: true }, { session_id: id1, user_id: id3, watched_recording: true }]);
    
    // Insert mock answers
    await db.from('assessment_questions').upsert([{ id: id1, lesson_id: 'l1', question_text: 'Test Q1' }, { id: id2, lesson_id: 'l1', question_text: 'Test Q2' }]);
    await db.from('assessment_answers').upsert([
      { user_id: id1, question_id: id1, is_correct: true }, { user_id: id3, question_id: id1, is_correct: false },
      { user_id: id1, question_id: id2, is_correct: true }, { user_id: id3, question_id: id2, is_correct: true }
    ]);
    fetchData();
  };

  if (loading) return <div style={{ padding: 40, textAlign: 'center' }}>Crunching numbers...</div>;
  if (!data) return null;

  return (
    <div className="stack" style={{ gap: 24, marginTop: 24 }}>
      <div className="row" style={{ justifyContent: 'flex-end' }}>
        <button className="btn btn-ghost btn-sm" onClick={seedMockData} style={{ color: 'var(--text-muted)' }}>
          Seed Mock Data (Test)
        </button>
      </div>

      {data.totalLearners === 0 && (
        <div style={{ padding: 16, background: 'rgba(231, 76, 60, 0.1)', color: '#e74c3c', borderRadius: 8, display: 'flex', alignItems: 'center', marginTop: -8 }}>
          <strong>No Learner Data Found:</strong> The database has no learners. The charts below will be empty. 
        </div>
      )}

      {/* Row 1: High Level Stats */}
      <div className="row gap-16">
        <StatCard label="Total Learners" value={data.totalLearners} subtext="Enrolled in system" />
        <StatCard label="Ghost Rate" value={data.totalLearners ? Math.round((data.ghosts / data.totalLearners)*100)+'%' : '0%'} subtext={`${data.ghosts} never started`} hue="#e67e22" />
        <StatCard label="Median Progress" value={`${data.medianProg}%`} subtext="Overall cohort progression" hue="#3498db" />
        <StatCard label="Avg Resumption" value={data.avgResumptionDays} subtext="Days between active sessions" />
      </div>

      {/* Row 2: Charts */}
      <div className="row gap-16">
        <div className="card card-pad stack gap-16" style={{ flex: 2, background: 'var(--surface-2)', border: 'none' }}>
          <h3 style={{ margin: 0, fontSize: 16 }}>Lesson Completions</h3>
          <p className="muted" style={{ margin: 0, fontSize: 13 }}>Total learners who fully completed each lesson.</p>
          {data.lessonStats.length > 0 ? <BarGraph data={data.lessonStats} /> : <div className="muted" style={{ height: 180, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>No lessons found</div>}
        </div>
        
        <div className="card card-pad stack gap-16" style={{ flex: 1, background: 'var(--surface-2)', border: 'none' }}>
          <h3 style={{ margin: 0, fontSize: 16 }}>Enrollment Status</h3>
          <p className="muted" style={{ margin: 0, fontSize: 13 }}>Active vs Ghost Enrollments</p>
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <DonutChart data={[
              { label: 'Active', value: data.active, color: 'var(--lime)' },
              { label: 'Ghost', value: data.ghosts, color: '#e74c3c' }
            ]} />
          </div>
        </div>
      </div>

      {/* Row 3: Live vs Async & Questions */}
      <div className="row gap-16">
        <div className="card card-pad stack gap-16" style={{ flex: 1, background: 'var(--surface-2)', border: 'none' }}>
          <h3 style={{ margin: 0, fontSize: 16 }}>Session Attendance</h3>
          <p className="muted" style={{ margin: 0, fontSize: 13 }}>Live attendance vs Async recording views</p>
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <DonutChart data={[
              { label: 'Live', value: data.liveCount, color: '#3498db' },
              { label: 'Async (Recording)', value: data.asyncCount, color: '#9b59b6' }
            ]} />
          </div>
        </div>

        <div className="card card-pad stack gap-16" style={{ flex: 2, background: 'var(--surface-2)', border: 'none' }}>
          <h3 style={{ margin: 0, fontSize: 16 }}>Question Success Rate</h3>
          <p className="muted" style={{ margin: 0, fontSize: 13 }}>% of correct answers per question (flags poor teaching).</p>
          {data.qStats.length > 0 ? <BarGraph data={data.qStats} barColor="#3498db" /> : <div className="muted" style={{ height: 180, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>No assessment data</div>}
        </div>
      </div>

      {/* Row 4: Learner Insights — collected at course start and course completion */}
      <div style={{ marginTop: 8 }}>
        <h2 style={{ fontSize: 18, fontWeight: 800, marginBottom: 4 }}>Learner Insights</h2>
        <p className="muted" style={{ fontSize: 13, marginBottom: 20 }}>Collected via survey prompts: confidence before starting, NPS + satisfaction + confidence after completing the full course.</p>

        {/* Top row: NPS + Course Satisfaction + Lesson Ratings */}
        <div className="row gap-16" style={{ alignItems: 'stretch', marginBottom: 16 }}>
          <div className="card card-pad stack gap-12" style={{ flex: 1, background: 'var(--surface-2)', border: 'none' }}>
            <h3 style={{ margin: 0, fontSize: 16 }}>Net Promoter Score</h3>
            <p className="muted" style={{ margin: 0, fontSize: 13 }}>Likelihood to recommend · collected at course completion.</p>
            <NPSDisplay score={data.npsScore} stats={data.npsStats} />
          </div>
          <div className="card card-pad stack gap-12" style={{ flex: 1, background: 'var(--surface-2)', border: 'none' }}>
            <h3 style={{ margin: 0, fontSize: 16 }}>Course Satisfaction</h3>
            <p className="muted" style={{ margin: 0, fontSize: 13 }}>Overall satisfaction rating (1–5) · collected at course completion.</p>
            <SatisfactionDisplay avg={data.avgCourseSat} count={data.courseSatCount} />
          </div>
          <div className="card card-pad stack gap-12" style={{ flex: 1, background: 'var(--surface-2)', border: 'none' }}>
            <h3 style={{ margin: 0, fontSize: 16 }}>Per-Lesson Ratings</h3>
            <p className="muted" style={{ margin: 0, fontSize: 13 }}>Avg star rating (1–5) · collected after each lesson.</p>
            <SatisfactionDisplay avg={data.avgLessonRating} count={data.lessonRatingCount} />
          </div>
        </div>

        {/* Bottom: Confidence growth */}
        <div className="card card-pad stack gap-16" style={{ background: 'var(--surface-2)', border: 'none' }}>
          <div>
            <h3 style={{ margin: '0 0 4px' }}>Confidence Growth</h3>
            <p className="muted" style={{ margin: 0, fontSize: 13 }}>Self-reported confidence (1–5) before the first lesson vs. after completing the full course.</p>
          </div>
          <ConfidenceGrowthPanel data={data.confidenceData} />
        </div>
      </div>

      {/* Roster Table */}
      <div className="card" style={{ border: '1px solid var(--border)' }}>
        <div className="card-pad" style={{ borderBottom: '1px solid var(--border)', background: 'var(--surface-2)' }}>
          <h3 style={{ margin: 0 }}>Learner Roster</h3>
        </div>
        {data.learners.length === 0 ? (
          <div className="card-pad muted">No learners found.</div>
        ) : (
          <div style={{ overflowX: 'auto' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', textAlign: 'left', fontSize: 14 }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--border)', background: 'var(--surface-1)' }}>
                  <th style={{ padding: '16px 24px', fontWeight: 600, color: 'var(--text-muted)', fontSize: 12, textTransform: 'uppercase', letterSpacing: 1 }}>Student</th>
                  <th style={{ padding: '16px 24px', fontWeight: 600, color: 'var(--text-muted)', fontSize: 12, textTransform: 'uppercase', letterSpacing: 1 }}>Cohort</th>
                  <th style={{ padding: '16px 24px', fontWeight: 600, color: 'var(--text-muted)', fontSize: 12, textTransform: 'uppercase', letterSpacing: 1 }}>Engagement</th>
                  <th style={{ padding: '16px 24px', fontWeight: 600, color: 'var(--text-muted)', fontSize: 12, textTransform: 'uppercase', letterSpacing: 1 }}>Joined</th>
                </tr>
              </thead>
              <tbody>
                {data.learners.map(l => (
                  <tr key={l.id} style={{ borderBottom: '1px solid var(--border)', transition: 'background 0.2s' }} onMouseOver={e => e.currentTarget.style.background = 'var(--surface-1)'} onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                    <td style={{ padding: '16px 24px' }}>
                      <div className="row gap-10">
                        <div className="avatar" style={{ width: 36, height: 36, fontSize: 14, background: 'var(--surface-2)', color: 'var(--text)', border: '1px solid var(--border)' }}>{l.avatar || 'S'}</div>
                        <div className="stack" style={{ gap: 4 }}>
                          <strong style={{ fontSize: 14, fontWeight: 600, color: 'var(--text)' }}>{l.name}</strong>
                          <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>{l.first_name}</span>
                        </div>
                      </div>
                    </td>
                    <td style={{ padding: '16px 24px', color: 'var(--text)' }}>
                      {l.cohort ? <span className="pill" style={{ background: 'var(--surface-2)', border: '1px solid var(--border)', color: 'var(--text)' }}>{l.cohort}</span> : <span className="muted">—</span>}
                    </td>
                    <td style={{ padding: '16px 24px' }}>
                      <div className="stack" style={{ gap: 4 }}>
                        <span style={{ color: 'var(--text)', fontWeight: 500 }}>{l.streak || 0} Day Streak</span>
                        <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>{Math.round((l.total_time_spent_seconds || 0) / 60)} mins active</span>
                      </div>
                    </td>
                    <td style={{ padding: '16px 24px', color: 'var(--text-muted)' }}>
                      {new Date(l.created_at).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
    </div>
  );
}

/* ---- Support Tickets Panel ---- */
function TicketsPanel() {
  const [tickets, setTickets] = aState([]);
  const [loading, setLoading] = aState(true);
  const [filter, setFilter] = aState('all');

  aEffect(() => {
    async function load() {
      if (!window.supabaseClient) { setLoading(false); return; }
      const { data } = await window.supabaseClient
        .from('support_tickets')
        .select('*')
        .order('created_at', { ascending: false });
      setTickets(data || []);
      setLoading(false);
    }
    load();
  }, []);

  const updateStatus = async (id, status) => {
    setTickets(t => t.map(x => x.id === id ? { ...x, status } : x));
    if (window.supabaseClient) {
      await window.supabaseClient.from('support_tickets').update({ status }).eq('id', id);
    }
  };

  const STATUS_COLOR = { open: '#E67E22', resolved: '#27AE60', closed: 'var(--text-muted)' };
  const filtered = filter === 'all' ? tickets : tickets.filter(t => t.status === filter);

  return (
    <div style={{ marginTop: 24 }}>
      <div className="row gap-10" style={{ marginBottom: 20 }}>
        {['all', 'open', 'resolved', 'closed'].map(f => (
          <button key={f} onClick={() => setFilter(f)}
            className={'btn btn-sm ' + (filter === f ? 'btn-primary' : 'btn-ghost')}
            style={{ textTransform: 'capitalize' }}>
            {f}
            {f !== 'all' && <span style={{ marginLeft: 6, opacity: .75 }}>({tickets.filter(t => f === 'all' || t.status === f).length})</span>}
          </button>
        ))}
        <span className="muted" style={{ marginLeft: 'auto', fontSize: 13, fontWeight: 700 }}>{filtered.length} ticket{filtered.length !== 1 ? 's' : ''}</span>
      </div>

      {loading ? (
        <div className="stack" style={{ gap: 12 }}>
          {[1,2,3].map(i => <Skeleton key={i} height={80} radius={12} />)}
        </div>
      ) : filtered.length === 0 ? (
        <div className="card card-pad" style={{ textAlign: 'center', padding: '48px 24px', color: 'var(--text-muted)' }}>
          <Icon name="check" size={32} style={{ marginBottom: 12 }} />
          <p style={{ fontWeight: 700 }}>No {filter !== 'all' ? filter : ''} tickets</p>
        </div>
      ) : (
        <div className="stack" style={{ gap: 12 }}>
          {filtered.map(t => (
            <div key={t.id} className="card card-pad" style={{ borderLeft: `4px solid ${STATUS_COLOR[t.status] || 'var(--border)'}` }}>
              <div className="row gap-12" style={{ justifyContent: 'space-between', flexWrap: 'wrap', marginBottom: 8 }}>
                <div className="row gap-10">
                  <span className="pill" style={{ background: STATUS_COLOR[t.status] + '22', color: STATUS_COLOR[t.status], fontSize: 11, textTransform: 'capitalize' }}>{t.status}</span>
                  <span className="pill" style={{ fontSize: 11 }}>{t.category}</span>
                  <strong style={{ fontSize: 15 }}>{t.subject}</strong>
                </div>
                <span className="muted" style={{ fontSize: 12 }}>{new Date(t.created_at).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit' })}</span>
              </div>
              <p style={{ fontSize: 15, lineHeight: 1.55, color: 'var(--text-muted)', marginBottom: 12 }}>{t.message}</p>
              <div className="row gap-10" style={{ justifyContent: 'space-between' }}>
                <span className="muted" style={{ fontSize: 13 }}>
                  {t.user_name && <span><strong>{t.user_name}</strong>{t.user_email ? ` · ${t.user_email}` : ''}</span>}
                </span>
                <div className="row gap-8">
                  {t.status !== 'resolved' && <button className="btn btn-soft btn-sm" onClick={() => updateStatus(t.id, 'resolved')}><Icon name="check" size={14} /> Resolve</button>}
                  {t.status !== 'closed' && <button className="btn btn-ghost btn-sm" onClick={() => updateStatus(t.id, 'closed')}>Close</button>}
                  {t.status === 'closed' && <button className="btn btn-ghost btn-sm" onClick={() => updateStatus(t.id, 'open')}>Reopen</button>}
                </div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

/* ---- Submissions Panel ---- */
function SubmissionsPanel() {
  const [subs, setSubs] = aState([]);
  const [loading, setLoading] = aState(true);

  aEffect(() => {
    async function load() {
      if (!window.supabaseClient) { setLoading(false); return; }
      const { data } = await window.supabaseClient
        .from('submissions')
        .select('*, profiles:user_id (name, avatar, cohort)')
        .order('submitted_at', { ascending: false });
      setSubs(data || []);
      setLoading(false);
    }
    load();
  }, []);

  const getUrl = (path) => {
    if (!window.supabaseClient) return '#';
    const { data: { publicUrl } } = window.supabaseClient.storage.from('media').getPublicUrl(path);
    return publicUrl;
  };

  const isVideo = (s) => s.file_type?.startsWith('video/') || s.lesson_id?.endsWith('_video');

  return (
    <div style={{ marginTop: 24 }}>
      <div className="row" style={{ marginBottom: 16 }}>
        <span className="muted" style={{ fontWeight: 700 }}>{subs.length} submission{subs.length !== 1 ? 's' : ''}</span>
      </div>
      {loading ? (
        <div className="stack" style={{ gap: 12 }}>
          {[1,2,3].map(i => <Skeleton key={i} height={72} radius={12} />)}
        </div>
      ) : subs.length === 0 ? (
        <div className="card card-pad" style={{ textAlign: 'center', padding: '48px 24px', color: 'var(--text-muted)' }}>
          <Icon name="upload" size={32} style={{ marginBottom: 12 }} />
          <p style={{ fontWeight: 700 }}>No learner submissions yet</p>
        </div>
      ) : (
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 14 }}>
            <thead>
              <tr style={{ borderBottom: '1px solid var(--border)', background: 'var(--surface-2)' }}>
                {['Learner', 'Lesson', 'File', 'Type', 'Size', 'Submitted', ''].map(h => (
                  <th key={h} style={{ padding: '12px 16px', fontWeight: 700, color: 'var(--text-muted)', fontSize: 12, textTransform: 'uppercase', letterSpacing: '.06em', textAlign: 'left', whiteSpace: 'nowrap' }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {subs.map(s => (
                <tr key={s.id} style={{ borderBottom: '1px solid var(--border)' }}>
                  <td style={{ padding: '12px 16px' }}>
                    <div className="row gap-8">
                      <div className="avatar" style={{ width: 32, height: 32, fontSize: 12 }}>{s.profiles?.avatar || '?'}</div>
                      <div>
                        <div style={{ fontWeight: 600 }}>{s.profiles?.name || s.user_id}</div>
                        {s.profiles?.cohort && <div className="muted" style={{ fontSize: 12 }}>{s.profiles.cohort}</div>}
                      </div>
                    </div>
                  </td>
                  <td style={{ padding: '12px 16px', color: 'var(--text-muted)', maxWidth: 160 }}>
                    <span style={{ fontSize: 13, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'block' }}>{s.lesson_id}</span>
                  </td>
                  <td style={{ padding: '12px 16px', maxWidth: 200 }}>
                    <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'block', fontSize: 13, fontWeight: 600 }}>{s.file_name}</span>
                  </td>
                  <td style={{ padding: '12px 16px' }}>
                    <span className="pill" style={{ fontSize: 11 }}>{isVideo(s) ? '🎥 Video' : '📄 Doc'}</span>
                  </td>
                  <td style={{ padding: '12px 16px', color: 'var(--text-muted)', fontSize: 13, whiteSpace: 'nowrap' }}>
                    {s.size_bytes ? (s.size_bytes / (1024*1024)).toFixed(1) + ' MB' : '—'}
                  </td>
                  <td style={{ padding: '12px 16px', color: 'var(--text-muted)', fontSize: 13, whiteSpace: 'nowrap' }}>
                    {new Date(s.submitted_at).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' })}
                  </td>
                  <td style={{ padding: '12px 16px' }}>
                    <a href={getUrl(s.storage_path)} target="_blank" className="btn btn-ghost btn-sm">
                      <Icon name="eye" size={13} /> View
                    </a>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

/* ---- CMS Content Tab ---- */
function CMSPanel({ go }) {
  const [modules, setModules] = aState([]);
  const [loading, setLoading] = aState(true);
  const [newModTitle, setNewModTitle] = aState('');
  const [uploadStates, setUploadStates] = aState({});
  const [errorBanner, setErrorBanner] = aState(null);
  const [renaming, setRenaming] = aState({});   // { lessonId: currentDraftTitle }
  const [dragState, setDragState] = aState({ from: null, over: null }); // drag-to-reorder

  const fetchCMS = async () => {
    if (!window.supabaseClient) return;
    setErrorBanner(null);
    const { data: mods, error } = await window.supabaseClient
      .from('modules').select('*, lessons (*, assets (*))').order('num', { ascending: true });
    await window.supabaseClient.storage.createBucket('media', { public: true }).catch(() => {});
    if (error) setErrorBanner("Failed to load CMS: " + error.message);
    else if (mods) {
      // sort lessons by position then created_at
      setModules(mods.map(m => ({
        ...m,
        lessons: [...(m.lessons || [])].sort((a, b) =>
          (a.position ?? 9999) - (b.position ?? 9999) ||
          new Date(a.created_at) - new Date(b.created_at)
        ),
      })));
    }
    setLoading(false);
  };

  aEffect(() => { fetchCMS(); }, []);

  const createModule = async () => {
    if (!newModTitle) return;
    const { error } = await window.supabaseClient.from('modules').insert({ title: newModTitle, num: modules.length + 1, status: 'draft' }).select();
    if (!error) { setNewModTitle(''); fetchCMS(); }
    else alert("Error: " + error.message);
  };

  const createLesson = async (modId) => {
    const title = prompt("Lesson title:");
    if (!title) return;
    const mod = modules.find(m => m.id === modId);
    const nextPos = mod ? (mod.lessons || []).length : 0;
    const { error } = await window.supabaseClient.from('lessons')
      .insert({ module_id: modId, title, status: 'draft', position: nextPos }).select();
    if (error) { setErrorBanner("Lesson Add Error: " + error.message); }
    else await fetchCMS();
  };

  const startRename = (l) => setRenaming(r => ({ ...r, [l.id]: l.title }));
  const cancelRename = (id) => setRenaming(r => { const n = { ...r }; delete n[id]; return n; });

  const saveRename = async (id) => {
    const newTitle = (renaming[id] || '').trim();
    if (!newTitle) return;
    const { error } = await window.supabaseClient.from('lessons').update({ title: newTitle }).eq('id', id);
    if (error) { setErrorBanner("Rename failed: " + error.message); return; }
    cancelRename(id);
    setModules(ms => ms.map(m => ({
      ...m, lessons: (m.lessons || []).map(l => l.id === id ? { ...l, title: newTitle } : l),
    })));
  };

  const reorderLessons = async (moduleId, lessons) => {
    // Optimistic update
    setModules(ms => ms.map(m => m.id === moduleId ? { ...m, lessons } : m));
    // Persist positions
    const updates = lessons.map((l, i) =>
      window.supabaseClient.from('lessons').update({ position: i }).eq('id', l.id)
    );
    await Promise.all(updates);
  };

  const onDragStart = (e, lessonId) => {
    setDragState({ from: lessonId, over: null });
    e.dataTransfer.effectAllowed = 'move';
  };
  const onDragOver = (e, lessonId) => {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    if (dragState.over !== lessonId) setDragState(s => ({ ...s, over: lessonId }));
  };
  const onDragLeave = () => setDragState(s => ({ ...s, over: null }));
  const onDrop = (e, moduleId, targetId) => {
    e.preventDefault();
    const { from } = dragState;
    setDragState({ from: null, over: null });
    if (!from || from === targetId) return;
    const mod = modules.find(m => m.id === moduleId);
    if (!mod) return;
    const lessons = [...(mod.lessons || [])];
    const fromIdx = lessons.findIndex(l => l.id === from);
    const toIdx   = lessons.findIndex(l => l.id === targetId);
    if (fromIdx === -1 || toIdx === -1) return;
    lessons.splice(toIdx, 0, lessons.splice(fromIdx, 1)[0]);
    reorderLessons(moduleId, lessons);
  };
  const onDragEnd = () => setDragState({ from: null, over: null });

  const handleUpload = async (e, lessonId) => {
    const file = e.target.files[0];
    if (!file) return;
    setUploadStates(prev => ({ ...prev, [lessonId]: 'uploading' }));
    setErrorBanner(null);
    const fileName = `lessons/${lessonId}/${Date.now()}_${file.name.replace(/[^a-zA-Z0-9._-]/g, '_')}`;
    const { error } = await window.supabaseClient.storage.from('media').upload(fileName, file);
    if (error) {
      setErrorBanner("Upload Error: " + error.message);
      setUploadStates(prev => ({ ...prev, [lessonId]: 'error' }));
      return;
    }
    const { error: dbError } = await window.supabaseClient.from('assets').insert({ lesson_id: lessonId, storage_path: fileName, file_type: file.type, size: file.size });
    if (dbError) {
      setErrorBanner("Asset DB Error: " + dbError.message);
      setUploadStates(prev => ({ ...prev, [lessonId]: 'error' }));
    } else {
      setUploadStates(prev => ({ ...prev, [lessonId]: 'success' }));
      fetchCMS();
    }
  };

  const getUrl = (path) => {
    if (!window.supabaseClient) return '#';
    const { data: { publicUrl } } = window.supabaseClient.storage.from('media').getPublicUrl(path);
    return publicUrl;
  };

  if (loading) return <div style={{ padding: 40, textAlign: 'center' }}>Loading CMS...</div>;

  return (
    <div>
      {errorBanner && (
        <div style={{ padding: 14, background: '#fee', color: '#c0392b', border: '1px solid #e74c3c', borderRadius: 8, marginBottom: 20, fontWeight: 500 }}>
          {errorBanner}
        </div>
      )}

      <div className="card card-pad" style={{ marginTop: 8, background: 'var(--surface-2)' }}>
        <h3 style={{ marginBottom: 12 }}>Create Module</h3>
        <div className="row gap-10">
          <input value={newModTitle} onChange={e => setNewModTitle(e.target.value)} placeholder="Module title…" className="card-pad" style={{ flex: 1, border: '1px solid var(--border)', borderRadius: 10, background: 'var(--surface)', color: 'var(--text)' }}
            onKeyDown={e => e.key === 'Enter' && createModule()} />
          <button className="btn btn-primary" onClick={createModule}><Icon name="plus" size={16} /> Add Module</button>
        </div>
      </div>

      <div className="stack" style={{ marginTop: 24, gap: 20 }}>
        {modules.map(m => (
          <div key={m.id} className="card card-pad">
            <div className="row" style={{ justifyContent: 'space-between', marginBottom: 14 }}>
              <h2 style={{ fontSize: 22 }}>{m.num}. {m.title} <span className="pill" style={{ marginLeft: 8, fontSize: 11 }}>{m.status}</span></h2>
              <button className="btn btn-ghost btn-sm" onClick={() => createLesson(m.id)}><Icon name="plus" size={15} /> Add Lesson</button>
            </div>
            <div className="stack" style={{ gap: 10 }}>
              {m.lessons && m.lessons.map(l => {
                const isRenaming = renaming.hasOwnProperty(l.id);
                const isDragging = dragState.from === l.id;
                const isOver    = dragState.over === l.id && dragState.from !== l.id;
                return (
                  <div key={l.id}
                    draggable={!isRenaming}
                    onDragStart={e => onDragStart(e, l.id)}
                    onDragOver={e => onDragOver(e, l.id)}
                    onDragLeave={onDragLeave}
                    onDrop={e => onDrop(e, m.id, l.id)}
                    onDragEnd={onDragEnd}
                    className="card"
                    style={{
                      padding: 16, background: 'var(--bg)',
                      border: '1px solid ' + (isOver ? 'var(--lime)' : 'var(--border)'),
                      opacity: isDragging ? 0.45 : 1,
                      boxShadow: isOver ? '0 0 0 3px var(--lime-soft)' : 'none',
                      transition: 'border-color .12s, box-shadow .12s, opacity .12s',
                      cursor: isRenaming ? 'default' : 'grab',
                    }}>
                    <div className="row" style={{ justifyContent: 'space-between', marginBottom: 10, gap: 10 }}>
                      {/* Drag handle + title/rename */}
                      <div className="row gap-10" style={{ flex: 1, minWidth: 0, alignItems: 'center' }}>
                        <span title="Drag to reorder" style={{ color: 'var(--border-strong)', fontSize: 18, lineHeight: 1, flex: 'none', cursor: 'grab', userSelect: 'none' }}>⠿</span>
                        {isRenaming ? (
                          <div className="row gap-8" style={{ flex: 1, minWidth: 0 }}>
                            <input
                              autoFocus
                              value={renaming[l.id]}
                              onChange={e => setRenaming(r => ({ ...r, [l.id]: e.target.value }))}
                              onKeyDown={e => { if (e.key === 'Enter') saveRename(l.id); if (e.key === 'Escape') cancelRename(l.id); }}
                              style={{ flex: 1, minWidth: 0, fontWeight: 700, fontSize: 15, padding: '5px 10px', borderRadius: 8, border: '2px solid var(--lime)', outline: 'none', background: 'var(--surface-1)', color: 'var(--text)' }}
                            />
                            <button className="btn btn-primary btn-sm" onClick={() => saveRename(l.id)}>Save</button>
                            <button className="btn btn-ghost btn-sm" onClick={() => cancelRename(l.id)}>Cancel</button>
                          </div>
                        ) : (
                          <h3 style={{ fontSize: 16, margin: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                            {l.title}
                            <span className="pill async" style={{ marginLeft: 8, fontSize: 11 }}>{l.status}</span>
                          </h3>
                        )}
                      </div>
                      {/* Actions */}
                      {!isRenaming && (
                        <div className="row gap-8" style={{ flex: 'none' }}>
                          <button className="btn btn-ghost btn-sm" onClick={() => startRename(l)} title="Rename lesson">
                            <Icon name="pen" size={14} /> Rename
                          </button>
                          {go && (
                            <button className="btn btn-soft btn-sm" onClick={() => go({ name: 'editor', id: l.id })}>
                              <Icon name="pen" size={14} /> Edit blocks
                            </button>
                          )}
                        </div>
                      )}
                    </div>
                    {l.assets && l.assets.length > 0 && (
                      <div style={{ marginBottom: 10 }}>
                        {l.assets.map(a => (
                          <div key={a.id} className="row gap-10" style={{ fontSize: 13, color: 'var(--text-muted)', marginBottom: 4 }}>
                            <Icon name="book" size={14} />
                            <a href={getUrl(a.storage_path)} target="_blank" style={{ color: 'var(--lime-strong)', textDecoration: 'none', fontWeight: 600 }}>{a.storage_path.split('/').pop()}</a>
                            <span style={{ fontSize: 11 }}>{a.file_type}</span>
                          </div>
                        ))}
                      </div>
                    )}
                    <label className="btn btn-soft btn-sm" style={{ display: 'inline-flex', cursor: 'pointer' }}>
                      <Icon name="upload" size={15} /> {uploadStates[l.id] === 'uploading' ? 'Uploading…' : 'Upload Media'}
                      <input type="file" style={{ display: 'none' }} onChange={e => handleUpload(e, l.id)} disabled={uploadStates[l.id] === 'uploading'} />
                    </label>
                    {uploadStates[l.id] === 'success' && <span style={{ marginLeft: 10, color: 'var(--lime-strong)', fontSize: 13, fontWeight: 700 }}>Uploaded!</span>}
                    {uploadStates[l.id] === 'error' && <span style={{ marginLeft: 10, color: '#e74c3c', fontSize: 13 }}>Failed.</span>}
                  </div>
                );
              })}
              {(!m.lessons || m.lessons.length === 0) && <p className="muted" style={{ fontSize: 14, padding: '8px 0' }}>No lessons yet — add one above.</p>}
            </div>
          </div>
        ))}
        {modules.length === 0 && <p className="muted">No modules created yet. Build your curriculum above!</p>}
      </div>
    </div>
  );
}

/* ---- Live Sessions Panel ---- */
function fmtSessionDate(iso) {
  return new Date(iso).toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric' })
    + ' · ' + new Date(iso).toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
}

function SessionRow({ s, onEdit, onDelete }) {
  const endMs = new Date(s.scheduled_for).getTime() + (s.duration_minutes || 60) * 60 * 1000;
  const isPast = Date.now() > endMs;
  return (
    <div className="card card-pad" style={{ display: 'flex', alignItems: 'center', gap: 16, borderLeft: `4px solid ${isPast ? 'var(--border)' : 'var(--lime)'}`, opacity: isPast ? 0.72 : 1 }}>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div className="row gap-8" style={{ marginBottom: 4 }}>
          <span className="pill" style={{ fontSize: 11, background: isPast ? 'var(--surface-2)' : 'rgba(143,191,46,.15)', color: isPast ? 'var(--text-muted)' : 'var(--lime-strong)' }}>
            {isPast ? 'Past' : 'Upcoming'}
          </span>
          {s.module_title && <span className="muted" style={{ fontSize: 12 }}>{s.module_title}</span>}
        </div>
        <p style={{ fontWeight: 700, fontSize: 15, margin: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{s.title}</p>
        <div className="row gap-12" style={{ marginTop: 4, color: 'var(--text-muted)', fontSize: 13, flexWrap: 'wrap' }}>
          <span className="row gap-4"><Icon name="calendar" size={13} /> {fmtSessionDate(s.scheduled_for)}</span>
          {s.instructor && <span className="row gap-4"><Icon name="users" size={13} /> {s.instructor}</span>}
          {s.duration_minutes && <span className="row gap-4"><Icon name="clock" size={13} /> {s.duration_minutes} min</span>}
          {isPast && s.recording_url && <span style={{ color: 'var(--lime-strong)', fontWeight: 700 }}>Recording available</span>}
        </div>
      </div>
      <div className="row gap-8" style={{ flex: 'none' }}>
        <button className="btn btn-ghost btn-sm" onClick={onEdit}><Icon name="pen" size={14} /> Edit</button>
        <button className="btn btn-ghost btn-sm" style={{ color: '#DC2626', borderColor: 'rgba(220,38,38,.3)' }} onClick={onDelete}><Icon name="trash" size={14} /> Delete</button>
      </div>
    </div>
  );
}

function LiveSessionsPanel() {
  const BLANK = { title: '', scheduled_for: '', instructor: '', duration_minutes: 60, module_title: '', meeting_url: '', description: '', recording_url: '' };
  const [sessions, setSessions] = aState([]);
  const [loading, setLoading] = aState(true);
  const [modal, setModal] = aState(null);
  const [form, setForm] = aState(BLANK);
  const [saving, setSaving] = aState(false);
  const [deleteId, setDeleteId] = aState(null);

  aEffect(() => { load(); }, []);

  async function load() {
    setLoading(true);
    if (!window.supabaseClient) { setLoading(false); return; }
    const { data } = await window.supabaseClient.from('live_sessions').select('*').order('scheduled_for', { ascending: true });
    setSessions(data || []);
    setLoading(false);
  }

  function openNew() {
    const d = new Date(); d.setMinutes(0, 0, 0); d.setHours(d.getHours() + 1);
    setForm({ ...BLANK, scheduled_for: d.toISOString().slice(0, 16) });
    setModal({ mode: 'new' });
  }

  function openEdit(s) {
    setForm({
      title: s.title || '', scheduled_for: s.scheduled_for ? s.scheduled_for.slice(0, 16) : '',
      instructor: s.instructor || '', duration_minutes: s.duration_minutes || 60,
      module_title: s.module_title || '', meeting_url: s.meeting_url || '',
      description: s.description || '', recording_url: s.recording_url || '',
    });
    setModal({ mode: 'edit', id: s.id });
  }

  async function save() {
    if (!form.title || !form.scheduled_for) return;
    setSaving(true);
    const payload = {
      title: form.title, scheduled_for: new Date(form.scheduled_for).toISOString(),
      instructor: form.instructor || null, duration_minutes: Number(form.duration_minutes) || 60,
      module_title: form.module_title || null, meeting_url: form.meeting_url || null,
      description: form.description || null, recording_url: form.recording_url || null,
    };
    if (modal.mode === 'new') await window.supabaseClient.from('live_sessions').insert(payload);
    else await window.supabaseClient.from('live_sessions').update(payload).eq('id', modal.id);
    setSaving(false); setModal(null); load();
  }

  async function del() {
    await window.supabaseClient.from('live_sessions').delete().eq('id', deleteId);
    setDeleteId(null); load();
  }

  const fld = key => ({ value: form[key] ?? '', onChange: e => setForm(f => ({ ...f, [key]: e.target.value })) });

  const nowMs = Date.now();
  const sessionEnd = s => new Date(s.scheduled_for).getTime() + (s.duration_minutes || 60) * 60 * 1000;
  const upcoming = sessions.filter(s => sessionEnd(s) > nowMs);
  const past     = sessions.filter(s => sessionEnd(s) <= nowMs);

  return (
    <div style={{ marginTop: 24 }}>
      <div className="row" style={{ justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
        <p className="muted" style={{ margin: 0, fontSize: 14 }}>{upcoming.length} upcoming · {past.length} past</p>
        <button className="btn btn-primary btn-sm" onClick={openNew}><Icon name="plus" size={16} /> Add Session</button>
      </div>

      {loading ? (
        <div className="stack" style={{ gap: 12 }}>{[1,2,3].map(i => <Skeleton key={i} height={80} radius={12} />)}</div>
      ) : sessions.length === 0 ? (
        <div className="card card-pad" style={{ textAlign: 'center', padding: '48px 24px', color: 'var(--text-muted)' }}>
          <Icon name="calendar" size={36} style={{ marginBottom: 12 }} />
          <p style={{ fontWeight: 700, fontSize: 16 }}>No live sessions yet</p>
          <p style={{ fontSize: 14, marginTop: 4 }}>Click "Add Session" to schedule your first one.</p>
        </div>
      ) : (
        <>
          {upcoming.length > 0 && <>
            <p style={{ fontWeight: 800, fontSize: 12, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 10 }}>Upcoming</p>
            <div className="stack" style={{ gap: 10, marginBottom: 24 }}>
              {upcoming.map(s => <SessionRow key={s.id} s={s} onEdit={() => openEdit(s)} onDelete={() => setDeleteId(s.id)} />)}
            </div>
          </>}
          {past.length > 0 && <>
            <p style={{ fontWeight: 800, fontSize: 12, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: 10 }}>Past</p>
            <div className="stack" style={{ gap: 10 }}>
              {[...past].reverse().map(s => <SessionRow key={s.id} s={s} onEdit={() => openEdit(s)} onDelete={() => setDeleteId(s.id)} />)}
            </div>
          </>}
        </>
      )}

      {/* Create / Edit modal */}
      {modal && (
        <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.6)', backdropFilter: 'blur(10px)', zIndex: 5000, display: 'grid', placeItems: 'center', padding: 20 }}>
          <div style={{ width: '100%', maxWidth: 600, maxHeight: '92vh', overflowY: 'auto', borderRadius: 20, background: 'var(--surface)', border: '1px solid var(--border)', boxShadow: '0 32px 80px rgba(0,0,0,.4)' }}>

            {/* Header */}
            <div style={{ background: 'var(--brand-ink)', borderRadius: '20px 20px 0 0', padding: '26px 30px' }}>
              <div className="row gap-12" style={{ alignItems: 'center' }}>
                <div style={{ width: 42, height: 42, borderRadius: 12, background: 'rgba(143,191,46,.18)', display: 'grid', placeItems: 'center', flex: 'none' }}>
                  <Icon name="calendar" size={20} style={{ color: '#BCEA72' }} />
                </div>
                <div>
                  <p style={{ margin: 0, fontSize: 11, fontWeight: 800, letterSpacing: '.12em', textTransform: 'uppercase', color: 'rgba(255,255,255,.45)' }}>Live Session</p>
                  <h2 style={{ margin: 0, fontSize: 19, fontWeight: 800, color: '#fff' }}>{modal.mode === 'new' ? 'Schedule a New Session' : 'Edit Session Details'}</h2>
                </div>
              </div>
            </div>

            <div style={{ padding: '26px 30px' }}>

              {/* Title */}
              <label className="stack" style={{ gap: 7, marginBottom: 22 }}>
                <span style={{ fontSize: 12, fontWeight: 800, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--text-muted)' }}>Session Title <span style={{ color: '#f55' }}>*</span></span>
                <input className="input" style={{ fontSize: 16, fontWeight: 700 }} placeholder="e.g. Orientation & Welcome" {...fld('title')} />
              </label>

              {/* When & Where */}
              <div style={{ borderTop: '1px solid var(--border)', paddingTop: 18, marginBottom: 18 }}>
                <p style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--lime-strong)', margin: '0 0 14px' }}>When &amp; Where</p>
                <div className="stack" style={{ gap: 12 }}>
                  <div className="row gap-12">
                    <label className="stack" style={{ gap: 6, flex: 2 }}>
                      <span style={{ fontSize: 12, fontWeight: 700, color: 'var(--text-muted)' }}>Date &amp; Time <span style={{ color: '#f55' }}>*</span></span>
                      <input className="input" type="datetime-local" {...fld('scheduled_for')} />
                    </label>
                    <label className="stack" style={{ gap: 6, flex: 1 }}>
                      <span style={{ fontSize: 12, fontWeight: 700, color: 'var(--text-muted)' }}>Duration (min)</span>
                      <input className="input" type="number" min="15" step="15" {...fld('duration_minutes')} />
                    </label>
                  </div>
                  <label className="stack" style={{ gap: 6 }}>
                    <span style={{ fontSize: 12, fontWeight: 700, color: 'var(--text-muted)' }}>Join URL — Zoom / Meet / Teams</span>
                    <div style={{ position: 'relative' }}>
                      <span style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none' }}><Icon name="play" size={14} style={{ color: 'var(--text-muted)' }} /></span>
                      <input className="input" type="url" placeholder="https://zoom.us/j/..." style={{ paddingLeft: 34 }} {...fld('meeting_url')} />
                    </div>
                  </label>
                </div>
              </div>

              {/* Session Details */}
              <div style={{ borderTop: '1px solid var(--border)', paddingTop: 18, marginBottom: 18 }}>
                <p style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--lime-strong)', margin: '0 0 14px' }}>Session Details</p>
                <div className="stack" style={{ gap: 12 }}>
                  <div className="row gap-12">
                    <label className="stack" style={{ gap: 6, flex: 1 }}>
                      <span style={{ fontSize: 12, fontWeight: 700, color: 'var(--text-muted)' }}>Instructor</span>
                      <input className="input" placeholder="e.g. Christine Janssen" {...fld('instructor')} />
                    </label>
                    <label className="stack" style={{ gap: 6, flex: 1 }}>
                      <span style={{ fontSize: 12, fontWeight: 700, color: 'var(--text-muted)' }}>Module context</span>
                      <input className="input" placeholder="e.g. Module 1: Foundations" {...fld('module_title')} />
                    </label>
                  </div>
                  <label className="stack" style={{ gap: 6 }}>
                    <span style={{ fontSize: 12, fontWeight: 700, color: 'var(--text-muted)' }}>Agenda / Description</span>
                    <textarea className="input" rows={4} placeholder="What will learners cover? Paste your agenda, key topics, or prep notes here." {...fld('description')} />
                  </label>
                </div>
              </div>

              {/* Post-session */}
              <div style={{ borderTop: '1px solid var(--border)', paddingTop: 18, marginBottom: 24 }}>
                <p style={{ fontSize: 11, fontWeight: 800, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--text-muted)', margin: '0 0 14px' }}>Post-Session</p>
                <label className="stack" style={{ gap: 6 }}>
                  <span style={{ fontSize: 12, fontWeight: 700, color: 'var(--text-muted)' }}>Recording URL <span style={{ fontWeight: 400, color: 'var(--text-muted)' }}>— add after the session ends</span></span>
                  <input className="input" type="url" placeholder="https://..." {...fld('recording_url')} />
                </label>
              </div>

              {/* Actions */}
              <div className="row gap-10" style={{ justifyContent: 'flex-end' }}>
                <button className="btn btn-ghost" onClick={() => setModal(null)}>Cancel</button>
                <button className="btn btn-primary" onClick={save} disabled={saving || !form.title || !form.scheduled_for}>
                  {saving ? 'Saving…' : modal.mode === 'new' ? 'Create Session' : 'Save Changes'}
                </button>
              </div>

            </div>
          </div>
        </div>
      )}

      {/* Delete confirm */}
      {deleteId && (
        <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.55)', backdropFilter: 'blur(8px)', zIndex: 5000, display: 'grid', placeItems: 'center', padding: 20 }}>
          <div className="card" style={{ maxWidth: 400, width: '100%', padding: '28px 32px' }}>
            <h3 style={{ fontSize: 18, marginBottom: 10 }}>Delete this session?</h3>
            <p className="muted" style={{ fontSize: 15, marginBottom: 24 }}>This cannot be undone.</p>
            <div className="row gap-10" style={{ justifyContent: 'flex-end' }}>
              <button className="btn btn-ghost" onClick={() => setDeleteId(null)}>Cancel</button>
              <button className="btn btn-primary" style={{ background: '#DC2626', borderColor: '#DC2626' }} onClick={del}>Delete</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

const ADMIN_TABS = [
  { id: 'data',        label: 'Analytics',      icon: 'target' },
  { id: 'content',     label: 'Content CMS',    icon: 'layers' },
  { id: 'live',        label: 'Live Sessions',  icon: 'calendar' },
  { id: 'tickets',     label: 'Support Tickets', icon: 'chat' },
  { id: 'submissions', label: 'Submissions',    icon: 'upload' },
  { id: 'rubrics',     label: 'Rubrics',        icon: 'layers' },
  { id: 'gradebook',   label: 'Gradebook',      icon: 'target' },
];

function Admin({ go }) {
  const [activeTab, setActiveTab] = aState('data');

  return (
    <div className="page page-wide enter">
      <span className="eyebrow">Admin Environment</span>
      <h1 style={{ fontSize: 36, marginTop: 6 }}>Admin Dashboard</h1>

      {/* Tab bar */}
      <div className="row gap-4" style={{ marginTop: 24, borderBottom: '1px solid var(--border)', paddingBottom: 0 }}>
        {ADMIN_TABS.map(tab => (
          <button key={tab.id} onClick={() => setActiveTab(tab.id)}
            className="row gap-8"
            style={{ border: 'none', background: 'none', cursor: 'pointer', padding: '10px 18px', fontFamily: 'var(--font-head)', fontWeight: 700, fontSize: 15,
              color: activeTab === tab.id ? 'var(--lime-strong)' : 'var(--text-muted)',
              borderBottom: activeTab === tab.id ? '2.5px solid var(--lime-strong)' : '2.5px solid transparent',
              marginBottom: -1, transition: 'color .15s, border-color .15s' }}>
            <Icon name={tab.icon} size={17} /> {tab.label}
          </button>
        ))}
      </div>

      {activeTab === 'data'        && <DataDashboard />}
      {activeTab === 'content'     && <CMSPanel go={go} />}
      {activeTab === 'live'        && <LiveSessionsPanel />}
      {activeTab === 'tickets'     && <TicketsPanel />}
      {activeTab === 'submissions' && <SubmissionsPanel />}
      {activeTab === 'rubrics'     && window.RubricsAdmin  && React.createElement(window.RubricsAdmin)}
      {activeTab === 'gradebook'   && window.GradebookAdmin && React.createElement(window.GradebookAdmin)}
    </div>
  );
}

window.Admin = Admin;
