// src/features/admin/ui/admin-instructors-modals-3.jsx
//
// Third slice of the AdminInstructors modals: the book-a-lesson
// modal (admin manually creates a booking) and the confirm-delete
// modal. Split off from admin-instructors-modals-2.jsx so both
// halves stay under the 400 LOC budget.
//
// Public on window: AIBookLessonModal, AIConfirmDelete,
// plus the AdminBookLessonModal legacy alias.

// ── Book Lesson Modal (admin manually books a class for a student) ──────────
// Picks a student already assigned to this instructor + date/time/duration.
// The booking is created with status='confirmed' and the rate is snapshotted
// from the assignment (handled by data.addBooking).
const AIBookLessonModal = ({ instructor, onClose }) => {
  const data = window.useAdminData();
  const [studentId, setStudentId] = React.useState('');
  const [date,      setDate]      = React.useState(() => new Date().toISOString().slice(0,10));
  const [time,      setTime]      = React.useState('17:00');
  const [duration,  setDuration]  = React.useState(60);
  const [message,   setMessage]   = React.useState('');
  const [recurring, setRecurring] = React.useState(false);
  const [infinite,  setInfinite]  = React.useState(false);
  const [weeks,     setWeeks]     = React.useState(4);
  const [busy,      setBusy]      = React.useState(false);
  const [error,     setError]     = React.useState('');
  // Which zone the admin is THINKING in when typing the date+time. Defaults
  // to the browser's detected zone; the badge below lets the admin switch
  // to (e.g.) the teacher's zone so "5 PM Beirut" books at the correct
  // absolute moment instead of 5 PM whatever-the-admin's-laptop-says.
  const [tz, setTz] = React.useState(() => window.Calendar.time.detect());

  // Availability context for this instructor (weekly hours + blocked time +
  // the tz their hours are anchored to). Loaded once on open and used to
  // HARD-BLOCK booking a time the teacher hasn't opened up — the same
  // constraint the student booking page enforces. A teacher who has set no
  // weekly hours at all is treated as unconstrained (so newly-onboarded
  // teachers without a schedule can still be booked). Fails open on error.
  const [availCtx, setAvailCtx] = React.useState(null);
  React.useEffect(() => {
    let cancelled = false;
    window.Calendar.db.loadAvailabilityContext(instructor.id)
      .then(ctx => { if (!cancelled) setAvailCtx(ctx); })
      .catch(() => { if (!cancelled) setAvailCtx({ slots: [], exceptions: [], instructorTz: null }); });
    return () => { cancelled = true; };
  }, [instructor.id]);

  // Only show students that already have an assignment with this instructor —
  // otherwise the rate snapshot in addBooking would come back null.
  const myStudents = (data.assignments || [])
    .filter(a => a.instructorId === instructor.id && a.active && a.student)
    .map(a => ({ id: a.studentId, name: a.student.name, assignmentId: a.id, rates: a.rates }));

  const fld = { width:'100%', padding:'12px 14px', borderRadius:8, border:'1.5px solid oklch(88% 0.015 265)', fontSize:16, minHeight:44, fontFamily:"'Plus Jakarta Sans', sans-serif", color:'oklch(22% 0.06 265)', background:'#fff', outline:'none', boxSizing:'border-box' };
  const lbl = { display:'block', fontSize:10, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.06em', color:'oklch(52% 0.04 265)', marginBottom:5 };

  const submit = async (e) => {
    e.preventDefault();
    if (!studentId) { setError('Pick a student.'); return; }
    setBusy(true); setError('');
    try {
      // Construct the absolute UTC moment for "date+time" interpreted in the
      // selected zone (not browser-local). tzMakeDate iterates against
      // Intl.DateTimeFormat so DST spring-forward gaps converge correctly.
      const [yy, mm, dd] = date.split('-').map(Number);
      const [hh, mi]     = time.split(':').map(Number);
      const scheduledAt  = window.Calendar.time.makeDate(yy, mm, dd, hh, mi, tz).toISOString();
      // Back-dating guard: a lesson whose time is already in the past is treated
      // as one that happened — it gets auto-marked completed and counts toward
      // the teacher's payout. Confirm first so a mistyped date can't silently
      // bill the teacher; an intentional back-fill just clicks OK.
      if (new Date(scheduledAt).getTime() < Date.now()) {
        const whenStr = new Date(scheduledAt).toLocaleString(undefined, { weekday:'short', month:'short', day:'numeric', hour:'numeric', minute:'2-digit' });
        if (!window.confirm(`This lesson is in the past (${whenStr}). It'll be marked completed and count toward ${instructor.name}'s payout. Add it anyway?`)) {
          setBusy(false);
          return;
        }
      }
      if (recurring) {
        await window.MASTERY.withTimeout(
          data.createRecurringSeries({
            studentId, firstAt: scheduledAt, durationMinutes: Number(duration),
            weeks: Number(weeks) || 4, message: message || null,
            infinite: !!infinite,
          }),
          60000, 'Create recurring series',
        );
      } else {
        await window.MASTERY.withTimeout(
          data.addBooking({
            studentId, instructorId: instructor.id,
            scheduledAt, durationMinutes: Number(duration),
            message: message || null,
            status: 'confirmed',
          }),
          20000, 'Create booking',
        );
      }
      onClose();
    } catch (e2) { setError(e2.message || 'Could not book.'); }
    finally { setBusy(false); }
  };

  // Show a hint about the student-side rate that'll be snapshotted.
  const picked = myStudents.find(s => s.id === studentId);
  const rateForDur = picked?.rates?.student?.[duration];

  // Resolve the current date+time+tz selection to an absolute moment so we can
  // surface (but never block) times outside the teacher's availability.
  const pickedStart = (() => {
    const [yy, mm, dd] = (date || '').split('-').map(Number);
    const [hh, mi]     = (time || '').split(':').map(Number);
    if (!yy || !mm || !dd || hh == null || isNaN(hh)) return null;
    const d = window.Calendar.time.makeDate(yy, mm, dd, hh, mi || 0, tz);
    return isNaN(d.getTime()) ? null : d;
  })();
  // Summary in the admin's SELECTED zone (the badge tz) so the hours line up
  // with the date/time picker instead of showing the teacher's raw local numbers.
  const availSummary = availCtx ? window.Calendar.shape.weeklyAvailabilitySummary(availCtx.slots, availCtx.instructorTz, tz, pickedStart) : '';
  // Soft signals — distinguish "outside weekly hours" from "overlaps an existing
  // lesson / blocked time". Either one warns; neither one blocks (Book anyway).
  const durMin = Number(duration);
  const outsideHours = !!(availCtx && pickedStart) && availCtx.slots.length > 0 &&
    !window.Calendar.shape.isWithinWeeklyAvailability(availCtx.slots, pickedStart, durMin, availCtx.instructorTz);
  const conflict = !!(availCtx && pickedStart) &&
    !!window.Calendar.shape.isSlotBlocked(availCtx.exceptions, pickedStart, durMin);
  const outsideAvailability = outsideHours || conflict;

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(10,12,24,0.4)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:9000 }} onClick={onClose}>
      <div style={{ background:'#fff', borderRadius:14, padding:'26px', width:460, boxShadow:'0 20px 60px rgba(0,0,0,0.18)', fontFamily:"'Plus Jakarta Sans', sans-serif", maxHeight:'92vh', overflowY:'auto' }} onClick={e=>e.stopPropagation()}>
        <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:10, marginBottom:6 }}>
          <div style={{ fontWeight:700, fontSize:16, color:'oklch(18% 0.03 265)' }}>Book a lesson with {instructor.name}</div>
          <window.TimezoneBadge compact value={tz} onChange={setTz} />
        </div>
        <div style={{ fontSize:12, color:'oklch(58% 0.03 265)', marginBottom:18 }}>Manually create a confirmed lesson on this teacher's calendar. Both sides get a confirmation email.</div>
        {myStudents.length === 0 ? (
          <>
            <div style={{ fontSize:13, color:'oklch(48% 0.04 265)', lineHeight:1.6, marginBottom:18 }}>
              No students are assigned to this instructor yet. Use <strong>+ Assign Student</strong> first, then come back here to book a lesson.
            </div>
            <button type="button" onClick={onClose} style={{ width:'100%', padding:'11px 0', background:'oklch(22% 0.06 265)', color:'#fff', border:'none', borderRadius:8, fontSize:13, fontWeight:600, cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>OK</button>
          </>
        ) : (
          <form onSubmit={submit}>
            <div style={{ marginBottom:14 }}>
              <label style={lbl}>Student</label>
              <select value={studentId} onChange={e=>setStudentId(e.target.value)} required style={fld}>
                <option value="">— Pick a student —</option>
                {myStudents.map(s => (
                  <option key={s.id} value={s.id}>{s.name}</option>
                ))}
              </select>
            </div>
            <div style={{ display:'grid', gridTemplateColumns:'2fr 1fr', gap:12, marginBottom:14 }}>
              <div>
                <label style={lbl}>Date</label>
                <input type="date" value={date} onChange={e=>setDate(e.target.value)} required style={fld} />
              </div>
              <div>
                <label style={lbl}>Time</label>
                <input type="time" value={time} onChange={e=>setTime(e.target.value)} required style={fld} />
              </div>
            </div>
            <div style={{ marginBottom:14 }}>
              <label style={lbl}>Duration</label>
              <select value={duration} onChange={e=>setDuration(Number(e.target.value))} style={fld}>
                {[30,45,60,90].map(d => (
                  <option key={d} value={d}>{d} min{picked && picked.rates?.student?.[d] != null ? ` · $${picked.rates.student[d]}` : ''}</option>
                ))}
              </select>
            </div>
            <div style={{ marginBottom:14 }}>
              <label style={lbl}>Notes (optional)</label>
              <input value={message} onChange={e=>setMessage(e.target.value)} placeholder="Anything the teacher should know" style={fld} />
            </div>
            <div style={{ display:'flex', alignItems:'center', gap:9, marginBottom:recurring?6:14, padding:'9px 12px', background:'oklch(98% 0.005 265)', borderRadius:8, border:'1px dashed oklch(85% 0.02 265)' }}>
              <input type="checkbox" id="aRec" checked={recurring} onChange={e=>{ const v = e.target.checked; setRecurring(v); if (!v) setInfinite(false); }} style={{ width:14, height:14, accentColor:'oklch(22% 0.06 265)' }} />
              <label htmlFor="aRec" style={{ fontSize:13, color:'oklch(28% 0.05 265)', cursor:'pointer', fontWeight:600 }}>↻ Repeat weekly</label>
            </div>
            {recurring && (
              <>
                <div style={{ display:'flex', alignItems:'center', gap:9, marginBottom:infinite?12:6, paddingLeft:8 }}>
                  <input type="checkbox" id="aRecInf" checked={infinite} onChange={e=>setInfinite(e.target.checked)} style={{ width:14, height:14, accentColor:'oklch(34% 0.13 150)' }} />
                  <label htmlFor="aRecInf" style={{ fontSize:13, color:'oklch(28% 0.05 265)', cursor:'pointer', fontWeight:600 }}>∞ Infinite — keep going forever (most clients renew)</label>
                </div>
                {!infinite && (
                  <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:14, paddingLeft:8, fontSize:13, color:'oklch(40% 0.04 265)' }}>
                    <span>For</span>
                    <input type="number" min={1} max={52} value={weeks} onChange={e=>setWeeks(e.target.value)} style={{ width:60, padding:'5px 8px', borderRadius:6, border:'1.5px solid oklch(86% 0.02 265)', fontSize:13, fontFamily:"'Plus Jakarta Sans', sans-serif", textAlign:'center' }} />
                    <span>weeks (creates {weeks} lessons total)</span>
                  </div>
                )}
                {infinite && (
                  <div style={{ marginBottom:14, padding:'9px 11px', background:'oklch(96% 0.04 150)', border:'1px solid oklch(82% 0.1 150)', borderRadius:7, fontSize:11.5, color:'oklch(34% 0.08 150)', lineHeight:1.5 }}>
                    Creates 104 weekly lessons up-front and tops itself up daily — cancel any time via Series → Cancel from here.
                  </div>
                )}
              </>
            )}
            {studentId && rateForDur == null && (
              <div style={{ background:'oklch(96% 0.05 75)', color:'oklch(38% 0.12 75)', padding:'9px 12px', borderRadius:8, fontSize:12, marginBottom:12 }}>
                Heads-up: no $ rate set for {duration} min on this assignment — the booking will save with no rate snapshot.
              </div>
            )}
            {availSummary && (
              <div style={{ fontSize:11.5, color:'oklch(50% 0.03 265)', marginBottom: outsideAvailability ? 6 : 12, lineHeight:1.5 }}>
                Available: <strong>{availSummary}</strong> <span style={{ color:'oklch(62% 0.02 265)' }}>(in the selected time zone)</span>
              </div>
            )}
            {outsideAvailability && (
              <div style={{ background:'oklch(96.5% 0.06 75)', color:'oklch(42% 0.13 70)', padding:'9px 12px', borderRadius:8, fontSize:12, marginBottom:12, lineHeight:1.5 }}>
                {outsideHours
                  ? `Heads up — that's outside ${instructor.name}'s weekly hours.`
                  : `Heads up — ${instructor.name} already has a lesson or blocked time then.`}
                {' '}You can still book it.
              </div>
            )}
            {error && <div style={{ background:'oklch(95% 0.06 25)', color:'oklch(40% 0.15 25)', padding:'9px 12px', borderRadius:8, fontSize:12, marginBottom:12 }}>{error}</div>}
            <div style={{ display:'flex', gap:10 }}>
              <button type="submit" disabled={busy || !studentId} style={{ flex:1, background: outsideAvailability ? 'oklch(58% 0.14 65)' : 'oklch(34% 0.13 150)', color:'#fff', border:'none', borderRadius:9, padding:'11px 0', fontWeight:600, fontSize:14, cursor: busy ? 'wait' : 'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif", opacity: busy ? 0.7 : 1 }}>
                {busy ? 'Booking…' : outsideAvailability ? 'Book anyway' : 'Book lesson'}
              </button>
              <button type="button" onClick={onClose} style={{ padding:'11px 16px', background:'oklch(95% 0.01 265)', border:'none', borderRadius:9, fontSize:13, cursor:'pointer', color:'oklch(46% 0.04 265)', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>Cancel</button>
            </div>
          </form>
        )}
      </div>
    </div>
  );
};

// ── Confirm Delete Instructor ────────────────────────────────────────────────

// Typed-name confirmation (mirrors ASConfirmDelete in admin-students-modals.jsx).
// Admin must retype the instructor's full name before the Delete button enables.
// The same check is enforced server-side by admin_hard_delete_instructor
// (v78-delete-safety.sql). onConfirm receives the typed name.
const AIConfirmDelete = ({ instructor, onConfirm, onClose }) => {
  const [busy, setBusy] = React.useState(false);
  const [err, setErr]   = React.useState('');
  const [typed, setTyped] = React.useState('');
  const expected = String((instructor && instructor.name) || '').trim();
  const matches  = typed.trim().toLowerCase() === expected.toLowerCase() && expected.length > 0;
  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(10,12,24,0.4)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:9000 }} onClick={onClose}>
      <div style={{ background:'#fff', borderRadius:14, padding:'26px', width:380, maxWidth:'calc(100vw - 32px)', boxShadow:'0 20px 60px rgba(0,0,0,0.18)', fontFamily:"'Plus Jakarta Sans', sans-serif" }} onClick={e=>e.stopPropagation()}>
        <div style={{ fontWeight:700, fontSize:16, color:'oklch(18% 0.03 265)', marginBottom:8 }}>Delete instructor {instructor.name}?</div>
        <div style={{ fontSize:13, color:'oklch(54% 0.03 265)', lineHeight:1.55, marginBottom:14 }}>
          This permanently removes their account, all of their bookings,
          availability, and assignments. The email is freed up so it can be
          used again. The account is moved to <strong>Trash</strong>, where it
          can be restored within a short window.
        </div>
        <div style={{ fontSize:12, color:'oklch(40% 0.04 265)', marginBottom:6, fontWeight:600 }}>
          To confirm, type <span style={{ background:'oklch(96% 0.01 265)', padding:'1px 6px', borderRadius:4, fontWeight:700, color:'oklch(18% 0.03 265)' }}>{expected}</span>
        </div>
        <input
          type="text"
          value={typed}
          onChange={e => setTyped(e.target.value)}
          autoFocus
          placeholder={`Type ${expected} here`}
          aria-label="Type instructor full name to confirm delete"
          data-testid="confirm-delete-typed-name"
          style={{
            width:'100%', boxSizing:'border-box', padding:'10px 12px',
            borderRadius:8, fontSize:13, marginBottom:14,
            border: matches ? '1.5px solid oklch(60% 0.16 145)'
                            : '1.5px solid oklch(88% 0.02 265)',
            outline:'none', fontFamily:"'Plus Jakarta Sans', sans-serif",
          }}
        />
        {err && <div style={{ background:'oklch(95% 0.06 25)', color:'oklch(40% 0.15 25)', padding:'8px 12px', borderRadius:8, fontSize:12, marginBottom:12 }}>{err}</div>}
        <div style={{ display:'flex', gap:10 }}>
          <button
            onClick={async () => {
              if (!matches || busy) return;
              setBusy(true); setErr('');
              try { await onConfirm(typed.trim()); onClose(); }
              catch (e) { setErr(e.message || 'Failed.'); }
              finally { setBusy(false); }
            }}
            disabled={busy || !matches}
            title={!matches ? `Type "${expected}" exactly to enable Delete` : undefined}
            data-testid="confirm-delete-submit"
            style={{
              flex:1,
              background: matches ? 'oklch(40% 0.18 25)' : 'oklch(88% 0.04 25)',
              color:'#fff', border:'none', borderRadius:9, padding:'11px 0',
              fontWeight:700, fontSize:13,
              cursor: matches ? (busy?'wait':'pointer') : 'not-allowed',
              fontFamily:"'Plus Jakarta Sans', sans-serif",
              opacity: busy ? 0.7 : 1,
            }}
          >
            {busy ? 'Deleting…' : 'Yes, delete instructor'}
          </button>
          <button onClick={onClose} style={{ padding:'11px 16px', background:'oklch(95% 0.01 265)', border:'none', borderRadius:9, fontSize:13, cursor:'pointer', color:'oklch(46% 0.04 265)', fontFamily:"'Plus Jakarta Sans', sans-serif" }}>Cancel</button>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, {
  AIBookLessonModal,
  AIConfirmDelete,
  // Legacy alias used by admin-view-as.jsx.
  AdminBookLessonModal: AIBookLessonModal,
});
