/* ============================================================
   MUIY — Auth gate + Root boundary  (src/auth.jsx)
   ------------------------------------------------------------
   RootApp decides what to mount:
     · Supabase NOT configured      → <App/> directly (local-only mode,
                                       identical to the pre-cloud build).
     · Configured, no session       → <AuthGate/> (phone / email OTP).
     · Configured, signed in         → pull+merge the cloud doc, activate
                                       sync, then mount <App/>.
   Passwordless only: 6-digit SMS code or 6-digit email code.
   ============================================================ */

// Fit the 390×844 phone frame into the viewport (mirrors App's scaler).
function useFitScale() {
  const [scale, setScale] = React.useState(1);
  React.useEffect(() => {
    const fit = () => {
      const W = 390, H = 844, pad = 24;
      const s = Math.min((window.innerWidth - pad) / W, (window.innerHeight - pad) / H, 1.15);
      setScale(s > 0 ? s : 1);
    };
    fit();
    window.addEventListener('resize', fit);
    return () => window.removeEventListener('resize', fit);
  }, []);
  return scale;
}

function TCHeart({ size = 40, color = '#fff' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" aria-hidden="true">
      <path fill={color} d="M12 21c-5.5-3.9-9-7.2-9-11.3C3 6.6 5.2 4.5 8 4.5c1.7 0 3.2.8 4 2.1.8-1.3 2.3-2.1 4-2.1 2.8 0 5 2.1 5 5.2C21 13.8 17.5 17.1 12 21z" />
    </svg>
  );
}

// Official four-colour Google "G" for the OAuth button.
function GoogleG({ size = 20 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 48 48" aria-hidden="true">
      <path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z" />
      <path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z" />
      <path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z" />
      <path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z" />
    </svg>
  );
}

const tcAuthStyles = {
  wrap: { position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', background: 'var(--bg)', color: 'var(--ink)', fontFamily: 'Manrope, system-ui, sans-serif' },
  scroll: { flex: 1, overflowY: 'auto', padding: '0 26px', display: 'flex', flexDirection: 'column' },
  hero: { paddingTop: 96, paddingBottom: 18, display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' },
  badge: { width: 76, height: 76, borderRadius: 24, background: 'linear-gradient(150deg, var(--orange-2), var(--orange))', display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: '0 16px 30px -12px rgba(252,107,5,.6)' },
  title: { fontFamily: 'Nunito, sans-serif', fontWeight: 800, fontSize: 27, margin: '20px 0 6px', letterSpacing: '-0.02em' },
  sub: { color: 'var(--ink-2)', fontSize: 15, lineHeight: 1.5, maxWidth: 300 },
  label: { fontSize: 13, fontWeight: 700, color: 'var(--ink-2)', margin: '0 0 8px 2px' },
  input: { width: '100%', boxSizing: 'border-box', height: 56, borderRadius: 16, border: '1.5px solid var(--hairline-2, #E6DECE)', background: 'var(--surface)', color: 'var(--ink)', fontSize: 17, fontWeight: 600, padding: '0 16px', outline: 'none', fontFamily: 'inherit' },
  codeInput: { width: '100%', boxSizing: 'border-box', height: 64, borderRadius: 16, border: '1.5px solid var(--hairline-2, #E6DECE)', background: 'var(--surface)', color: 'var(--ink)', fontSize: 30, fontWeight: 800, letterSpacing: '0.5em', textAlign: 'center', outline: 'none', fontFamily: 'Nunito, sans-serif', paddingLeft: '0.5em' },
  primary: { width: '100%', height: 56, borderRadius: 16, border: 'none', background: 'var(--orange)', color: '#fff', fontSize: 17, fontWeight: 800, cursor: 'pointer', fontFamily: 'Nunito, sans-serif', boxShadow: '0 12px 26px -12px rgba(252,107,5,.7)' },
  google: { width: '100%', height: 56, borderRadius: 16, border: '1.5px solid var(--hairline-2, #E6DECE)', background: 'var(--surface)', color: 'var(--ink)', fontSize: 16.5, fontWeight: 700, cursor: 'pointer', fontFamily: 'inherit', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12, boxShadow: '0 2px 8px -4px rgba(0,0,0,.15)' },
  divider: { display: 'flex', alignItems: 'center', gap: 12, color: 'var(--ink-3)', fontSize: 12, fontWeight: 800, letterSpacing: '0.08em', textTransform: 'uppercase', margin: '2px 0' },
  dividerLine: { flex: 1, height: 1, background: 'var(--hairline-2, #E6DECE)' },
  ghost: { width: '100%', height: 52, borderRadius: 16, border: '1.5px solid var(--hairline-2, #E6DECE)', background: 'transparent', color: 'var(--ink)', fontSize: 16, fontWeight: 700, cursor: 'pointer', fontFamily: 'inherit', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10 },
  linkBtn: { background: 'none', border: 'none', color: 'var(--orange)', fontWeight: 700, fontSize: 15, cursor: 'pointer', padding: 6, fontFamily: 'inherit' },
  err: { background: 'var(--orange-wash, #FFEFE2)', color: '#B11A22', fontSize: 13.5, fontWeight: 600, borderRadius: 12, padding: '11px 14px', lineHeight: 1.45 },
  foot: { padding: '14px 26px 26px', textAlign: 'center', color: 'var(--ink-3)', fontSize: 12, lineHeight: 1.5 },
};

function AuthGate({ onAuthed }) {
  const scale = useFitScale();
  // step: 'choose' | 'email' | 'code'
  const [step, setStep] = React.useState('choose');
  const [method, setMethod] = React.useState('email');   // email only (SMS removed)
  const [phone, setPhone] = React.useState('+960');
  const [email, setEmail] = React.useState('');
  const [code, setCode] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [googleBusy, setGoogleBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const [resentAt, setResentAt] = React.useState(0);

  const identity = method === 'phone' ? phone.trim() : email.trim();

  const startGoogle = React.useCallback(async () => {
    setErr(null); setGoogleBusy(true);
    const r = await window.TCsb.signInWithGoogle();
    // On success the page is already redirecting to Google; only reach here on error.
    if (!r || !r.ok) { setGoogleBusy(false); setErr(friendly(r && r.error) || 'Couldn’t start Google sign-in. Please try again.'); }
  }, []);

  const send = React.useCallback(async (kind, value) => {
    setErr(null); setBusy(true);
    const v = (value || '').trim();
    if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v)) { setBusy(false); setErr('That doesn’t look like a valid email address.'); return; }
    const r = await window.TCsb.sendEmailOtp(v);
    setBusy(false);
    if (!r.ok) { setErr(friendly(r.error)); return; }
    setMethod('email'); setCode(''); setStep('code'); setResentAt(Date.now());
  }, []);

  const verify = React.useCallback(async () => {
    setErr(null);
    const t = code.replace(/\D/g, '');
    if (t.length < 6) { setErr('Enter the 6-digit code we sent you.'); return; }
    setBusy(true);
    const r = await window.TCsb.verifyEmailOtp(email.trim(), t);
    setBusy(false);
    if (!r.ok) { setErr(friendly(r.error) || 'That code didn’t work. Check it and try again.'); return; }
    onAuthed && onAuthed(r.session);
  }, [code, email, onAuthed]);

  const resend = React.useCallback(async () => {
    if (Date.now() - resentAt < 20000) return;          // throttle
    await send(method, identity);
  }, [resentAt, method, identity, send]);

  function friendly(msg) {
    if (!msg) return null;
    const m = String(msg).toLowerCase();
    if (m.indexOf('rate') >= 0 || m.indexOf('limit') >= 0) return 'Too many attempts just now — please wait a minute and try again.';
    if (m.indexOf('expired') >= 0) return 'That code has expired. Tap “Resend code”.';
    if (m.indexOf('network') >= 0 || m.indexOf('fetch') >= 0) return 'Can’t reach the server. Check your connection and try again.';
    return msg;
  }

  return (
    <div className="desk">
      <div className="device-scale" style={{ transform: `scale(${scale})` }}>
        <div className="phone"><div className="screen" data-theme="light">
          <div className="notch" />
          <div style={tcAuthStyles.wrap}>
            <div style={tcAuthStyles.scroll}>
              <div style={tcAuthStyles.hero}>
                <div style={tcAuthStyles.badge}><TCHeart size={40} /></div>
                <h1 style={tcAuthStyles.title}>
                  {step === 'code' ? 'Enter your code' : 'Welcome to MUIY'}
                </h1>
                <p style={tcAuthStyles.sub}>
                  {step === 'choose' && 'Your private companion for transfusions, iron and your donor pool. Sign in to sync securely across your devices.'}
                  {step === 'email' && 'We’ll email you a 6-digit code to confirm it’s you.'}
                  {step === 'code' && `We sent a code to ${email}.`}
                </p>
              </div>

              <div style={{ display: 'flex', flexDirection: 'column', gap: 14, paddingTop: 8 }}>
                {err && <div style={tcAuthStyles.err} role="alert">{err}</div>}

                {step === 'choose' && (
                  <React.Fragment>
                    <button style={{ ...tcAuthStyles.google, opacity: googleBusy ? 0.6 : 1 }} disabled={googleBusy}
                      onClick={startGoogle}>
                      <GoogleG size={20} /> {googleBusy ? 'Opening Google…' : 'Continue with Google'}
                    </button>
                    <div style={tcAuthStyles.divider}><span style={tcAuthStyles.dividerLine} />or<span style={tcAuthStyles.dividerLine} /></div>
                    <button style={tcAuthStyles.primary} onClick={() => { setStep('email'); setErr(null); }}>
                      Continue with email
                    </button>
                  </React.Fragment>
                )}

                {step === 'email' && (
                  <React.Fragment>
                    <div>
                      <div style={tcAuthStyles.label}>Email address</div>
                      <input style={tcAuthStyles.input} type="email" inputMode="email" autoFocus
                        value={email} onChange={(e) => setEmail(e.target.value)}
                        placeholder="you@example.com" aria-label="Email address" />
                    </div>
                    <button style={{ ...tcAuthStyles.primary, opacity: busy ? 0.6 : 1 }} disabled={busy}
                      onClick={() => send('email', email)}>
                      {busy ? 'Sending…' : 'Send code'}
                    </button>
                    <button style={tcAuthStyles.linkBtn} onClick={() => { setStep('choose'); setErr(null); }}>← Back</button>
                  </React.Fragment>
                )}

                {step === 'code' && (
                  <React.Fragment>
                    <input style={tcAuthStyles.codeInput} type="text" inputMode="numeric" autoFocus
                      maxLength={6} value={code}
                      onChange={(e) => setCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
                      onKeyDown={(e) => { if (e.key === 'Enter') verify(); }}
                      placeholder="······" aria-label="6-digit code" />
                    <button style={{ ...tcAuthStyles.primary, opacity: busy ? 0.6 : 1 }} disabled={busy}
                      onClick={verify}>
                      {busy ? 'Verifying…' : 'Verify & continue'}
                    </button>
                    <div style={{ display: 'flex', justifyContent: 'center', gap: 4 }}>
                      <button style={tcAuthStyles.linkBtn} onClick={resend}>Resend code</button>
                      <span style={{ color: 'var(--ink-3)', alignSelf: 'center' }}>·</span>
                      <button style={tcAuthStyles.linkBtn} onClick={() => { setStep(method); setErr(null); }}>Change email</button>
                    </div>
                  </React.Fragment>
                )}
              </div>
            </div>
            <div style={tcAuthStyles.foot}>
              Your health data is encrypted and visible only to you.<br />
              By continuing you agree to MUIY’s terms & privacy notice.
            </div>
          </div>
        </div></div>
      </div>
    </div>
  );
}

// Lightweight full-screen splash shown while we check the session / pull data.
function TCSplash({ label }) {
  const scale = useFitScale();
  return (
    <div className="desk">
      <div className="device-scale" style={{ transform: `scale(${scale})` }}>
        <div className="phone"><div className="screen" data-theme="light">
          <div className="notch" />
          <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 18, background: 'var(--bg)' }}>
            <div style={{ ...tcAuthStyles.badge, animation: 'tcPulse 1.4s ease-in-out infinite' }}><TCHeart size={40} /></div>
            <div style={{ color: 'var(--ink-2)', fontWeight: 700, fontFamily: 'Manrope, sans-serif' }}>{label || 'Loading…'}</div>
          </div>
        </div></div>
      </div>
      <style>{'@keyframes tcPulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.08);opacity:.8}}'}</style>
    </div>
  );
}

// Pre-auth brand splash — reuses WfSplash (welcome.jsx) inside the same shell
// scaffold as TCSplash, so a fresh or signed-out visitor meets the welcome
// screen (Pearl mark + "Get started" / "Log in") instead of a bare login form.
// Both actions continue to the sign-in gate: in cloud mode an account comes
// first, then WelcomeFlow routes "Get started"/"Log in" into profile setup.
function TCWelcomeSplash({ onContinue }) {
  const scale = useFitScale();
  const Splash = window.WfSplash;
  const hasSaved = React.useMemo(() => {
    try { const r = localStorage.getItem('mui:onboard:v3'); const s = r ? JSON.parse(r) : null; return !!(s && s.f && (s.f.name || s.step > 0)); } catch (e) { return false; }
  }, []);
  if (!Splash) return <TCSplash label="Starting MUIY…" />;
  return (
    <div className="desk">
      <div className="device-scale" style={{ transform: `scale(${scale})` }}>
        <div className="phone"><div className="screen" data-theme="light">
          <div className="notch" />
          <Splash resuming={hasSaved} onStart={onContinue} onHaveAccount={onContinue} />
        </div></div>
      </div>
    </div>
  );
}

function RootApp() {
  const configured = !!(window.TCsb && window.TCsb.isConfigured());
  // phase: 'check' | 'auth' | 'sync' | 'ready'
  const [phase, setPhase] = React.useState(configured ? 'check' : 'ready');
  // pre-auth gate: 'splash' (WfSplash welcome) → 'login' (AuthGate)
  const [gate, setGate] = React.useState('splash');
  const [bootKey, setBootKey] = React.useState(0);   // remount <App/> after data swap

  const enterApp = React.useCallback(async () => {
    setPhase('sync');
    try { await window.TCCloud.pullAndMerge(); } catch (e) {}
    try { window.TCCloud.activate(); } catch (e) {}
    setBootKey((k) => k + 1);
    setPhase('ready');
  }, []);

  React.useEffect(() => {
    if (!configured) return;
    let unsub = function () {};
    (async () => {
      const session = await window.TCsb.getSession();
      if (session) { await enterApp(); }
      else { setGate('splash'); setPhase('auth'); }
      // react to token loss / external sign-out
      unsub = window.TCsb.onAuthChange((s, evt) => {
        if (evt === 'SIGNED_OUT' || !s) { setGate('splash'); setPhase('auth'); }
      });
    })();
    return () => unsub();
  }, [configured, enterApp]);

  if (phase === 'check') return <TCSplash label="Starting MUIY…" />;
  if (phase === 'auth') {
    if (gate === 'splash') return <TCWelcomeSplash onContinue={() => setGate('login')} />;
    return <AuthGate onAuthed={enterApp} />;
  }
  if (phase === 'sync') return <TCSplash label="Restoring your record…" />;
  // ready
  return <App key={bootKey} />;
}

window.RootApp = RootApp;
window.mountMUIRoot = function () {
  ReactDOM.createRoot(document.getElementById('root')).render(<RootApp />);
};
