// instructor-calendar-sync.jsx -- Settings card for Google Calendar sync.
//
// Shows the instructor's connection state and lets them connect / disconnect.
// Mounted inside instructor-dashboard.jsx above the schedule view.
//
// States:
//   - loading: spinner while we read public.gcal_my_connection()
//   - disconnected: "Connect Google Calendar" button -> initiates OAuth
//   - connected: shows google_email + last sync + Disconnect button.
//                Surfaces last_push_error with a reconnect prompt if set.
//
// Exports: window.InstructorCalendarSync.Card

(function () {
  'use strict';
  if (window.InstructorCalendarSync) return;

  const ICS_CARD_STYLE = {
    background: '#fff',
    border: '1px solid oklch(90% 0.01 265)',
    borderRadius: 12,
    padding: '18px 20px',
    marginBottom: 16,
    fontFamily: "'Plus Jakarta Sans', sans-serif",
    color: 'oklch(22% 0.06 265)',
  };
  const ICS_TITLE_STYLE = {
    fontSize: 14,
    fontWeight: 700,
    margin: '0 0 6px',
    letterSpacing: '0.01em',
  };
  const ICS_SUB_STYLE = {
    fontSize: 13,
    color: 'oklch(48% 0.03 265)',
    margin: '0 0 12px',
    lineHeight: 1.5,
  };
  const ICS_BTN_PRIMARY = {
    background: 'oklch(22% 0.06 265)',
    color: '#fff',
    border: 'none',
    borderRadius: 8,
    padding: '10px 18px',
    fontSize: 14,
    fontWeight: 600,
    cursor: 'pointer',
    fontFamily: "'Plus Jakarta Sans', sans-serif",
    minHeight: 40,
  };
  const ICS_BTN_SECONDARY = {
    background: '#fff',
    color: 'oklch(36% 0.04 265)',
    border: '1px solid oklch(85% 0.02 265)',
    borderRadius: 8,
    padding: '8px 14px',
    fontSize: 13,
    fontWeight: 600,
    cursor: 'pointer',
    fontFamily: "'Plus Jakarta Sans', sans-serif",
    minHeight: 36,
  };
  const ICS_ERROR_BOX = {
    background: 'oklch(96% 0.05 25)',
    border: '1px solid oklch(85% 0.07 25)',
    borderRadius: 8,
    padding: '10px 12px',
    fontSize: 12,
    color: 'oklch(36% 0.13 25)',
    marginBottom: 12,
    lineHeight: 1.5,
  };
  const ICS_OK_BOX = {
    background: 'oklch(96% 0.04 155)',
    border: '1px solid oklch(85% 0.07 155)',
    borderRadius: 8,
    padding: '10px 12px',
    fontSize: 12,
    color: 'oklch(34% 0.13 150)',
    marginBottom: 12,
    lineHeight: 1.5,
  };

  const fmtSince = (iso) => {
    if (!iso) return null;
    const t = new Date(iso).getTime();
    if (Number.isNaN(t)) return null;
    const diff = Date.now() - t;
    const mins = Math.floor(diff / 60000);
    if (mins < 1) return 'just now';
    if (mins < 60) return mins + ' min ago';
    const hrs = Math.floor(mins / 60);
    if (hrs < 24) return hrs + ' hr ago';
    const days = Math.floor(hrs / 24);
    return days + ' day' + (days === 1 ? '' : 's') + ' ago';
  };

  const getAccessToken = async () => {
    if (window.supa && window.supa.auth && window.supa.auth.getSession) {
      const r = await window.supa.auth.getSession();
      return r && r.data && r.data.session && r.data.session.access_token;
    }
    return null;
  };

  const Card = () => {
    const [conn, setConn] = React.useState(undefined); // undefined=loading, null=disconnected, object=connected
    const [busy, setBusy] = React.useState(false);
    const [flash, setFlash] = React.useState(null);

    const load = React.useCallback(async () => {
      try {
        const { data, error } = await window.supa.rpc('gcal_my_connection');
        if (error) { setConn(null); return; }
        const row = Array.isArray(data) ? data[0] : data;
        setConn(row || null);
      } catch (_) {
        setConn(null);
      }
    }, []);

    React.useEffect(() => {
      load();
      // Pick up the OAuth callback flash from the URL.
      const params = new URLSearchParams(window.location.search || '');
      const flag = params.get('gcal');
      if (flag === 'connected') {
        setFlash({ kind: 'ok', text: 'Google Calendar connected. Your existing events are importing now, and changes sync within a minute.' });
      } else if (flag === 'error') {
        const reason = params.get('reason') || 'unknown';
        const text = reason === 'calendar_permission_required'
          ? 'Almost there — calendar access wasn’t granted. Reconnect and make sure the calendar permission ("See, edit, share… your Google Calendar") is checked on Google’s screen.'
          : 'Connection failed (' + reason + '). Please try again.';
        setFlash({ kind: 'err', text });
      }
      if (flag) {
        // Strip the query params so a refresh doesn't replay the flash.
        const url = new URL(window.location.href);
        url.searchParams.delete('gcal');
        url.searchParams.delete('reason');
        window.history.replaceState({}, '', url.toString());
      }
    }, [load]);

    const onConnect = async () => {
      setBusy(true);
      setFlash(null);
      try {
        const token = await getAccessToken();
        if (!token) {
          setFlash({ kind: 'err', text: 'Please refresh the page and sign in again.' });
          return;
        }
        const r = await fetch('/api/google-calendar/start', {
          method: 'POST',
          headers: { Authorization: 'Bearer ' + token, 'Content-Type': 'application/json' },
        });
        const body = await r.json().catch(() => ({}));
        if (!r.ok || !body.redirect) {
          setFlash({ kind: 'err', text: body.error || 'Could not start the connection. Please try again.' });
          return;
        }
        window.location.assign(body.redirect);
      } catch (err) {
        setFlash({ kind: 'err', text: err.message || 'Connection failed.' });
      } finally {
        setBusy(false);
      }
    };

    const onDisconnect = async () => {
      if (!window.confirm('Disconnect Google Calendar? Existing events stay; new lessons will stop syncing.')) return;
      setBusy(true);
      setFlash(null);
      try {
        const token = await getAccessToken();
        if (!token) {
          setFlash({ kind: 'err', text: 'Please refresh the page and sign in again.' });
          return;
        }
        const r = await fetch('/api/google-calendar/disconnect', {
          method: 'POST',
          headers: { Authorization: 'Bearer ' + token, 'Content-Type': 'application/json' },
        });
        const body = await r.json().catch(() => ({}));
        if (!r.ok) {
          setFlash({ kind: 'err', text: body.error || 'Could not disconnect.' });
          return;
        }
        setConn(null);
        setFlash({ kind: 'ok', text: 'Google Calendar disconnected.' });
      } catch (err) {
        setFlash({ kind: 'err', text: err.message || 'Disconnect failed.' });
      } finally {
        setBusy(false);
      }
    };

    if (conn === undefined) {
      return (
        <div style={ICS_CARD_STYLE}>
          <div style={ICS_TITLE_STYLE}>Google Calendar</div>
          <div style={ICS_SUB_STYLE}>Loading...</div>
        </div>
      );
    }

    if (!conn) {
      return (
        <div style={ICS_CARD_STYLE}>
          <div style={ICS_TITLE_STYLE}>Google Calendar</div>
          <div style={ICS_SUB_STYLE}>Sync new lessons to your Google Calendar automatically. Mastery is the source of truth -- changes here update Google.</div>
          {flash && flash.kind === 'err' ? <div style={ICS_ERROR_BOX}>{flash.text}</div> : null}
          {flash && flash.kind === 'ok'  ? <div style={ICS_OK_BOX}>{flash.text}</div>    : null}
          <div style={{ fontSize: 12.5, lineHeight: 1.5, color: 'oklch(45% 0.03 265)', background: 'oklch(96% 0.02 235)', border: '1px solid oklch(90% 0.03 235)', borderRadius: 8, padding: '9px 11px', margin: '0 0 12px' }}>
            Google will show an “app isn’t verified” screen — that’s expected. Click <strong>Advanced → Continue</strong>, then <strong>tick the calendar box</strong> so your events can sync.
          </div>
          <button onClick={onConnect} disabled={busy} style={{ ...ICS_BTN_PRIMARY, opacity: busy ? 0.7 : 1 }}>
            {busy ? 'Opening Google...' : 'Connect Google Calendar'}
          </button>
        </div>
      );
    }

    // A connection whose granted scope has no calendar access can't sync (every
    // Google read/write 403s). This catches connections saved before the connect
    // flow started rejecting no-calendar grants. Show it as broken, not "Connected".
    const calendarMissing = !!(conn.scope && !conn.scope.includes('auth/calendar'));
    if (calendarMissing) {
      return (
        <div style={ICS_CARD_STYLE}>
          <div style={ICS_TITLE_STYLE}>Google Calendar</div>
          <div style={ICS_SUB_STYLE}>
            Connected as <strong>{conn.google_email || 'your Google account'}</strong>, but calendar access wasn’t granted — your events can’t sync yet.
          </div>
          <div style={ICS_ERROR_BOX}>
            Reconnect and make sure the calendar permission ("See, edit, share… your Google Calendar") is checked on Google’s screen.
          </div>
          {flash && flash.kind === 'err' ? <div style={ICS_ERROR_BOX}>{flash.text}</div> : null}
          {flash && flash.kind === 'ok'  ? <div style={ICS_OK_BOX}>{flash.text}</div>    : null}
          <button onClick={onConnect} disabled={busy} style={{ ...ICS_BTN_PRIMARY, opacity: busy ? 0.7 : 1 }}>
            {busy ? 'Opening Google...' : 'Reconnect Google Calendar'}
          </button>
        </div>
      );
    }

    const since = fmtSince(conn.last_push_at);
    return (
      <div style={ICS_CARD_STYLE}>
        <div style={ICS_TITLE_STYLE}>Google Calendar</div>
        <div style={ICS_SUB_STYLE}>
          Connected as <strong>{conn.google_email || 'your Google account'}</strong>
          {since ? <span> -- last synced {since}</span> : <span> -- waiting for the first lesson to sync</span>}
        </div>
        {conn.last_push_error ? (
          <div style={ICS_ERROR_BOX}>
            Last sync failed: {conn.last_push_error}. Disconnect and reconnect to re-authorise Google.
          </div>
        ) : null}
        {flash && flash.kind === 'err' ? <div style={ICS_ERROR_BOX}>{flash.text}</div> : null}
        {flash && flash.kind === 'ok'  ? <div style={ICS_OK_BOX}>{flash.text}</div>    : null}
        <button onClick={onDisconnect} disabled={busy} style={{ ...ICS_BTN_SECONDARY, opacity: busy ? 0.7 : 1 }}>
          {busy ? 'Disconnecting...' : 'Disconnect'}
        </button>
      </div>
    );
  };

  window.InstructorCalendarSync = { Card };
})();
