/* global React */
const { useState, useEffect, useRef } = React;

function GoogleGlyph() {
  return (
    <svg width="18" height="18" viewBox="0 0 18 18" aria-hidden>
      <path fill="#4285F4" d="M17.6 9.2c0-.6-.1-1.2-.2-1.7H9v3.3h4.8c-.2 1.1-.8 2-1.8 2.6v2.2h2.9c1.7-1.6 2.7-3.9 2.7-6.4z"/>
      <path fill="#34A853" d="M9 18c2.4 0 4.5-.8 6-2.2l-2.9-2.2c-.8.5-1.8.9-3.1.9-2.4 0-4.4-1.6-5.1-3.7H.9v2.3C2.4 15.9 5.5 18 9 18z"/>
      <path fill="#FBBC05" d="M3.9 10.7c-.2-.5-.3-1.1-.3-1.7s.1-1.2.3-1.7V5H.9C.3 6.2 0 7.5 0 9s.3 2.8.9 4l3-2.3z"/>
      <path fill="#EA4335" d="M9 3.6c1.3 0 2.5.5 3.5 1.4l2.6-2.6C13.5.9 11.4 0 9 0 5.5 0 2.4 2.1.9 5l3 2.3C4.6 5.2 6.6 3.6 9 3.6z"/>
    </svg>
  );
}

function getGoogleClientIdLocal() {
  return (window.JOVANA_CONFIG && window.JOVANA_CONFIG.googleClientId) || '';
}

// Google blocks OAuth in embedded webviews (error 403: disallowed_useragent).
// We detect the most common in-app browsers so we can swap the Google button
// for an "open in your real browser" banner — see Google's Secure Browsers
// policy. Email-code sign-in still works in these webviews, so the rest of
// the gate stays usable.
function detectInAppBrowser() {
  if (typeof navigator === 'undefined') return null;
  const ua = navigator.userAgent || '';
  if (/\bLine\//i.test(ua)) return 'LINE';
  if (/FBAN|FBAV|FB_IAB|FBIOS/i.test(ua)) return 'Facebook';
  if (/Instagram/i.test(ua)) return 'Instagram';
  if (/\bThreads\b/i.test(ua)) return 'Threads';
  if (/MicroMessenger/i.test(ua)) return 'WeChat';
  if (/KAKAOTALK/i.test(ua)) return 'KakaoTalk';
  if (/TwitterAndroid|\bTwitter for/i.test(ua)) return 'X / Twitter';
  if (/DingTalk/i.test(ua)) return 'DingTalk';
  if (/Snapchat/i.test(ua)) return 'Snapchat';
  // Android system webview: the `; wv)` token in the UA.
  if (/Android[^;]*;\s*wv\)/i.test(ua)) return 'in-app browser';
  // iOS heuristic: WebKit without a Safari/ token, and not a standalone PWA.
  const isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream;
  if (isIOS) {
    const hasSafariToken = / Safari\//.test(ua);
    const isStandalone = window.navigator && window.navigator.standalone === true;
    if (!hasSafariToken && !isStandalone) return 'in-app browser';
  }
  return null;
}

async function gateApi(path, opts = {}) {
  const init = { credentials: 'include', ...opts };
  init.headers = { 'Content-Type': 'application/json', ...(opts.headers || {}) };
  if (init.body && typeof init.body !== 'string') init.body = JSON.stringify(init.body);
  const res = await fetch(path, init);
  let data = null;
  try { data = await res.json(); } catch {}
  if (!res.ok) {
    const err = new Error((data && data.error) || `http_${res.status}`);
    err.status = res.status;
    err.data = data;
    throw err;
  }
  return data;
}

const REDIRECT_AFTER_SIGNIN = '/dashboard.html';

function SignInGate({ onClose, onSignedIn }) {
  const [step, setStep] = useState('email'); // 'email' | 'code'
  const [email, setEmail] = useState('');
  const [name, setName] = useState('');
  const [code, setCode] = useState('');
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState('');
  const [status, setStatus] = useState('SECURE CHANNEL · READY');
  const [devCode, setDevCode] = useState('');

  const [clientId, setClientId] = useState(getGoogleClientIdLocal());
  const [inAppBrowser] = useState(() => detectInAppBrowser());
  const gsiBtnRef = useRef(null);

  // Pick up the Client ID once /api/config resolves and writes it onto window
  useEffect(() => {
    if (clientId) return;
    const onConfig = () => setClientId(getGoogleClientIdLocal());
    window.addEventListener('jovana:config', onConfig);
    onConfig();
    return () => window.removeEventListener('jovana:config', onConfig);
  }, [clientId]);

  // Initialize Google Identity Services and render the (transparent overlay) button
  useEffect(() => {
    if (step !== 'email' || !clientId) return;
    if (inAppBrowser) return; // GIS would 403 in webviews; banner is rendered instead.
    let cancelled = false;
    let attempts = 0;
    const tryInit = () => {
      if (cancelled) return;
      const gsi = window.google && window.google.accounts && window.google.accounts.id;
      if (!gsi) {
        if (attempts++ < 50) setTimeout(tryInit, 150);
        return;
      }
      gsi.initialize({
        client_id: clientId,
        callback: async (res) => {
          if (!res || !res.credential) return;
          setBusy(true);
          setError('');
          setStatus('VERIFYING IDENTITY…');
          try {
            const data = await gateApi('/api/auth/google', {
              method: 'POST',
              body: { idToken: res.credential },
            });
            setStatus('ACCESS GRANTED');
            onSignedIn?.(data.user);
            setTimeout(() => {
              window.location.assign(REDIRECT_AFTER_SIGNIN);
            }, 700);
          } catch (e) {
            setBusy(false);
            setStatus('SECURE CHANNEL · READY');
            setError('Google sign-in failed: ' + (e.message || ''));
          }
        },
        ux_mode: 'popup',
        auto_select: false,
        itp_support: true,
      });
      const slot = gsiBtnRef.current;
      if (slot) {
        slot.replaceChildren();
        gsi.renderButton(slot, {
          type: 'standard',
          theme: 'filled_black',
          size: 'large',
          shape: 'rectangular',
          text: 'continue_with',
          logo_alignment: 'left',
          width: 360,
        });
      }
    };
    tryInit();
    return () => { cancelled = true; };
  }, [clientId, step, onSignedIn, inAppBrowser]);

  function isValidEmail(value) {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
  }

  async function submitEmail(e) {
    e.preventDefault();
    if (busy) return;
    const value = email.trim().toLowerCase();
    if (!isValidEmail(value)) {
      setError('請輸入有效的電子郵件 · Please enter a valid email.');
      return;
    }
    if (!name.trim()) {
      setError('請輸入顯示名稱 · Please enter a display name.');
      return;
    }
    setError('');
    setBusy(true);
    setStatus('REQUESTING ACCESS CODE…');
    try {
      const data = await gateApi('/api/auth/email/start', {
        method: 'POST',
        body: { email: value },
      });
      setEmail(value);
      setDevCode(data.devCode || '');
      setStep('code');
      setStatus('CODE DELIVERED · CHECK INBOX');
    } catch (err) {
      if (err.status === 429) setError('請求過於頻繁，請稍後再試 · Too many requests.');
      else setError(err.message || '寄送失敗 · Failed to send code.');
      setStatus('SECURE CHANNEL · READY');
    } finally {
      setBusy(false);
    }
  }

  async function submitCode(e) {
    e.preventDefault();
    if (busy) return;
    const cleanCode = code.replace(/\s+/g, '');
    if (!/^\d{6}$/.test(cleanCode)) {
      setError('請輸入 6 位數驗證碼 · Enter the 6-digit code.');
      return;
    }
    setError('');
    setBusy(true);
    setStatus('VERIFYING IDENTITY…');
    try {
      const data = await gateApi('/api/auth/email/verify', {
        method: 'POST',
        body: { email, code: cleanCode, name: name.trim() || undefined },
      });
      setStatus('ACCESS GRANTED');
      onSignedIn?.(data.user);
      setTimeout(() => {
        window.location.assign(REDIRECT_AFTER_SIGNIN);
      }, 700);
    } catch (err) {
      if (err.status === 401) setError('驗證碼錯誤 · Incorrect code.');
      else if (err.status === 429) setError('嘗試次數過多 · Too many attempts.');
      else if (err.message === 'code_expired') setError('驗證碼已過期 · Code expired.');
      else if (err.message === 'no_active_code') setError('找不到有效驗證碼 · Request a new one.');
      else setError(err.message || '驗證失敗 · Verification failed.');
      setBusy(false);
      setStatus('CODE DELIVERED · CHECK INBOX');
    }
  }

  async function resend() {
    if (busy) return;
    setError('');
    setBusy(true);
    setStatus('REQUESTING ACCESS CODE…');
    try {
      const data = await gateApi('/api/auth/email/start', {
        method: 'POST',
        body: { email },
      });
      setDevCode(data.devCode || '');
      setStatus('CODE DELIVERED · CHECK INBOX');
    } catch (err) {
      if (err.status === 429) setError('請求過於頻繁，請稍後再試 · Too many requests.');
      else setError(err.message || '');
      setStatus('SECURE CHANNEL · READY');
    } finally {
      setBusy(false);
    }
  }

  function backToEmail() {
    if (busy) return;
    setStep('email');
    setCode('');
    setError('');
    setStatus('SECURE CHANNEL · READY');
  }

  const submitHandler = step === 'email' ? submitEmail : submitCode;

  return (
    <div className="gate" role="dialog" aria-modal="true" aria-label="Sign in">
      <div className="gate-bg" />
      <div className="gate-card" onClick={(e) => e.stopPropagation()}>
        <div className="gate-corners">
          <i className="tl"/><i className="tr"/><i className="bl"/><i className="br"/>
        </div>

        <button onClick={onClose} aria-label="Close" style={{
          position: 'absolute', top: 14, right: 14, background: 'none',
          border: '1px solid var(--line-soft)', color: 'var(--ink-2)',
          width: 28, height: 28, borderRadius: 4, fontFamily: 'var(--ff-mono)',
          fontSize: 14, lineHeight: 1
        }}>×</button>

        <div className="gate-eyebrow">CHANNEL · 0xJM-AUTH</div>
        <h2 className="gate-title">進入 <em>檔案室</em></h2>

        <form className="gate-form" onSubmit={submitHandler} autoComplete="on">
          {step === 'email' ? (
            <>
              <div className="field">
                <input
                  type="email" required placeholder=" "
                  value={email}
                  onChange={(e) => setEmail(e.target.value)}
                  id="gate-email"
                  disabled={busy}
                  autoComplete="email"
                />
                <label htmlFor="gate-email">EMAIL</label>
              </div>
              <div className="field">
                <input
                  type="text" required placeholder=" "
                  value={name}
                  onChange={(e) => setName(e.target.value)}
                  id="gate-name"
                  disabled={busy}
                  maxLength={64}
                  autoComplete="name"
                />
                <label htmlFor="gate-name">顯示名稱 · DISPLAY NAME</label>
              </div>
            </>
          ) : (
            <>
              <div className="field">
                <input
                  type="email" placeholder=" "
                  value={email}
                  readOnly
                  id="gate-email-locked"
                />
                <label htmlFor="gate-email-locked">EMAIL</label>
              </div>
              <div className="field">
                <input
                  type="text" required placeholder=" "
                  value={code}
                  onChange={(e) => setCode(e.target.value.replace(/[^0-9]/g, '').slice(0, 6))}
                  id="gate-code"
                  disabled={busy}
                  inputMode="numeric"
                  pattern="[0-9]{6}"
                  autoComplete="one-time-code"
                  autoFocus
                />
                <label htmlFor="gate-code">驗證碼 · 6-DIGIT CODE</label>
              </div>
              {devCode && (
                <div style={{
                  fontFamily: 'var(--ff-mono)', fontSize: 11,
                  letterSpacing: '.18em', color: 'var(--neon-mint)',
                  textAlign: 'center', padding: '6px 0',
                }}>
                  DEV CODE · {devCode}
                </div>
              )}
            </>
          )}

          <div className="gate-actions">
            <button className="gate-submit" type="submit" disabled={busy}>
              {busy
                ? '處理中…'
                : step === 'email'
                  ? '傳送驗證碼 · SEND CODE'
                  : '解鎖檔案室 · UNSEAL'}
            </button>

            {step === 'email' && (
              <>
                <div className="gate-divider">OR</div>
                {inAppBrowser ? (
                  <div
                    role="note"
                    style={{
                      border: '1px solid var(--line-soft)',
                      borderRadius: 6,
                      padding: '12px 14px',
                      fontFamily: 'var(--ff-mono)',
                      fontSize: 12,
                      lineHeight: 1.55,
                      color: 'var(--ink-2)',
                      background: 'rgba(255,255,255,0.02)',
                    }}
                  >
                    <div style={{
                      fontSize: 10, letterSpacing: '.18em',
                      color: 'var(--neon-amber, #f5b452)', marginBottom: 6,
                    }}>
                      ⚠ {inAppBrowser.toUpperCase()} IN-APP BROWSER DETECTED
                    </div>
                    <div style={{ color: 'var(--ink-1)' }}>
                      Google 為了帳號安全，會拒絕在 <strong>{inAppBrowser}</strong> 內建瀏覽器中以 Google 登入（錯誤代碼 <code>403 disallowed_useragent</code>）。
                    </div>
                    <div style={{ marginTop: 8 }}>
                      請點畫面右上角的「<strong>⋯</strong>」或選單，選「<strong>在瀏覽器中開啟</strong>」（Safari / Chrome），再按 Google 登入。
                    </div>
                    <div style={{ marginTop: 8, color: 'var(--neon-mint)' }}>
                      或直接使用上方 Email 驗證碼登入，這在此瀏覽器內仍可正常運作。
                    </div>
                  </div>
                ) : (
                  <div className="gate-google-shell">
                    <button
                      type="button"
                      className="gate-google"
                      disabled={busy}
                      aria-hidden="true"
                      tabIndex={-1}
                    >
                      <GoogleGlyph /> 以 Google 一鍵登入
                    </button>
                    <div ref={gsiBtnRef} className="gate-google-real" aria-label="Sign in with Google" />
                  </div>
                )}
              </>
            )}
          </div>
        </form>

        <div className="gate-status" aria-live="polite">
          <span className="dot"/>
          {error ? (
            <span style={{ color: 'var(--neon-magenta)' }}>{error}</span>
          ) : (
            <span>{status}</span>
          )}
        </div>

        <div className="gate-foot">
          {step === 'email' ? (
            <a href="#" onClick={(e) => { e.preventDefault(); }}>首次登入？以上資料即為註冊</a>
          ) : (
            <>
              <a href="#" onClick={(e) => { e.preventDefault(); backToEmail(); }}>← 回上一步</a>
              <a href="#" onClick={(e) => { e.preventDefault(); resend(); }}>重寄驗證碼</a>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

window.SignInGate = SignInGate;
