// admin-reminders-log.jsx — "Recent sends" tab of the reminder editor.
//
// Self-contained: owns the booking_reminders page it shows, the live
// realtime subscription, the timezone the timestamps render in, and the
// "Send test reminder" action. Mounted by admin-reminders.jsx only while
// the Recent-sends tab is active. Pure helpers (date formatting, timezone
// lists, page sizes) live in admin-reminders-helpers.js.
//
// Props:
//   schedules — the global_reminder_schedules list, used to resolve each
//               row's recipient + interval via window.arResolveSendRow.

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

  const [rowsRaw, setRowsRaw]   = React.useState(null); // null = loading
  const [total, setTotal]       = React.useState(0);
  const [page, setPage]         = React.useState(0);
  const [pageSize, setPageSize] = React.useState(AR_PAGE_SIZES[0]);
  const [lookups, setLookups]   = React.useState(null);
  const [liveOn, setLiveOn]     = React.useState(false);
  const [tz, setTz]             = React.useState(() => {
    try { return window.localStorage.getItem(TZ_KEY) || window.arBrowserTz(); }
    catch (_) { return window.arBrowserTz(); }
  });
  const [testBusy, setTestBusy]     = React.useState(false);
  const [testResult, setTestResult] = React.useState('');
  const [loadErr, setLoadErr]       = React.useState('');

  // Refs so the realtime handler reads current paging without re-subscribing.
  const pageRef = React.useRef(0);
  const sizeRef = React.useRef(pageSize);
  React.useEffect(() => { pageRef.current = page; }, [page]);
  React.useEffect(() => { sizeRef.current = pageSize; }, [pageSize]);

  const loadSends = React.useCallback(async (pg, size) => {
    setRowsRaw(null);
    setLoadErr('');
    const from = pg * size;
    const to   = from + size - 1;
    const res = await window.supa.from('booking_reminders')
      .select('sent_at, rule_id, booking_id', { count: 'exact' })
      .order('sent_at', { ascending: false })
      .range(from, to);
    if (res.error) { setRowsRaw([]); setTotal(0); setLoadErr(res.error.message); return; }
    setRowsRaw(res.data || []);
    setTotal(res.count == null ? (res.data || []).length : res.count);
  }, []);

  // Load lookups (names) once, then the first page.
  React.useEffect(() => {
    let alive = true;
    (async () => {
      const lk = await window.arLoadReminderLogLookups();
      if (alive) setLookups(lk);
    })();
    return () => { alive = false; };
  }, []);

  React.useEffect(() => { loadSends(page, pageSize); }, [loadSends, page, pageSize]);

  // Persist the chosen timezone so it sticks across visits.
  React.useEffect(() => {
    try { window.localStorage.setItem(TZ_KEY, tz); } catch (_) {}
  }, [tz]);

  // Realtime: new reminders land live. On page 1 we refetch so order + count
  // stay exact; deeper pages just bump the total so "of N" keeps up.
  React.useEffect(() => {
    const ch = window.supa.channel('admin-reminders-log')
      .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'booking_reminders' }, () => {
        if (pageRef.current === 0) loadSends(0, sizeRef.current);
        else setTotal(t => t + 1);
      })
      .subscribe((status) => { if (status === 'SUBSCRIBED') setLiveOn(true); });
    return () => { setLiveOn(false); window.supa.removeChannel(ch); };
  }, [loadSends]);

  const sendTestReminder = async () => {
    setTestBusy(true); setTestResult('');
    try {
      const count = await window.ADMIN_DATA.fireRemindersNow();
      const n = Number(count) || 0;
      setTestResult(n === 0
        ? 'Cron ran. No bookings in the send window — 0 reminders fired. (Reminders only send for bookings whose target time is within the last 30 min.)'
        : 'Cron ran. ' + n + ' reminder' + (n === 1 ? '' : 's') + ' sent.');
    } catch (e) {
      setTestResult(e.message || 'Test reminder failed');
    } finally {
      setTestBusy(false);
      setTimeout(() => setTestResult(''), 12000);
    }
  };

  const changePageSize = (size) => { setPageSize(size); setPage(0); };

  // ── Styles ────────────────────────────────────────────────────────
  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 pillStyle = { display:'inline-flex', alignItems:'center', gap:6, fontSize:11, fontWeight:600, padding:'3px 9px', borderRadius:999, background: liveOn ? 'oklch(96% 0.04 150)' : 'oklch(95% 0.005 265)', color: liveOn ? 'oklch(36% 0.13 150)' : 'oklch(50% 0.03 265)', border:'1px solid ' + (liveOn ? 'oklch(85% 0.05 150)' : 'oklch(90% 0.01 265)'), fontFamily:"'Plus Jakarta Sans', sans-serif" };
  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 testBtn  = { 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:testBusy?'wait':'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif", opacity:testBusy?0.7:1, whiteSpace:'nowrap' };
  const navBtn = (disabled) => ({ background:'#fff', color: disabled ? 'oklch(72% 0.02 265)' : 'oklch(22% 0.06 265)', border:'1.5px solid oklch(86% 0.02 265)', borderRadius:8, padding:'6px 12px', fontSize:12.5, fontWeight:600, cursor: disabled ? 'default' : 'pointer', fontFamily:"'Plus Jakarta Sans', sans-serif", opacity: disabled ? 0.6 : 1 });
  const sizePill = (active) => ({ fontSize:12, fontWeight:600, padding:'4px 10px', 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 minLabel = (mb) => (AR_TIME_BEFORE_OPTIONS.find(o => o.value === mb)?.label || (mb + ' min before'));

  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 rows = (rowsRaw || []).map(r => window.arResolveSendRow(r, schedules, lookups));
  const from1 = total === 0 ? 0 : page * pageSize + 1;
  const to1   = Math.min((page + 1) * pageSize, total);
  const hasPrev = page > 0;
  const hasNext = (page + 1) * pageSize < total;

  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>
    );
  };

  return (
    <div style={card}>
      <div style={{ display:'flex', alignItems:'center', gap:10, flexWrap:'wrap', marginBottom:14 }}>
        <div style={h2}>Recent sends</div>
        <span style={pillStyle}>
          <span style={{ width:6, height:6, borderRadius:999, background: liveOn ? 'oklch(60% 0.18 150)' : 'oklch(70% 0.02 265)' }} />
          {liveOn ? 'Live' : 'Connecting…'}
        </span>
        <div style={{ flex:1 }} />
        {renderTimezonePicker()}
        <button type="button" onClick={sendTestReminder} disabled={testBusy}
          title="Fires send_booking_reminders() once. Sends a real email for any booking whose reminder target time is in the last 30 minutes."
          style={testBtn}>
          {testBusy ? 'Sending…' : 'Send test reminder'}
        </button>
      </div>

      <div style={{ fontSize:12, color:'oklch(56% 0.03 265)', marginBottom:14, lineHeight:1.5 }}>
        New reminders appear here live as send_booking_reminders() fires. Times shown in <strong>{tz}</strong>.
      </div>

      {testResult && (
        <div style={{ fontSize:13, color:'oklch(28% 0.13 150)', marginBottom:12, padding:'10px 14px', background:'oklch(96% 0.04 150)', borderRadius:8, lineHeight:1.5 }}>{testResult}</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>
      )}

      {rowsRaw === null ? (
        <div style={{ fontSize:13, color:'oklch(60% 0.03 265)' }}>Loading…</div>
      ) : rows.length === 0 ? (
        <div style={{ fontSize:13, color:'oklch(60% 0.03 265)', fontStyle:'italic' }}>No reminders have been sent yet. After the next booking with a target time within the last 30 minutes, sends will appear here.</div>
      ) : (
        <React.Fragment>
          <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}>Sent 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>
                {rows.map((d, i) => (
                  <tr key={i + ':' + d.sentAt} style={{ borderBottom:'1px solid oklch(94% 0.005 60)' }}>
                    <td style={td}>{fmtCell(d.sentAt, false)}</td>
                    <td style={{ ...td, textTransform:'capitalize' }}>{d.recipient || '—'}</td>
                    <td style={td}>{d.student}</td>
                    <td style={td}>{d.teacher}</td>
                    <td style={tdDim}>{fmtCell(d.lessonAt, true)}</td>
                    <td style={{ ...tdDim, textAlign:'right', whiteSpace:'nowrap' }}>{d.minutesBefore != null ? minLabel(d.minutesBefore) : '—'}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>

          <div style={{ display:'flex', alignItems:'center', gap:12, flexWrap:'wrap', marginTop:16, paddingTop:14, borderTop:'1px solid oklch(94% 0.005 60)' }}>
            <div style={{ fontSize:12, color:'oklch(50% 0.03 265)' }}>
              Showing <strong>{from1}–{to1}</strong> of <strong>{total}</strong>
            </div>
            <div style={{ display:'flex', alignItems:'center', gap:6 }}>
              <span style={{ fontSize:11, color:'oklch(56% 0.03 265)', marginRight:2 }}>Rows:</span>
              {AR_PAGE_SIZES.map(s => (
                <button key={s} type="button" onClick={() => changePageSize(s)} style={sizePill(s === pageSize)}>{s}</button>
              ))}
            </div>
            <div style={{ flex:1 }} />
            <div style={{ display:'flex', alignItems:'center', gap:8 }}>
              <button type="button" disabled={!hasPrev} onClick={() => hasPrev && setPage(p => p - 1)} style={navBtn(!hasPrev)}>← Prev</button>
              <button type="button" disabled={!hasNext} onClick={() => hasNext && setPage(p => p + 1)} style={navBtn(!hasNext)}>Next →</button>
            </div>
          </div>
        </React.Fragment>
      )}
    </div>
  );
};

window.AdminRemindersLog = AdminRemindersLog;
