/**
 * ═══════════════════════════════════════════════════════════════════
 * Login Page Component (State-driven)
 * ═══════════════════════════════════════════════════════════════════
 * 
 * Login component that renders inside index.html when appState.view = 'login'
 * NO redirects - purely state-driven
 *
 * First-impression UX: SylvanTech halo logo, benefit-led copy, PIN explainer,
 * stacked primary/secondary CTAs, trust line, reduced-motion-safe entrance.
 */

(function() {
  'use strict';

  const { useState, useEffect } = React;

  /** Official multicolor Google "G" — Sign in with Google button branding */
  function GoogleSignInIcon({ className = 'h-5 w-5 shrink-0' }) {
    return (
      <svg
        className={className}
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 48 48"
        width="20"
        height="20"
        aria-hidden="true"
        focusable="false"
      >
        <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>
    );
  }

  function LoginPage() {
    const [email, setEmail] = useState('');
    const [pin, setPin] = useState('');
    const [step, setStep] = useState('email'); // 'email', 'pin', 'pending'
    const [mode, setMode] = useState(null); // 'login' or 'create'
    const [loading, setLoading] = useState(false);
    const [googleBusy, setGoogleBusy] = useState(false);
    const [error, setError] = useState(null);
    const [success, setSuccess] = useState(null);

    useEffect(() => {
      try {
        const oauthErr = sessionStorage.getItem('sylvanflow_oauth_error');
        if (oauthErr) {
          sessionStorage.removeItem('sylvanflow_oauth_error');
          setError(
            oauthErr === 'access_denied'
              ? 'Google sign-in was cancelled.'
              : 'Google sign-in failed. Try email sign-up or try again.'
          );
        }
        if (sessionStorage.getItem('sylvanflow_oauth_pending') === '1') {
          sessionStorage.removeItem('sylvanflow_oauth_pending');
          const msg = sessionStorage.getItem('sylvanflow_oauth_pending_message');
          sessionStorage.removeItem('sylvanflow_oauth_pending_message');
          setStep('pending');
          setSuccess(msg || 'Google sign-in verified. Your account is pending admin approval.');
        }
      } catch (_) {
        /* non-fatal */
      }
    }, []);

    useEffect(() => {
      try {
        if (window.SYLVAN_TECH_THEME && typeof window.SYLVAN_TECH_THEME.ensureKeyframes === 'function') {
          window.SYLVAN_TECH_THEME.ensureKeyframes();
        }
      } catch (_) {
        /* non-fatal */
      }
    }, []);

    const handleGoogleSignIn = () => {
      if (googleBusy || loading) return;
      setGoogleBusy(true);
      setError(null);
      setSuccess(null);
      const apiBase = window.SF_API_BASE || window.location.origin;
      const relay = window.SylvanFlowOAuthRelay;

      const finishIframeOAuthFromPopup = (data) => {
        if (relay) relay.applySession(data);
        setGoogleBusy(false);
        const err = data?.error;
        if (err) {
          setError(
            err === 'access_denied'
              ? 'Google sign-in was cancelled.'
              : err === 'approval_pending'
                ? 'Google sign-in verified. Your account is pending admin approval.'
                : typeof err === 'string' && err.length < 120
                  ? err
                  : 'Google sign-in failed. Try email sign-up or try again.'
          );
          return;
        }
        if (data?.pending) {
          setStep('pending');
          setSuccess(data.message || 'Google sign-in verified. Your account is pending admin approval.');
          return;
        }
        if (data?.next === 'legal') {
          // SF_ALLOW_HARDEXIT_REDIRECT
          window.location.href = '/legal?return=/app';
          return;
        }
        // SF_ALLOW_HARDEXIT_REDIRECT — session applied from popup relay (partition-safe)
        window.location.href = '/app';
      };

      // SF_ALLOW_HARDEXIT_REDIRECT — Google blocks OAuth inside iframes (X-Frame-Options: DENY)
      let inIframe = false;
      try {
        inIframe = window.self !== window.top;
      } catch {
        inIframe = true;
      }
      if (inIframe) {
        const returnPath = '/app?oauth_popup=1';
        const url = `${apiBase}/api/auth/google?return=${encodeURIComponent(returnPath)}`;
        let poll = null;
        let busyTimeout = null;
        let detachRelay = null;

        const cleanup = () => {
          detachRelay?.();
          if (poll) window.clearInterval(poll);
          if (busyTimeout) window.clearTimeout(busyTimeout);
        };

        detachRelay = relay
          ? relay.attachListener((data) => {
              cleanup();
              finishIframeOAuthFromPopup(data);
            })
          : null;
        let popup = null;

        busyTimeout = window.setTimeout(() => {
          cleanup();
          setGoogleBusy(false);
        }, 180000);

        if (relay?.parentIsCrossOrigin()) {
          window.parent.postMessage({ type: relay.REQUEST, url }, '*');
        } else {
          popup = window.open(
            url,
            'sylvanflow_google_oauth',
            'popup=yes,width=520,height=720,left=80,top=80'
          );
          if (!popup) {
            cleanup();
            setGoogleBusy(false);
            setError(
              'Allow pop-ups for Google sign-in. The popup closes when done and the app continues in this panel.'
            );
            return;
          }
        }

        poll = window.setInterval(() => {
          if (popup && !popup.closed) return;
          if (popup && popup.closed) {
            cleanup();
            setGoogleBusy(false);
            if (localStorage.getItem('sylvanflow_session_token')) {
              // SF_ALLOW_HARDEXIT_REDIRECT
              window.location.href = '/app';
            }
          }
        }, 400);
        return;
      }
      const url = `${apiBase}/api/auth/google?return=${encodeURIComponent('/app')}`;
      // SF_ALLOW_HARDEXIT_REDIRECT — same-tab OAuth when not embedded
      window.location.href = url;
    };

    const tc =
      typeof window !== 'undefined' && window.SYLVAN_TECH_THEME && window.SYLVAN_TECH_THEME.classes
        ? window.SYLVAN_TECH_THEME.classes
        : {};

    // ✅ GATEWAY MIGRATION: Use SF_API_BASE (Gateway Worker) instead of smartBrainUrl
    // ✅ GATEWAY MIGRATION: Use SF_API_BASE from shared-api-config.js (no duplicate declaration)
    const SF_API_BASE = window.SF_API_BASE;

    const handleEmailSubmit = async (e, action) => {
      // ✅ TASK 1: Comprehensive instrumentation - entry point (admin-only, sanitized)
      if (window.uiLogger) {
        window.uiLogger.uiLog('[LOGIN-TRACE] HANDLER ENTRY', {
          action,
          hasEmail: !!email,
          emailLength: email?.length || 0,
          timestamp: Date.now()
        });
      }
      
      // ✅ STEP 7: Catch-all error handler to surface silent errors
      try {
        // ✅ FIX: Log resetAuthState availability at the very top (admin-only)
        if (window.uiLogger) {
          window.uiLogger.uiLog('[LOGIN] resetAuthState present?', { present: !!window.resetAuthState, type: typeof window.resetAuthState });
        }
        
        // ✅ STEP 4: Verify form submission path (admin-only, sanitized)
        if (window.uiLogger) {
          window.uiLogger.uiLog('[LOGIN-TRACE] Form submission path', {
            hasEvent: !!e,
            eventType: e?.type,
            eventTarget: e?.target?.tagName,
            eventCurrentTarget: e?.currentTarget?.tagName,
            action: action
          });
        }
        
        if (e) {
          e.preventDefault();
          e.stopPropagation();
          if (window.uiLogger) {
            window.uiLogger.uiLog('[LOGIN-TRACE] preventDefault() called ONCE');
          }
        }
        if (window.uiLogger) {
          window.uiLogger.uiLog('handleEmailSubmit called with action:', action, 'hasEmail:', !!email);
        }
        
        // ✅ INVESTIGATION: DO NOT call resetAuthState() during login flow
        // resetAuthState() clears session token, which breaks PIN verification flow
        // Only call it when starting a NEW login (not during existing flow)
        // The view should already be 'login' when user is on login page
        if (window.uiLogger) {
          window.uiLogger.uiLog('[LOGIN-TRACE] SKIPPING resetAuthState() - not needed during login flow');
          window.uiLogger.uiLog('[LOGIN-TRACE] Current view:', window.appState?.get()?.view);
        }
        
        // ✅ FIX: Only reset view if it's not already 'login'
        const currentView = window.appState?.get()?.view;
        if (currentView !== 'login') {
          if (window.uiLogger) {
            window.uiLogger.uiLog('[LOGIN-TRACE] Setting view to login (was:', currentView, ')');
          }
          window.appState?.set({ view: 'login' });
        } else {
          if (window.uiLogger) {
            window.uiLogger.uiLog('[LOGIN-TRACE] View already set to login, skipping');
          }
        }
        
        // ✅ TASK 2: Log after resetAuthState() scheduling (not execution) (admin-only, sanitized)
        if (window.uiLogger) {
          window.uiLogger.uiLog('[LOGIN-TRACE] After resetAuthState() scheduled', {
            hasEmail: Boolean(email),
            emailLength: email?.length || 0,
            action
          });
        }
        
        if (!email || !email.trim()) {
          // ✅ TASK 2: Log early return (admin-only, sanitized)
          if (window.uiLogger) {
            window.uiLogger.uiWarn('[LOGIN-TRACE] EARLY RETURN TRIGGERED', {
              reason: 'email missing or empty',
              hasEmail: Boolean(email),
              emailLength: email?.length || 0
            });
          }
          setError('Please enter your email address');
          if (window.uiLogger) {
            window.uiLogger.uiLog('[LOGIN-TRACE] HANDLER EXIT (early return - no email)');
          }
          return;
        }
        
        if (window.uiLogger) {
          window.uiLogger.uiLog('[LOGIN-TRACE] Email validation passed, setting loading state');
        }
        setLoading(true);
        setError(null);
        setSuccess(null);
        setMode(action);

        try {
        // First, check login status (for existing users who may not need PIN)
        const loginUrl = `${SF_API_BASE}/api/auth/login`;
        const isExistingUser = action === 'login';
        
        // ✅ TASK 4: Log before fetch construction (admin-only, sanitized)
        if (window.uiLogger) {
          window.uiLogger.uiLog('[LOGIN-TRACE] About to call auth API', {
            endpoint: '/api/auth/login',
            action: action,
            isExistingUser: isExistingUser,
            url: loginUrl,
            hasEmail: !!email,
            emailLength: email?.trim().length || 0
          });
          
          window.uiLogger.uiLog('Checking login status:', loginUrl);
          window.uiLogger.uiLog('Request body:', { hasEmail: !!email, emailLength: email?.trim().length || 0 });
          window.uiLogger.uiLog('[LOGIN-TRACE] AUTH FETCH STARTED - constructing fetch() call');
        }
        const fetchStartTime = Date.now();
        const loginResponse = await fetch(loginUrl, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          credentials: 'include',
          body: JSON.stringify({ email: email.trim() }),
        });
        
        // ✅ TASK 4: Log after fetch returns (admin-only, sanitized)
        const fetchEndTime = Date.now();
        if (window.uiLogger) {
          window.uiLogger.uiLog('[LOGIN-TRACE] AUTH FETCH COMPLETED', {
            status: loginResponse.status,
            duration_ms: fetchEndTime - fetchStartTime
          });

          window.uiLogger.uiLog('Login response status:', loginResponse.status);
        }
        const loginData = await loginResponse.json();
        if (window.uiLogger) {
          window.uiLogger.uiLog('Login response data:', { 
            ok: loginData.ok, 
            hasCode: !!loginData.code,
            hasState: !!loginData.state,
            hasError: !!loginData.error
          });

          // ✅ DEBUG: Log condition check for PIN redirect (admin-only, sanitized)
          window.uiLogger.uiLog('[LOGIN-DEBUG] Checking PIN redirect condition:', {
            'loginData.ok': loginData.ok,
            'loginData.state': loginData.state,
            'loginData.next_action': loginData.next_action,
            'state === "AUTH_NEEDS_PIN"': loginData.state === "AUTH_NEEDS_PIN",
            'next_action === "request_pin"': loginData.next_action === "request_pin",
            'allConditions': loginData.ok && loginData.state === "AUTH_NEEDS_PIN" && loginData.next_action === "request_pin"
          });
        }

        // ✅ PHASE 1 MIGRATION: Use new auth states format (state-based checks)
        // Login should return AUTH_NEEDS_PIN for approved users; AUTH_OK here is defensive only (verify-pin uses its own handler)
        if (loginData.ok && loginData.state === "AUTH_OK") {
          if (window.uiLogger) {
            window.uiLogger.uiLog('✅ Login returned AUTH_OK (session established)');
          }
          // ✅ FIX: Store email for display only - NEVER use as identity
          localStorage.setItem('sylvanflow_display_email', email.trim()); // DISPLAY ONLY — NEVER USE AS IDENTITY
          // identity comes from auth.userKey ONLY
          // Identity comes from Bearer token only
          if (loginData.session_token) {
            const prevTok = localStorage.getItem('sylvanflow_session_token');
            if (prevTok !== loginData.session_token && window.SylvanFlowAuth?.clearSylvanClientChatSessionCache) {
              window.SylvanFlowAuth.clearSylvanClientChatSessionCache();
            }
            localStorage.setItem('sylvanflow_session_token', loginData.session_token);
            if (window.uiLogger) {
              window.uiLogger.uiLog('✅ Session token stored');
            }
          }
          localStorage.setItem('sylvanflow_session', 'active');
          
          // ✅ LEGACY LOGIN REMOVAL: Check for post-login return URL
          const postLoginReturn = localStorage.getItem('sf_post_login_return');
          if (postLoginReturn) {
            // ✅ STEP 3: Expose early return
            if (window.uiLogger) {
              window.uiLogger.uiWarn('[LOGIN-TRACE] EARLY RETURN TRIGGERED', {
                reason: 'post-login return URL exists',
                returnUrl: postLoginReturn
              });
            }
            // Remove return URL (one-time use)
            localStorage.removeItem('sf_post_login_return');
            // Redirect to return URL (hard-exit navigation is acceptable)
            // SF_ALLOW_HARDEXIT_REDIRECT
            window.location.href = postLoginReturn;
            return;
          }
          
          // ✅ S003 / Issue #68: Legal ack for *this* Bearer — always call /api/legal/status when token exists (no localStorage fast-pass skip).
          let legalAgreed = null;
          if (loginData.session_token) {
            try {
              const controller = new AbortController();
              const timeoutId = setTimeout(() => controller.abort(), 3500);
              const statusRes = await fetch(`${window.SF_API_BASE || 'https://sf-api-gateway.foofiebean.workers.dev'}/api/legal/status`, {
                headers: {
                  Authorization: `Bearer ${loginData.session_token}`
                },
                signal: controller.signal
              });
              clearTimeout(timeoutId);
              if (statusRes.ok) {
                const statusData = await statusRes.json();
                const legalCurrent = window.SylvanFlowLegal && typeof window.SylvanFlowLegal.isLegalStatusCurrent === 'function'
                  ? window.SylvanFlowLegal.isLegalStatusCurrent(statusData)
                  : !!(statusData.ok && statusData.acknowledged && statusData.acknowledged_at);
                if (legalCurrent) {
                  legalAgreed = statusData.acknowledged_at;
                  localStorage.setItem('sylvanflow_legal_agreed', statusData.acknowledged_at);
                  if (window.uiLogger) {
                    window.uiLogger.uiLog('[LOGIN] Legal bundle current via /api/legal/status');
                  }
                } else {
                  localStorage.removeItem('sylvanflow_legal_agreed');
                }
              }
            } catch (e) {
              if (window.uiLogger) {
                window.uiLogger.uiWarn('[LOGIN] /api/legal/status fetch failed:', e.message);
              }
              legalAgreed = localStorage.getItem('sylvanflow_legal_agreed');
            }
          }
          
          if (!legalAgreed) {
            if (window.uiLogger) {
              window.uiLogger.uiLog('[LOGIN] Legal not current or missing — redirecting to /legal');
            }
            // Redirect to legal page with return URL to power-up
            // SF_ALLOW_HARDEXIT_REDIRECT
            window.location.href = '/legal?return=/power-up';
            return;
          }
          
          // ✅ AUTH FLOW: Set to loading — ensureAuthenticated routes complete profiles to NOW WHAT
          // identity comes from auth.userKey ONLY
          // user object is for display/metadata only, not for identity
          window.appState.set({
            view: 'loading',
            user: { email: email.trim() } // Email is display-only, identity from Bearer token
          });
          setLoading(false); // Clear login loading state
          
          // ✅ ISSUE #15 FIX (Phase 2): ensureAuthenticated owns view transition when view === 'loading' (app.js line ~921). No redundant .then() — avoids race when duplicate ensureAuthenticated() returns false from guard.
          if (window.ensureAuthenticated && typeof window.ensureAuthenticated === 'function') {
            window.ensureAuthenticated("login_success_from_loginpage").catch((err) => {
              if (window.uiLogger) {
                window.uiLogger.uiError('[LOGIN] ensureAuthenticated failed', { err });
              }
            });
          } else {
            if (window.uiLogger) {
              window.uiLogger.uiWarn('[LOGIN->AUTH] ensureAuthenticated not available, dispatching event');
            }
            // Fallback: Dispatch event that AppShell can listen for
            try {
              window.dispatchEvent(new CustomEvent('sf:auth:token-updated', {
                detail: { reason: 'login_success_from_loginpage' }
              }));
            } catch (eventErr) {
              if (window.uiLogger) {
                window.uiLogger.uiError('[LOGIN->AUTH] Event dispatch error:', eventErr.message || eventErr);
              }
            }
          }

          return; // Issue #67: removed timed power-up unstick — ensureAuthenticated/legal/profile ordering must remain authoritative
        }

        // ✅ PHASE 1 MIGRATION: Use new auth states format (state-based checks)
        // If account exists but PIN required (new user needs PIN)
        if (loginData.ok && loginData.state === "AUTH_NEEDS_PIN" && loginData.next_action === "request_pin") {
          if (window.uiLogger) {
            window.uiLogger.uiLog('PIN required - requesting PIN');
            // ✅ STEP 2: Add trace log before request-pin call (admin-only, sanitized)
            window.uiLogger.uiLog('[LOGIN-TRACE] About to call auth API', {
              endpoint: '/api/auth/request-pin',
              isExistingUser: true
            });
            // Request PIN for existing user
            window.uiLogger.uiLog('[LOGIN-TRACE] AUTH FETCH STARTED');
          }
          const pinResponse = await fetch(`${SF_API_BASE}/api/auth/request-pin`, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            credentials: 'include',
            body: JSON.stringify({ email: email.trim() }),
          });

          const pinData = await pinResponse.json();

          // ✅ PHASE 1 MIGRATION: Use new auth states format (state-based checks)
          if (pinData.ok && pinData.state === "AUTH_PIN_SENT") {
            setStep('pin');
            setSuccess(pinData.message || 'PIN sent to your email. Please check your inbox.');
          } else {
            // Handle specific error cases (rate limiting)
            if (pinData.ok === false && pinData.state === "AUTH_NEEDS_PIN" && pinData.message && pinData.message.includes("Too many")) {
              const minutesMatch = pinData.message.match(/(\d+)\s+minute/);
              const minutes = minutesMatch ? minutesMatch[1] : '20';
              setError(pinData.message || `Too many PIN requests. Please try again in ${minutes} minute(s), or use a different email address.`);
            } else {
              // ✅ PHASE 1 MIGRATION: Use message field instead of error field
              setError(pinData.message || pinData.error || 'Failed to send PIN. Please try again.');
            }
          }
          return;
        }

        // ✅ PHASE 1 MIGRATION: Use new auth states format (state-based checks)
        // Handle other login errors
        if (loginData.state === "AUTH_APPROVAL_PENDING") {
          // ✅ STEP 3: Expose early return
          if (window.uiLogger) {
            window.uiLogger.uiWarn('[LOGIN-TRACE] EARLY RETURN TRIGGERED', {
              reason: 'AUTH_APPROVAL_PENDING'
            });
          }
          setError(loginData.message || 'Your account is pending admin approval. Please wait for approval.');
        } else if (loginData.state === "AUTH_NEEDS_PIN" && loginData.message && loginData.message.includes("not found") && action === 'login') {
          // ✅ STEP 3: Expose early return (admin-only, sanitized)
          if (window.uiLogger) {
            window.uiLogger.uiWarn('[LOGIN-TRACE] EARLY RETURN TRIGGERED', {
              reason: 'account_not_found with action=login',
              action: action,
              hasError: !!loginData.error
            });
          }
          setError('Account not found. Please create an account first.');
          // ✅ FIX: Ensure view is set to 'login' and complete auth check immediately
          // resetAuthState() set view to 'loading' and authChecked=false, but login failed
          // We need to complete the auth check so the safety timeout doesn't fire
          const currentView = window.appState?.get()?.view;
          if (window.uiLogger) {
            window.uiLogger.uiLog('[LOGIN] account_not_found - current view:', currentView, 'setting to login');
          }
          if (window.appState) {
            window.appState.set({ view: 'login' });
            if (window.uiLogger) {
              window.uiLogger.uiLog('[LOGIN] account_not_found - view set to login, new view:', window.appState.get().view);
            }
          }
          // ✅ FIX: Directly complete auth check by calling resetAuthState completion
          // This ensures authCompletedRef.current is set to true immediately
          if (window.uiLogger) {
            window.uiLogger.uiLog('[LOGIN] account_not_found - checking completeAuthCheck availability:', {
              hasResetAuthState: !!window.resetAuthState,
              hasCompleteAuthCheck: !!window.completeAuthCheck,
              completeAuthCheckType: typeof window.completeAuthCheck
            });
          }
          if (window.completeAuthCheck && typeof window.completeAuthCheck === 'function') {
            if (window.uiLogger) {
              window.uiLogger.uiLog('[LOGIN] account_not_found - calling completeAuthCheck()');
            }
            try {
              window.completeAuthCheck('account_not_found');
              if (window.uiLogger) {
                window.uiLogger.uiLog('[LOGIN] account_not_found - completeAuthCheck() called successfully');
              }
            } catch (e) {
              if (window.uiLogger) {
                window.uiLogger.uiError('[LOGIN] account_not_found - completeAuthCheck() error:', e.message || e);
              }
            }
          } else {
            if (window.uiLogger) {
              window.uiLogger.uiWarn('[LOGIN] account_not_found - completeAuthCheck not available, cannot complete auth check');
            }
          }
        } else {
          // ✅ PHASE 1 MIGRATION: Use new auth states format (message field)
          // ✅ STEP 3: Expose early return (admin-only, sanitized)
          if (window.uiLogger) {
            window.uiLogger.uiWarn('[LOGIN-TRACE] EARLY RETURN TRIGGERED', {
              reason: 'login failed with error',
              state: loginData.state,
              hasMessage: !!loginData.message
            });
          }
          setError(loginData.message || loginData.error || 'Login failed. Please try again.');
        }
      } catch (innerErr) {
        // ✅ TASK 2: Log exception in nested try block (admin-only, sanitized)
        if (window.uiLogger) {
            window.uiLogger.uiWarn('[LOGIN-TRACE] EARLY RETURN TRIGGERED', {
              reason: 'exception in nested try block',
              error: innerErr.message,
              errorName: innerErr.name,
              errorStackLength: innerErr.stack?.length || 0
            });
            window.uiLogger.uiError('Login error:', innerErr.message || innerErr);
          }
          setError('Network error. Please check your connection and try again.');
        }
      } catch (err) {
        // ✅ TASK 2: Log exception in outer try block (admin-only, sanitized)
        if (window.uiLogger) {
          window.uiLogger.uiWarn('[LOGIN-TRACE] EARLY RETURN TRIGGERED', {
            reason: 'exception in try block',
            error: err.message,
            errorName: err.name,
            errorStackLength: err.stack?.length || 0
          });
          window.uiLogger.uiError('Login error:', err.message || err);
        }
        setError('Network error. Please check your connection and try again.');
      } finally {
        setLoading(false);
        if (window.uiLogger) {
          window.uiLogger.uiLog('[LOGIN-TRACE] Inner try/finally block completed');
        }
      }
      
      // ✅ TASK 1: Log normal exit
      if (window.uiLogger) {
        window.uiLogger.uiLog('[LOGIN-TRACE] HANDLER EXIT (normal completion)');
      }
    };

    const handlePinSubmit = async (e) => {
      if (e) {
        e.preventDefault();
        e.stopPropagation();
      }
      
      if (!pin || pin.length !== 6) {
        setError('Please enter a valid 6-digit PIN');
        return;
      }
      
      setLoading(true);
      setError(null);
      setSuccess(null);

      try {
        const verifyUrl = `${SF_API_BASE}/api/auth/verify-pin`;
        const verifyResponse = await fetch(verifyUrl, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          credentials: 'include',
          body: JSON.stringify({
            email: email.trim(),
            pin: pin.trim(),
          }),
        });

        // Check if response is ok before parsing JSON
        if (!verifyResponse.ok) {
          // Try to parse error response
          let errorMessage = `Request failed (${verifyResponse.status})`;
          try {
            const errorData = await verifyResponse.json();
            errorMessage = errorData.error || errorData.message || errorMessage;
          } catch (e) {
            // If JSON parse fails, try to get text
            try {
              const errorText = await verifyResponse.text();
              if (errorText) {
                errorMessage = `${errorMessage}: ${errorText.substring(0, 200)}`;
              }
            } catch (e2) {
              // If all else fails, use status text
              errorMessage = `${errorMessage}: ${verifyResponse.statusText || 'Unknown error'}`;
            }
          }
          setError(errorMessage);
          return;
        }

        const verifyData = await verifyResponse.json();

        // ✅ PHASE 1 MIGRATION: Use new auth states format (state-based checks)
        if (verifyData.ok && verifyData.state === "AUTH_OK") {
          // Login successful - user approved
          // ✅ FIX: Store email for display only - NEVER use as identity
          localStorage.setItem('sylvanflow_display_email', email.trim()); // DISPLAY ONLY — NEVER USE AS IDENTITY
          // identity comes from auth.userKey ONLY
          // Identity comes from Bearer token only
          if (verifyData.session_token) {
            const prevTok = localStorage.getItem('sylvanflow_session_token');
            if (prevTok !== verifyData.session_token && window.SylvanFlowAuth?.clearSylvanClientChatSessionCache) {
              window.SylvanFlowAuth.clearSylvanClientChatSessionCache();
            }
            localStorage.setItem('sylvanflow_session_token', verifyData.session_token);
          }
          localStorage.setItem('sylvanflow_session', 'active');
          
          let legalAgreed = null;
          if (verifyData.session_token) {
            try {
              const statusRes = await fetch(`${window.SF_API_BASE || 'https://sf-api-gateway.foofiebean.workers.dev'}/api/legal/status`, {
                headers: {
                  Authorization: `Bearer ${verifyData.session_token}`
                }
              });
              if (statusRes.ok) {
                const statusData = await statusRes.json();
                const legalCurrent = window.SylvanFlowLegal && typeof window.SylvanFlowLegal.isLegalStatusCurrent === 'function'
                  ? window.SylvanFlowLegal.isLegalStatusCurrent(statusData)
                  : !!(statusData.ok && statusData.acknowledged && statusData.acknowledged_at);
                if (legalCurrent) {
                  legalAgreed = statusData.acknowledged_at;
                  localStorage.setItem('sylvanflow_legal_agreed', statusData.acknowledged_at);
                  if (window.uiLogger) {
                    window.uiLogger.uiLog('[LOGIN] PIN path: legal bundle current via /api/legal/status');
                  }
                } else {
                  localStorage.removeItem('sylvanflow_legal_agreed');
                }
              }
            } catch (e) {
              if (window.uiLogger) {
                window.uiLogger.uiWarn('[LOGIN] PIN path: /api/legal/status failed:', e.message);
              }
              legalAgreed = localStorage.getItem('sylvanflow_legal_agreed');
            }
          }
          
          if (!legalAgreed) {
            if (window.uiLogger) {
              window.uiLogger.uiLog('[LOGIN] Legal not current or missing — redirecting to /legal');
            }
            // Redirect to legal page with return URL to power-up
            // SF_ALLOW_HARDEXIT_REDIRECT
            window.location.href = '/legal?return=/power-up';
            return;
          }
          
          // ✅ AUTH FLOW: Set to loading — ensureAuthenticated routes complete profiles to NOW WHAT
          window.appState.set({
            view: 'loading',
            user: { email: email.trim() } // Email is display-only, identity from Bearer token
          });
          setLoading(false); // Clear login loading state
          
          if (window.ensureAuthenticated && typeof window.ensureAuthenticated === 'function') {
            if (window.uiLogger) {
              window.uiLogger.uiLog('[LOGIN] PIN verified - triggering ensureAuthenticated');
            }
            window.ensureAuthenticated('login_pin_success').catch((err) => {
              if (window.uiLogger) {
                window.uiLogger.uiError('[LOGIN] PIN verified - ensureAuthenticated error:', err.message || err);
              }
            });
          } else if (window.uiLogger) {
            window.uiLogger.uiWarn('[LOGIN] PIN verified - ensureAuthenticated not available, relying on app.js initialization');
          }
        } else if (verifyData.ok === false && verifyData.state === "AUTH_APPROVAL_PENDING") {
          // ✅ PHASE 1 MIGRATION: Use new auth states format (state-based checks)
          // ✅ BUG 2 FIX: Handle pending approval case
          // PIN verified but account pending admin approval
          setStep('pending');
          setSuccess(verifyData.message || 'PIN verified! Your account is pending admin approval. You will receive an email when approved.');
        } else {
          // ✅ PHASE 1 MIGRATION: Use message field instead of error field
          // PIN verification failed or other error
          setError(verifyData.message || verifyData.error || 'Invalid PIN. Please try again.');
        }
      } catch (err) {
        if (window.uiLogger) {
          window.uiLogger.uiError('PIN verification error:', err.message || err);
        }
        setError('Network error. Please check your connection and try again.');
      } finally {
        setLoading(false);
      }
    };

    const handleCreateAccount = async (e) => {
      // ✅ STEP 4: Verify form submission path
      if (window.uiLogger) {
        window.uiLogger.uiLog('[LOGIN-TRACE] handleCreateAccount called', {
          hasEvent: !!e,
          eventType: e?.type,
          eventTarget: e?.target?.tagName
        });
      }
      
      if (e) {
        e.preventDefault();
        e.stopPropagation();
        if (window.uiLogger) {
          window.uiLogger.uiLog('[LOGIN-TRACE] preventDefault() called ONCE (create account)');
        }
      }
      
      if (!email || !email.trim()) {
        // ✅ STEP 3: Expose early return (admin-only, sanitized)
        if (window.uiLogger) {
          window.uiLogger.uiWarn('[LOGIN-TRACE] EARLY RETURN TRIGGERED', {
            reason: 'email missing or empty (create account)',
            hasEmail: Boolean(email),
            emailLength: email?.length || 0
          });
        }
        setError('Please enter your email address');
        return;
      }
      
      setLoading(true);
      setError(null);
      setSuccess(null);
      setMode('create');

      try {
        const createUrl = `${SF_API_BASE}/api/auth/create-account`;
        
        // ✅ STEP 2: Add trace log before create-account call (admin-only, sanitized)
        if (window.uiLogger) {
          window.uiLogger.uiLog('[LOGIN-TRACE] About to call auth API', {
            endpoint: '/api/auth/create-account',
            isExistingUser: false,
            url: createUrl,
            hasEmail: !!email,
            emailLength: email?.trim().length || 0
          });
          
          // ✅ STEP 2: Add trace log as first line inside fetch
          window.uiLogger.uiLog('[LOGIN-TRACE] AUTH FETCH STARTED');
        }
        const createResponse = await fetch(createUrl, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          credentials: 'include',
          body: JSON.stringify({ email: email.trim() }),
        });

        // Check if response is ok before parsing JSON
        if (!createResponse.ok) {
          // Try to parse error response
          let errorMessage = `Request failed (${createResponse.status})`;
          try {
            const errorData = await createResponse.json();
            errorMessage = errorData.error || errorData.message || errorMessage;
          } catch (e) {
            // If JSON parse fails, try to get text
            try {
              const errorText = await createResponse.text();
              if (errorText) {
                errorMessage = `${errorMessage}: ${errorText.substring(0, 200)}`;
              }
            } catch (e2) {
              // If all else fails, use status text
              errorMessage = `${errorMessage}: ${createResponse.statusText || 'Unknown error'}`;
            }
          }
          setError(errorMessage);
          return;
        }

        const createData = await createResponse.json();

        // ✅ PHASE 1 MIGRATION: Use new auth states format (state-based checks with backward compatibility)
        if (createData.ok) {
          // Check for PIN sent (new format: state === "AUTH_PIN_SENT" OR legacy format: pin_sent === true)
          if (createData.state === "AUTH_PIN_SENT" || createData.pin_sent) {
            // PIN sent - move to PIN verification step
            setStep('pin');
            setSuccess(createData.message || 'PIN sent to your email. Please check your inbox and enter the PIN to complete account creation.');
          } else if (createData.state === "AUTH_OK") {
            // ✅ PHASE 1 MIGRATION: Account created and approved immediately (shouldn't happen with create-account, but handle it)
            // ✅ FIX: Store email for display only - NEVER use as identity
            localStorage.setItem('sylvanflow_display_email', email.trim()); // DISPLAY ONLY — NEVER USE AS IDENTITY
            // identity comes from auth.userKey ONLY
            // Identity comes from Bearer token only
            if (createData.session_token) {
              const prevTok = localStorage.getItem('sylvanflow_session_token');
              if (prevTok !== createData.session_token && window.SylvanFlowAuth?.clearSylvanClientChatSessionCache) {
                window.SylvanFlowAuth.clearSylvanClientChatSessionCache();
              }
              localStorage.setItem('sylvanflow_session_token', createData.session_token);
            }
            localStorage.setItem('sylvanflow_session', 'active');
            
            // Navigate to app via state (NO redirect)
            // identity comes from auth.userKey ONLY
            // user object is for display/metadata only, not for identity
            window.appState.set({
              view: 'explore',
              user: { email: email.trim() } // Email is display-only, identity from Bearer token
            });
          } else if (createData.state === "AUTH_APPROVAL_PENDING") {
            // ✅ PHASE 1 MIGRATION: Account created but pending approval
            setStep('pending');
            setSuccess(createData.message || 'Account created! Your account is pending admin approval. You will receive an email when approved.');
          } else {
            // Fallback: Account created but unknown state
            setStep('pending');
            setSuccess(createData.message || 'Account created! Your account is pending admin approval. You will receive an email when approved.');
          }
        } else {
          // ✅ PHASE 1 MIGRATION: Use message field, handle both legacy and new formats
          setError(createData.message || createData.error || 'Failed to create account. Please try again.');
        }
      } catch (err) {
        if (window.uiLogger) {
          window.uiLogger.uiError('Create account error:', err.message || err);
        }
        // Check if it's a CORS or network error
        if (err.name === 'TypeError' && err.message.includes('fetch')) {
          setError(`Network/CORS error: ${err.message}`);
        } else {
          setError(`Network error: ${err.message || 'Please check your connection and try again.'}`);
        }
      } finally {
        setLoading(false);
      }
    };

    return (
      <main
        id="sf-login-main"
        className={
          tc.pageCanvas ||
          'flex min-h-[100dvh] w-full flex-col items-center justify-center bg-black px-4 py-10 text-slate-100 sm:py-12 relative overflow-hidden'
        }
        aria-labelledby="login-title"
      >
        <style
          dangerouslySetInnerHTML={{
            __html:
              '.sf-login-shell{animation:sf-login-card-enter .55s cubic-bezier(.22,1,.36,1) both}' +
              '@media (prefers-reduced-motion:reduce){.sf-login-shell{animation:none!important}}'
          }}
        />

        {/* Ambient layers */}
        <div
          className={
            tc.ambientBlobTL ||
            'pointer-events-none absolute -left-24 -top-24 h-72 w-72 rounded-full bg-cyan-500/15 blur-3xl'
          }
          aria-hidden
        />
        <div
          className={
            tc.ambientBlobBR ||
            'pointer-events-none absolute -bottom-28 -right-20 h-80 w-80 rounded-full bg-teal-500/12 blur-3xl'
          }
          aria-hidden
        />
        <div
          className="pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_85%_55%_at_50%_-15%,rgba(45,226,197,0.14),transparent_58%)]"
          aria-hidden
        />
        <div
          className="pointer-events-none absolute inset-0 opacity-[0.035] [background-image:linear-gradient(rgba(255,255,255,0.14)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.11)_1px,transparent_1px)] [background-size:28px_28px]"
          aria-hidden
        />

        <div
          className={
            tc.loginCard ||
            'sf-login-shell w-full max-w-md rounded-2xl border border-cyan-400/15 bg-[#0c1018]/95 p-6 sm:p-9 shadow-[0_20px_60px_-20px_rgba(0,0,0,0.88)] backdrop-blur-md'
          }
        >
          <div className="mb-6 text-center">
            <div
              className={
                tc.loginLogoPlate ||
                'relative mx-auto mb-6 flex min-h-[88px] min-w-[88px] max-w-[200px] items-center justify-center rounded-2xl bg-[radial-gradient(ellipse_at_50%_35%,rgba(45,226,197,0.14)_0%,rgba(7,11,18,1)_58%)] px-5 py-4 ring-1 ring-cyan-400/25 shadow-[0_0_44px_-16px_rgba(45,226,197,0.5)] sm:min-h-[96px]'
              }
            >
              <img
                src="/assets/sylvanflow-logo.png"
                alt="SylvanFlow"
                width={120}
                height={120}
                className="h-auto max-h-[56px] w-auto max-w-[min(100%,10rem)] object-contain opacity-[0.98] sm:max-h-[64px]"
                onError={(e) => {
                  e.target.style.display = 'none';
                }}
              />
            </div>
            <h1
              id="login-title"
              className="text-2xl font-bold tracking-tight text-white sm:text-[1.65rem]"
            >
              Welcome
            </h1>
            <p className={tc.loginTaglineOneLine || 'mx-auto mt-2 max-w-[18rem] text-center text-sm leading-snug text-slate-400'}>
              Email sign-in · one-time code when needed
            </p>
          </div>

          {error && (
            <div
              className={
                tc.alertError ||
                'mb-4 rounded-xl border border-rose-500/35 bg-rose-950/50 p-3 text-sm text-rose-100'
              }
              role="alert"
            >
              <p className="text-sm">{error}</p>
            </div>
          )}

          {success && (
            <div
              className={
                tc.alertSuccess ||
                'mb-4 rounded-xl border border-emerald-500/35 bg-emerald-950/40 p-3 text-sm text-emerald-100'
              }
              role="status"
            >
              <p className="text-sm">{success}</p>
            </div>
          )}

          {step === 'email' && (
            <div className="space-y-5">
              <button
                type="button"
                onClick={handleGoogleSignIn}
                disabled={loading || googleBusy}
                className={
                  tc.btnGoogle ||
                  'inline-flex min-h-[44px] w-full items-center justify-center gap-2.5 rounded-xl border border-white/10 bg-white/[0.04] text-sm font-medium text-slate-200 transition hover:border-white/15 hover:bg-white/[0.07] focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300/40 focus-visible:ring-offset-2 focus-visible:ring-offset-[#0c1018] disabled:cursor-not-allowed disabled:opacity-40'
                }
              >
                {!googleBusy ? <GoogleSignInIcon className="h-[18px] w-[18px] shrink-0" /> : null}
                <span className={tc.btnGoogleLabel || 'text-[13px] font-medium text-white'}>
                  {googleBusy ? 'Redirecting to Google…' : 'Continue with Google'}
                </span>
              </button>

              <div className="flex items-center gap-3 text-xs text-slate-500">
                <span className="h-px flex-1 bg-white/10" aria-hidden />
                <span>or sign up with email</span>
                <span className="h-px flex-1 bg-white/10" aria-hidden />
              </div>

              <div>
                <label className={tc.label || 'mb-1 block text-sm font-medium text-cyan-100/85'} htmlFor="login-email">
                  Email
                </label>
                <input
                  id="login-email"
                  type="email"
                  name="email"
                  autoComplete="email"
                  inputMode="email"
                  value={email}
                  onChange={(e) => setEmail(e.target.value)}
                  placeholder="you@example.com"
                  aria-invalid={error ? 'true' : 'false'}
                  className={tc.input || 'w-full rounded-xl border border-cyan-400/30 bg-white/5 px-4 py-3.5 text-base text-white placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-400/55 focus:ring-offset-2 focus:ring-offset-[#0c1018]'}
                  disabled={loading}
                />
              </div>

              <div className="flex flex-col gap-4">
                <button
                  type="button"
                  onClick={(e) => handleEmailSubmit(e, 'login')}
                  disabled={loading || !email.trim()}
                  className={
                    tc.btnPrimaryLogin ||
                    tc.btnPrimaryFull ||
                    'min-h-[48px] w-full rounded-xl bg-gradient-to-r from-teal-400 to-cyan-400 font-semibold text-[#042f2e] shadow-[0_0_28px_-8px_rgba(45,226,197,0.7)] transition hover:brightness-110 focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 focus-visible:ring-offset-2 focus-visible:ring-offset-[#0c1018] disabled:cursor-not-allowed disabled:opacity-40 motion-safe:active:scale-[0.99]'
                  }
                >
                  {loading && mode === 'login' ? 'Signing in…' : 'Continue'}
                </button>
                <div className="text-center">
                  <button
                    type="button"
                    onClick={(e) => handleCreateAccount(e)}
                    disabled={loading || !email.trim()}
                    className={
                      tc.loginCreateLink ||
                      'text-center text-sm font-medium text-cyan-400/90 underline-offset-4 transition hover:text-cyan-300 hover:underline disabled:cursor-not-allowed disabled:opacity-40'
                    }
                  >
                    {loading && mode === 'create' ? 'Creating…' : 'Create an account'}
                  </button>
                </div>
              </div>

              <nav
                className={
                  tc.loginFooterLinks ||
                  'mt-8 flex flex-wrap items-center justify-center gap-x-3 gap-y-1 border-t border-white/[0.08] pt-5 text-[11px] text-slate-500'
                }
                aria-label="Legal"
              >
                <a href="/policies#privacy" className="transition hover:text-slate-300 focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-400/40 focus-visible:ring-offset-2 focus-visible:ring-offset-[#0c1018] rounded">
                  Privacy
                </a>
                <span className="text-slate-600" aria-hidden>
                  ·
                </span>
                <a href="/policies#terms" className="transition hover:text-slate-300 focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-400/40 focus-visible:ring-offset-2 focus-visible:ring-offset-[#0c1018] rounded">
                  Terms
                </a>
              </nav>
            </div>
          )}

          {step === 'pin' && (
            <div className="space-y-5">
              <p className="text-center text-sm text-slate-400">Enter the code from your email.</p>
              <div>
                <label className={tc.label || 'mb-1 block text-sm font-medium text-cyan-100/85'} htmlFor="login-pin">
                  One-time code
                </label>
                <input
                  id="login-pin"
                  type="text"
                  inputMode="numeric"
                  pattern="[0-9]*"
                  autoComplete="one-time-code"
                  value={pin}
                  onChange={(e) => {
                    const value = e.target.value.replace(/\D/g, '').slice(0, 6);
                    setPin(value);
                  }}
                  placeholder="• • • • • •"
                  maxLength={6}
                  aria-invalid={error ? 'true' : 'false'}
                  className={
                    tc.inputCenter ||
                    'w-full rounded-xl border border-cyan-400/30 bg-white/5 px-4 py-3.5 text-center text-2xl tracking-[0.35em] text-white placeholder:text-slate-600 focus:outline-none focus:ring-2 focus:ring-cyan-400/55 focus:ring-offset-2 focus:ring-offset-[#0c1018]'
                  }
                  disabled={loading}
                  autoFocus
                />
              </div>

              <button
                type="button"
                onClick={handlePinSubmit}
                disabled={loading || pin.length !== 6}
                className={
                  tc.btnPrimaryLogin ||
                  tc.btnPrimaryFull ||
                  'min-h-[48px] w-full rounded-xl bg-gradient-to-r from-teal-400 to-cyan-400 font-semibold text-[#042f2e] shadow-[0_0_28px_-8px_rgba(45,226,197,0.7)] transition hover:brightness-110 focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 focus-visible:ring-offset-2 focus-visible:ring-offset-[#0c1018] disabled:cursor-not-allowed disabled:opacity-40'
                }
              >
                {loading ? 'Verifying…' : 'Verify & continue'}
              </button>

              <button
                type="button"
                onClick={() => {
                  setStep('email');
                  setPin('');
                  setError(null);
                  setSuccess(null);
                }}
                className={
                  tc.btnGhost ||
                  'min-h-[44px] w-full rounded-xl border border-white/10 bg-white/5 font-semibold text-slate-200 transition hover:bg-white/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-white/20'
                }
              >
                Use a different email
              </button>
            </div>
          )}

          {step === 'pending' && (
            <div className="space-y-5 text-center">
              <div
                className="mx-auto flex h-14 w-14 items-center justify-center rounded-2xl border border-amber-400/25 bg-amber-950/30 text-2xl shadow-[0_0_32px_-10px_rgba(251,191,36,0.45)]"
                aria-hidden
              >
                ⏳
              </div>
              <h2 className="text-lg font-semibold text-white sm:text-xl">Approval pending</h2>
              <p className="text-sm leading-relaxed text-slate-400">
                Your account is in line for review. We’ll email you when you can sign in.
              </p>
              <button
                type="button"
                onClick={() => {
                  setStep('email');
                  setEmail('');
                  setPin('');
                  setError(null);
                  setSuccess(null);
                }}
                className={
                  tc.btnGhost ||
                  'min-h-[44px] w-full rounded-xl border border-white/10 bg-white/5 font-semibold text-slate-200 transition hover:bg-white/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-white/20'
                }
              >
                Back to sign in
              </button>
            </div>
          )}
        </div>
      </main>
    );
  }

  // Export component
  if (typeof window !== 'undefined') {
    window.LoginPage = LoginPage;
  }
})();

