// admin-reminders-upcoming.jsx — "Upcoming" tab of the reminder editor.
//
// Forward-looking companion to the Recent-sends tab. Where that one shows
// reminders ALREADY sent, this shows the lesson reminders that WILL be sent
// over the next few days, computed server-side by admin_upcoming_reminders()
// (supabase/v130) — which mirrors send_booking_reminders()'s exact selection.
//
// Read-only. Not realtime (it's a forecast); a horizon selector + Refresh
// button drive reloads. Times render in a viewer-chosen timezone, shared
// with the Recent-sends tab via the same localStorage key.
//
// Props:
//   schedules — global_reminder_schedules, only used for the interval label.

const AdminRemindersUpcoming = ({ schedules }) => {
  const AR_TIME_BEFORE_OPTIONS = window.AR_TIME_BEFORE_OPTIONS;
  const AR_COMMON_TZ           = window.AR_COMMON_TZ;
  const TZ_KEY = 'ar_reminders_tz';

  const HORIZONS = [
    { days: 2,  label: 'Next 2 days' },
    { days: 7,  label: 'Next 7 days' },
    { days: 14, label: 'Next 14 days' },
    { days: 30, label: 'Next 30 days' },
  ];

  const [rows, setRows]     = React.useState(null); // null = loading
  const [days, setDays]     = React.useState(7);
  const [loadErr, setLoadErr] = React.useState('');
  const [tz, setTz] = React.useState(() => {
    try { return window.localStorage.getItem(TZ_KEY) || window.arBrowserTz(); }
    catch (_) { return window.arBrowserTz(); }
  });

  const load = React.useCallback(async (d) => {
    setRows(null); setLoadErr('');
    try {
      const data = await window.ADMIN_DATA.upcomingReminders.get(d);
      setRows(Array.isArray(data) ? data : []);
    } catch (e) {
      setRows([]); setLoadErr(e.message || 'Could not load upcoming reminders');
    }
  }, []);

  React.useEffect(() => { load(days); }, [load, days]);
  React.useEffect(() => { try { window.localStorage.setItem(TZ_KEY, tz); } catch (_) {} }, [tz]);

  // ── Styles (kept in lockstep with admin-reminders-log.jsx) ──────────
  const card  = { background:'#fff', borderRadius:14, border:'1px solid oklch(91% 0.01 265)', padding:'22px 26px', marginBottom:18, boxShadow:'0 2px 10px oklch(18% 0.06 265 / 0.05)' };
  const h2    = { fontFamily:"'Cormorant Garamond', serif", fontSize:20, fontWeight:600, color:'oklch(18% 0.03 265)', marginBottom:0 };
  const td    = { padding:'9px 10px', color:'oklch(22% 0.06 265)', verticalAlign:'top' };
  const tdDim = { ...td, color:'oklch(40% 0.04 265)' };
  const th    = { textAlign:'left', padding:'8px 10px' };
  const tzSelect = { fontSize:12, fontFamily:"'Plus Jakarta Sans', sans-serif", color:'oklch(30% 0.05 265)', background:'#fff', border:'1.5px solid oklch(88% 0.015 265)', borderRadius:8, padding:'6px 8px', maxWidth:230, cursor:'pointer', outline:'none' };
  const refreshBtn = { background:'#fff', color:'oklch(22% 0.06 265)', border:'1.5px solid oklch(80% 0.02 265)', borderRadius:9, padding:'7px 14px', fontWeight:600, fontSize:12.5, cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif", whiteSpace:'nowrap' };
  const horizonPill = (active) => ({ fontSize:12, fontWeight:600, padding:'4px 11px', borderRadius:999, border:'1px solid ' + (active ? 'oklch(22% 0.06 265)' : 'oklch(88% 0.02 265)'), background: active ? 'oklch(22% 0.06 265)' : '#fff', color: active ? '#fff' : 'oklch(40% 0.04 265)', cursor:'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif" });
  const nowPill = { display:'inline-flex', alignItems:'center', gap:5, fontSize:10.5, fontWeight:700, padding:'2px 8px', borderRadius:999, background:'oklch(96% 0.04 150)', color:'oklch(36% 0.13 150)', border:'1px solid oklch(85% 0.05 150)', fontFamily:"'Plus Jakarta Sans', sans-serif", whiteSpace:'nowrap' };
  const warnPill = { display:'inline-flex', alignItems:'center', gap:5, fontSize:10.5, fontWeight:700, padding:'2px 8px', borderRadius:999, background:'oklch(96% 0.05 75)', color:'oklch(45% 0.14 55)', border:'1px solid oklch(86% 0.08 75)', fontFamily:"'Plus Jakarta Sans', sans-serif", whiteSpace:'nowrap' };

  const minLabel = (mb) => (AR_TIME_BEFORE_OPTIONS.find(o => o.value === mb)?.label || (mb + ' min before'));

  // A recipient with no real inbox can't actually be emailed. Off-platform
  // "guest" students (a teacher adds them manually; they never sign up) carry
  // a synthetic guest.<id>@guests.coachingforall.co placeholder — that domain
  // has no MX, so the reminder is attempted but bounces. Empty counts too
  // (defensive; the RPC already filters empties). The teacher on the same
  // booking has a real email and is still reminded.
  const isUndeliverable = (email) => !email || /@guests\.coachingforall\.co$/i.test(email);

  const fmtCell = (iso, dim) => {
    const f = window.arFormatInZone(iso, tz);
    if (!f) return <span style={{ color:'oklch(60% 0.03 265)' }}>—</span>;
    return (
      <div style={{ lineHeight:1.35, whiteSpace:'nowrap' }}>
        <div style={{ fontWeight:600, color: dim ? 'oklch(34% 0.04 265)' : 'oklch(22% 0.06 265)' }}>{f.date}</div>
        <div style={{ fontSize:12, color:'oklch(52% 0.03 265)' }}>{f.time}{f.zone ? ' · ' + f.zone : ''}</div>
      </div>
    );
  };

  const renderTimezonePicker = () => {
    const browserTz = window.arBrowserTz();
    const all = window.arAllTimezones();
    return (
      <select value={tz} onChange={e => setTz(e.target.value)} style={tzSelect} title="Show all times in this timezone">
        <optgroup label="Your timezone"><option value={browserTz}>{browserTz}</option></optgroup>
        <optgroup label="Common">
          {AR_COMMON_TZ.map(t => <option key={t.value} value={t.value}>{t.label}</option>)}
        </optgroup>
        <optgroup label="All timezones">
          {all.map(z => <option key={z} value={z}>{z}</option>)}
        </optgroup>
      </select>
    );
  };

  const list          = rows || [];
  const total         = list.length;
  const undeliverable = list.filter(r => isUndeliverable(r.recipient_email)).length;
  const deliverable   = total - undeliverable;
  // "Sending now" counts only deliverable in-window rows, so the count matches
  // the green badges (undeliverable rows suppress the badge).
  const nowCount      = list.filter(r => r.in_window && !isUndeliverable(r.recipient_email)).length;

  return (
    <div style={card}>
      <div style={{ display:'flex', alignItems:'center', gap:10, flexWrap:'wrap', marginBottom:14 }}>
        <div style={h2}>Upcoming</div>
        <div style={{ flex:1 }} />
        {renderTimezonePicker()}
        <button type="button" onClick={() => load(days)} style={refreshBtn}>Refresh</button>
      </div>

      <div style={{ fontSize:12, color:'oklch(56% 0.03 265)', marginBottom:14, lineHeight:1.5 }}>
        Lesson reminders scheduled to send automatically. Each booking gets a reminder at every enabled
        interval (e.g. 24 hours and 15 minutes before). A class booked closer than an interval simply
        won't show that interval — there's no time left to send it. Rows flagged <em>No email</em> go to
        off-platform guest students with no real inbox, so those won't be delivered (the teacher is still
        reminded). Times in <strong>{tz}</strong>.
      </div>

      <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap', marginBottom:16 }}>
        {HORIZONS.map(h => (
          <button key={h.days} type="button" onClick={() => setDays(h.days)} style={horizonPill(h.days === days)}>{h.label}</button>
        ))}
      </div>

      {loadErr && (
        <div style={{ fontSize:13, color:'oklch(40% 0.15 25)', marginBottom:12, padding:'10px 14px', background:'oklch(96% 0.06 25)', borderRadius:8 }}>{loadErr}</div>
      )}

      {rows === null ? (
        <div style={{ fontSize:13, color:'oklch(60% 0.03 265)' }}>Loading…</div>
      ) : total === 0 ? (
        <div style={{ fontSize:13, color:'oklch(60% 0.03 265)', fontStyle:'italic' }}>
          No reminders are scheduled to send in this window. New bookings appear here as soon as they're made.
        </div>
      ) : (
        <React.Fragment>
          <div style={{ fontSize:12.5, color:'oklch(48% 0.03 265)', marginBottom:12 }}>
            <strong style={{ color:'oklch(22% 0.06 265)' }}>{deliverable}</strong> will be delivered
            {undeliverable > 0 && <span> · <strong style={{ color:'oklch(45% 0.14 55)' }}>{undeliverable}</strong> won't (guest student, no email)</span>}
            {nowCount > 0 && <span> · <strong style={{ color:'oklch(36% 0.13 150)' }}>{nowCount}</strong> sending now</span>}
          </div>
          <div style={{ overflowX:'auto' }}>
            <table style={{ width:'100%', borderCollapse:'collapse', fontSize:13, fontFamily:"'Plus Jakarta Sans', sans-serif" }}>
              <thead><tr style={{ borderBottom:'1.5px solid oklch(90% 0.01 265)', color:'oklch(56% 0.03 265)', fontWeight:700 }}>
                <th style={th}>Sends at</th><th style={th}>To</th><th style={th}>Student</th>
                <th style={th}>Teacher</th><th style={th}>Lesson time</th>
                <th style={{ ...th, textAlign:'right' }}>Interval</th>
              </tr></thead>
              <tbody>
                {list.map((d, i) => {
                  const undeliv = isUndeliverable(d.recipient_email);
                  return (
                  <tr key={d.booking_id + ':' + d.recipient + ':' + d.minutes_before + ':' + i}
                      style={{ borderBottom:'1px solid oklch(94% 0.005 60)', background: undeliv ? 'oklch(98% 0.03 75)' : (d.in_window ? 'oklch(98.5% 0.02 150)' : 'transparent') }}>
                    <td style={td}>
                      {fmtCell(d.fire_at, false)}
                      {d.in_window && !undeliv && <div style={{ marginTop:4 }}><span style={nowPill}><span style={{ width:5, height:5, borderRadius:999, background:'oklch(60% 0.18 150)' }} />Sending now</span></div>}
                    </td>
                    <td style={td}>
                      <div style={{ textTransform:'capitalize', fontWeight:600 }}>{d.recipient || '—'}</div>
                      {d.recipient_email && (
                        <div style={{ fontSize:11.5, marginTop:2, wordBreak:'break-all', maxWidth:210, color: undeliv ? 'oklch(52% 0.05 55)' : 'oklch(52% 0.03 265)' }}>{d.recipient_email}</div>
                      )}
                      {undeliv && <div style={{ marginTop:4 }}><span style={warnPill}>No email · won't deliver</span></div>}
                    </td>
                    <td style={td}>{d.student_name || '—'}</td>
                    <td style={td}>{d.instructor_name || '—'}</td>
                    <td style={tdDim}>{fmtCell(d.scheduled_at, true)}</td>
                    <td style={{ ...tdDim, textAlign:'right', whiteSpace:'nowrap' }}>{d.minutes_before != null ? minLabel(d.minutes_before) : '—'}</td>
                  </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </React.Fragment>
      )}
    </div>
  );
};

window.AdminRemindersUpcoming = AdminRemindersUpcoming;
