// src/features/admin/ui/admin-gcal-reviews.jsx
//
// Admin "Google Changes" tab — the review queue for lesson changes a teacher
// made on their Google Calendar (delete / move / resize). Per Joe's "hold for
// my approval" decision, the sync engine does NOT auto-apply these; it queues
// them here and the admin Accepts (apply to the booking) or Rejects (keep as-is).
//
// v153 — "needs_student" rows: an unrecognised Google lesson title (e.g. a
// nickname "Amay") collapses to ONE card per title. Pick the student once and
// every in-window instance of that title becomes a lesson + future ones auto-
// resolve (the map is remembered). "Not a lesson" marks it busy time forever.
//
// Reads via window.supa.rpc('gcal_review_list'); acts via gcal_review_accept /
// gcal_review_reject / gcal_review_assign_student / gcal_review_mark_block (all
// admin-gated in the DB). Mounted as <window.AdminGcalReviews/>.

// One "who is this?" card — own student list + picker so cards load independently.
const NeedsStudentCard = ({ r, fmtDate, card, onDone }) => {
  const [students, setStudents] = React.useState(null);   // null = loading
  const [pick, setPick] = React.useState('');
  const [busy, setBusy] = React.useState(false);

  React.useEffect(() => {
    let alive = true;
    window.supa.rpc('gcal_review_students_for', { p_id: r.id })
      .then(({ data }) => { if (alive) setStudents(data || []); })
      .catch(() => { if (alive) setStudents([]); });
    return () => { alive = false; };
  }, [r.id]);

  const run = async (fn, body) => {
    setBusy(true);
    try {
      const { error } = await window.supa.rpc(fn, body);
      if (error) throw error;
      onDone(r.id);
    } catch (e) { alert(e.message || 'Action failed'); setBusy(false); }
  };

  const count = r.instance_count || 1;
  const amber = 'oklch(48% 0.14 75)';
  const btn = (bg, fg, bd) => ({ background:bg, color:fg, border:bd||'none', borderRadius:8, padding:'8px 14px',
    fontSize:13, fontWeight:700, cursor:busy?'wait':'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif" });

  return (
    <div style={{ ...card, borderColor:'oklch(86% 0.07 75)', background:'oklch(99% 0.01 75)' }}>
      <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap', marginBottom:6 }}>
        <span style={{ background:amber, color:'#fff', borderRadius:6, padding:'2px 9px', fontSize:11, fontWeight:700 }}>Who is this?</span>
        <span style={{ fontSize:14, fontWeight:700, color:'oklch(22% 0.06 265)' }}>{r.event_title || '(untitled)'}</span>
        <span style={{ fontSize:12, color:'oklch(58% 0.03 265)' }}>· {r.teacher || r.google_email || 'teacher'}</span>
      </div>
      <div style={{ fontSize:13, color:'oklch(38% 0.05 265)', marginBottom:10 }}>
        {count} lesson{count > 1 ? 's' : ''} on Google starting <b>{fmtDate(r.proposed_scheduled_at)}</b>
        {r.proposed_duration ? ` (${r.proposed_duration} min)` : ''}. Map it to a student once — it sticks for every future one.
      </div>
      <div style={{ display:'flex', gap:8, flexWrap:'wrap', alignItems:'center' }}>
        <select value={pick} onChange={e => setPick(e.target.value)} disabled={busy || students === null}
          style={{ flex:'1 1 200px', minWidth:160, padding:'8px 10px', borderRadius:8, border:'1px solid oklch(85% 0.03 265)',
                   fontSize:13, fontFamily:"'Plus Jakarta Sans', sans-serif", background:'#fff' }}>
          <option value="">{students === null ? 'Loading students…' : 'Select student…'}</option>
          {(students || []).map(s => <option key={s.student_id} value={s.student_id}>{s.full_name}</option>)}
        </select>
        <button disabled={!pick || busy} onClick={() => run('gcal_review_assign_student', { p_id: r.id, p_student_id: pick })}
          style={{ ...btn('oklch(32% 0.14 150)', '#fff'), opacity:(!pick||busy)?0.55:1 }}>
          {count > 1 ? `Add all ${count}` : 'Add lesson'}
        </button>
        <button disabled={busy} onClick={() => run('gcal_review_mark_block', { p_id: r.id })}
          style={btn('#fff', 'oklch(42% 0.04 265)', '1px solid oklch(85% 0.03 265)')}>
          Not a lesson
        </button>
      </div>
    </div>
  );
};

const AdminGcalReviews = () => {
  const [rows,    setRows]    = React.useState(null);   // null = loading
  const [busyId,  setBusyId]  = React.useState(null);
  const [error,   setError]   = React.useState('');

  const load = React.useCallback(async () => {
    try {
      const { data, error } = await window.supa.rpc('gcal_review_list');
      if (error) throw error;
      setRows(data || []);
      setError('');
    } catch (e) {
      setError(e.message || 'Could not load changes');
      setRows([]);
    }
  }, []);

  React.useEffect(() => {
    load();
    // Live-refresh: a new change can land any minute from the sync cron.
    let ch = null;
    if (window.supa && window.supa.channel) {
      ch = window.supa.channel('gcal-change-reviews')
        .on('postgres_changes', { event: '*', schema: 'public', table: 'gcal_change_reviews' }, () => load())
        .subscribe();
    }
    return () => { if (ch && window.supa.removeChannel) { try { window.supa.removeChannel(ch); } catch (_) {} } };
  }, [load]);

  const act = async (id, accept) => {
    setBusyId(id);
    try {
      const { error } = await window.supa.rpc(accept ? 'gcal_review_accept' : 'gcal_review_reject', { p_id: id });
      if (error) throw error;
      setRows(rs => (rs || []).filter(r => r.id !== id));   // optimistic
    } catch (e) {
      alert(e.message || 'Action failed');
      load();
    } finally {
      setBusyId(null);
    }
  };

  const fmtDate = (iso) => {
    if (!iso) return '—';
    try { return new Date(iso).toLocaleString(undefined, { weekday:'short', month:'short', day:'numeric', hour:'numeric', minute:'2-digit' }); }
    catch (_) { return iso; }
  };

  // Human description of the proposed change, with before → after.
  const describe = (r) => {
    // A named Google event that isn't on the platform yet -> add it as a lesson.
    if (r.target_kind === 'lesson_add') {
      if (r.change_type === 'delete') {
        return { tag: 'Lesson removed', color: 'oklch(50% 0.18 25)', detail:
          <span><b>{r.event_title}</b> was deleted on Google — remove it from the platform.</span> };
      }
      return { tag: 'Add lesson', color: 'oklch(38% 0.15 150)', detail:
        <span>Add <b>{r.event_title}</b> as a lesson at <b>{fmtDate(r.proposed_scheduled_at)}</b>{r.proposed_duration ? ` (${r.proposed_duration} min)` : ''}.</span> };
    }
    // A non-lesson Google event -> busy time / availability only.
    if (r.target_kind === 'block') {
      if (r.change_type === 'block_delete') {
        return { tag: 'Busy time removed', color: 'oklch(52% 0.05 265)', detail:
          <span><b>{r.event_title || 'Busy time'}</b> was removed on Google.</span> };
      }
      return { tag: 'Busy time', color: 'oklch(52% 0.05 265)', detail:
        <span><b>{r.event_title || 'Busy time'}</b> at <b>{fmtDate(r.proposed_scheduled_at)}</b>{r.proposed_duration ? ` (${r.proposed_duration} min)` : ''} — not a lesson; updates availability only.</span> };
    }
    if (r.change_type === 'delete') {
      return { tag: 'Delete', color: 'oklch(50% 0.18 25)', detail:
        <span>Cancel this lesson — it was <b>{fmtDate(r.current_scheduled_at)}</b> ({r.current_duration} min){r.current_status === 'completed' ? ' · was marked completed' : ''}.</span> };
    }
    if (r.change_type === 'resize') {
      return { tag: 'Duration', color: 'oklch(45% 0.13 265)', detail:
        <span><b>{r.current_duration} min</b> → <b>{r.proposed_duration} min</b> · {fmtDate(r.current_scheduled_at)}</span> };
    }
    // move / move_resize
    return { tag: r.change_type === 'move_resize' ? 'Move + duration' : 'Reschedule', color: 'oklch(40% 0.14 75)', detail:
      <span><b>{fmtDate(r.current_scheduled_at)}</b> → <b>{fmtDate(r.proposed_scheduled_at)}</b>
        {r.proposed_duration && r.proposed_duration !== r.current_duration ? <> · {r.current_duration}→{r.proposed_duration} min</> : null}</span> };
  };

  const card = { background:'#fff', border:'1px solid oklch(91% 0.01 265)', borderRadius:12, padding:'14px 16px' };

  return (
    <div style={{ fontFamily:"'Plus Jakarta Sans', sans-serif", maxWidth: 860 }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:14, gap:12, flexWrap:'wrap' }}>
        <div style={{ fontSize:13, color:'oklch(46% 0.04 265)' }}>
          Changes a teacher made on Google Calendar. Nothing is applied to the platform until you <b>Accept</b> it.
        </div>
        <button onClick={load} style={{ background:'oklch(96% 0.01 265)', border:'1px solid oklch(88% 0.02 265)', borderRadius:9, padding:'7px 13px', fontSize:12, fontWeight:600, color:'oklch(40% 0.04 265)', cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif", flexShrink:0 }}>Refresh</button>
      </div>

      {error && (
        <div style={{ ...card, borderColor:'oklch(85% 0.1 25)', color:'oklch(40% 0.16 25)', marginBottom:14 }}>{error}</div>
      )}

      {rows === null ? (
        <div style={{ ...card, textAlign:'center', color:'oklch(58% 0.03 265)', padding:'40px 24px' }}>Loading…</div>
      ) : rows.length === 0 ? (
        <div style={{ ...card, textAlign:'center', color:'oklch(56% 0.03 265)', padding:'48px 24px', fontSize:14 }}>
          No pending changes. When a teacher reschedules, resizes, or deletes a lesson on their Google Calendar, it'll show up here for you to approve.
        </div>
      ) : (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          {rows.map(r => {
            if (r.change_type === 'needs_student') {
              return (
                <NeedsStudentCard key={r.id} r={r} fmtDate={fmtDate} card={card}
                  onDone={(id) => setRows(rs => (rs || []).filter(x => x.id !== id))} />
              );
            }
            const d = describe(r);
            const busy = busyId === r.id;
            return (
              <div key={r.id} style={{ ...card, display:'grid', gridTemplateColumns:'1fr auto', gap:14, alignItems:'center' }}>
                <div style={{ minWidth:0 }}>
                  <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap', marginBottom:4 }}>
                    <span style={{ background:d.color, color:'#fff', borderRadius:6, padding:'2px 9px', fontSize:11, fontWeight:700 }}>{d.tag}</span>
                    <span style={{ fontSize:14, fontWeight:700, color:'oklch(22% 0.06 265)' }}>{r.student_name || r.event_title || '—'}</span>
                    <span style={{ fontSize:12, color:'oklch(58% 0.03 265)' }}>· {r.teacher || r.google_email || 'teacher'}</span>
                  </div>
                  <div style={{ fontSize:13, color:'oklch(38% 0.05 265)' }}>{d.detail}</div>
                </div>
                <div style={{ display:'flex', gap:8, flexShrink:0 }}>
                  <button disabled={busy} onClick={() => act(r.id, true)}
                    style={{ background:'oklch(32% 0.14 150)', color:'#fff', border:'none', borderRadius:8, padding:'8px 16px', fontSize:13, fontWeight:700, cursor:busy?'wait':'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>
                    Accept
                  </button>
                  <button disabled={busy} onClick={() => act(r.id, false)}
                    style={{ background:'#fff', color:'oklch(42% 0.1 25)', border:'1px solid oklch(86% 0.08 25)', borderRadius:8, padding:'8px 16px', fontSize:13, fontWeight:700, cursor:busy?'wait':'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>
                    Reject
                  </button>
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
};

Object.assign(window, { AdminGcalReviews });
