// WeWire applicant — root router + email auth + Supabase persistence.

function ScreenApplicationsClosed({ onResume, applyClose }) {
  return (
    <div style={{ minHeight: '100%', height: '100%', background: WW.ink, display: 'flex', flexDirection: 'column',
      padding: '64px 24px 36px', boxSizing: 'border-box', color: WW.cream, position: 'relative', overflow: 'hidden' }}>
      <img src="../assets/wewire-logo-cream.svg" alt="WeWire" style={{ height: 26, position: 'relative', display: 'block' }} />
      <div style={{ flex: 1 }} />
      <Eyebrow color="rgba(251,247,240,0.6)">Applications closed</Eyebrow>
      <h1 style={{ fontFamily: DISP, fontWeight: 600, fontSize: 36, lineHeight: 1.1, letterSpacing: '-0.03em', margin: '16px 0 14px' }}>
        The window for new applications has closed.
      </h1>
      <p style={{ fontSize: 16, lineHeight: 1.55, color: 'rgba(251,247,240,0.72)', maxWidth: 320 }}>
        Applications closed {applyClose || '24 July 2026'}. If you already started, sign in to view your progress.
      </p>
      <div style={{ flex: 1 }} />
      <Btn variant="primary" full onClick={onResume} icon="arrow" style={{ marginBottom: 14 }}>Sign in to continue</Btn>
      <div style={{ textAlign: 'center' }}>
        <a href={WWPaths.program()} style={{ fontSize: 13, color: 'rgba(251,247,240,0.6)', textDecoration: 'none' }}>← Program site</a>
      </div>
    </div>
  );
}

function App() {
  const { STAGES, PROGRAM } = window.WWData;
  const viewport = window.WWViewport?.useViewport?.() || { isMobile: window.innerWidth < 768 };

  const [booting, setBooting] = React.useState(true);
  const [ready, setReady] = React.useState(false);
  const [authed, setAuthed] = React.useState(false);
  const [applicationsOpen, setApplicationsOpen] = React.useState(true);
  const [authEmail, setAuthEmail] = React.useState('');
  const [authMode, setAuthMode] = React.useState('new');
  const [devHint, setDevHint] = React.useState(null);

  const [screen, setScreen] = React.useState('welcome');
  const [done, setDone] = React.useState(0);
  const [name, setName] = React.useState('');
  const [stageIdx, setStageIdx] = React.useState(0);
  const [form, setForm] = React.useState(null);
  const [formStep, setFormStep] = React.useState(0);
  const [scores, setScores] = React.useState({});
  const [applicantStatus, setApplicantStatus] = React.useState('in_progress');
  const leaveGuardRef = React.useRef(null);

  const refreshScores = React.useCallback(async () => {
    if (!window.WWApplicant?.getStageScores) return {};
    try {
      const s = await window.WWApplicant.getStageScores();
      setScores(s);
      return s;
    } catch (err) {
      console.warn('Could not load scores:', err.message);
      return {};
    }
  }, []);

  const applySession = (session) => {
    if (!session) return;
    setAuthEmail(session.email);
    setScreen(session.screen || 'home');
    setDone(session.done || 0);
    setName(session.name || '');
    setStageIdx(session.stageIdx || 0);
    setFormStep(session.formStep || 0);
    setForm(session.form || null);
    if (session.status) setApplicantStatus(session.status);
  };

  const persist = React.useCallback((patch) => {
    if (!authed) return;
    WWAuth.saveSession(patch).catch((err) => console.warn('Save failed:', err.message));
  }, [authed]);

  React.useEffect(() => {
    (async () => {
      try {
        if (WWAuth.useSupabase && WWAuth.useSupabase()) {
          const open = await window.WWApplicant.isApplicationsOpen();
          setApplicationsOpen(open);

          const sb = window.WWSupabase.getClient();
          const { data: { session: authSession } } = await sb.auth.getSession();
          if (authSession) {
            WWAuth.setAuth(authSession.access_token, authSession.user.email);
            const appSession = await WWAuth.loadSession();
            applySession(appSession);
            await refreshScores();
            setAuthed(true);
            setBooting(false);
            setReady(true);
            return;
          }
        } else {
          const magic = WWAuth.consumeMagicLinkToken();
          if (magic) {
            const data = await WWAuth.resumeWithToken(magic);
            applySession(data.session);
            setAuthed(true);
            setBooting(false);
            setReady(true);
            return;
          }
          const session = await WWAuth.loadSession();
          if (session) {
            applySession(session);
            setAuthed(true);
            setBooting(false);
            setReady(true);
            return;
          }
        }
      } catch (err) {
        console.warn('Session restore failed:', err.message);
        WWAuth.clearAuth();
      }
      setAuthed(false);
      setBooting(false);
      setReady(true);
    })();
  }, []);

  React.useEffect(() => {
    if (!ready || booting || !authed) return;
    persist({ screen, done, name, stageIdx, formStep, form });
  }, [ready, booting, authed, screen, done, name, stageIdx, formStep, form, persist]);

  React.useEffect(() => {
    if (!authed || screen !== 'home') return;
    (async () => {
      try {
        const session = await WWAuth.loadSession();
        if (session?.status) setApplicantStatus(session.status);
        await refreshScores();
      } catch (err) {
        console.warn('Refresh failed:', err.message);
      }
    })();
  }, [authed, screen, refreshScores]);

  const signOut = async () => {
    await WWAuth.clearAuth();
    setAuthed(false);
    setAuthEmail('');
    setScreen('welcome');
    setDone(0);
    setName('');
    setStageIdx(0);
    setForm(null);
    setFormStep(0);
    setScores({});
    setApplicantStatus('in_progress');
    setDevHint(null);
    setReady(true);
  };

  const handleVerified = async (session) => {
    applySession(session);
    await refreshScores();
    setAuthed(true);
    setDevHint(null);
    setReady(true);
  };

  const openStage = (i) => {
    if (!WWFunnel.canOpenStage(i, { done, scores, status: applicantStatus })) return;
    if (i === 0 && done > 0) setFormStep(0);
    setStageIdx(i);
    setScreen('stage');
  };

  const completeStage = async (i) => {
    const nextDone = Math.max(done, i + 1);

    if (i === 4) {
      let evaluation = null;
      try {
        if (window.WWApplicant?.runMilestone1Gate) {
          evaluation = await window.WWApplicant.runMilestone1Gate();
        } else {
          const latest = await refreshScores();
          evaluation = window.WWFunnel?.evaluateMilestone1
            ? window.WWFunnel.evaluateMilestone1(latest)
            : { passed: true, scores: latest };
        }
      } catch (err) {
        console.warn('Milestone gate re-check failed:', err.message);
      }

      if (evaluation?.scores) setScores(evaluation.scores);

      if (evaluation && !evaluation.passed) {
        setDone(nextDone);
        setApplicantStatus('rejected');
        setScreen('home');
        persist({ done: nextDone, screen: 'home', status: 'rejected' });
        return;
      }

      setDone(nextDone);
      setScreen('home');
      setApplicantStatus('advancing');
      persist({ done: nextDone, screen: 'home', status: 'advancing' });
      return;
    }

    if (i === 6) {
      setDone(nextDone);
      setScreen('home');
      setApplicantStatus('in_review');
      persist({ done: nextDone, screen: 'home', status: 'in_review' });
      return;
    }

    setDone(nextDone);
    setScreen('home');
    persist({ done: nextDone, screen: 'home' });
  };

  const handleMilestone1Evaluated = React.useCallback((evaluation) => {
    if (!evaluation) return;
    if (evaluation.scores) setScores(evaluation.scores);
    const nextDone = window.WWFunnel?.FUNNEL?.milestone1Count ?? 5;
    setDone(nextDone);
    if (!evaluation.passed) {
      setApplicantStatus('rejected');
      persist({ done: nextDone, status: 'rejected' });
    } else {
      setApplicantStatus('advancing');
      persist({ done: nextDone, status: 'advancing' });
    }
  }, [persist]);

  const handleMilestone2Submitted = React.useCallback(() => {
    setApplicantStatus('in_review');
    persist({ status: 'in_review' });
  }, [persist]);

  window.__resetWW = () => { WWAuth.clearAuth(); location.reload(); };

  if (booting) {
    return wrap(<ScreenAuthLoading />);
  }

  let body, label;

  if (!authed) {
    if (!applicationsOpen && screen !== 'auth-email' && screen !== 'auth-verify') {
      label = 'Closed';
      body = (
        <ScreenApplicationsClosed
          applyClose={PROGRAM.applyClose}
          onResume={() => { setAuthMode('resume'); setScreen('auth-email'); }}
        />
      );
    } else if (screen === 'auth-verify') {
      label = 'Verify email';
      body = (
        <ScreenAuthVerify
          email={authEmail}
          devHint={devHint}
          onVerified={handleVerified}
          onBack={() => setScreen('auth-email')}
          onResend={() => {}}
        />
      );
    } else if (screen === 'auth-email') {
      label = 'Sign in';
      body = (
        <ScreenAuthEmail
          mode={authMode}
          onBack={() => setScreen(applicationsOpen ? 'welcome' : 'welcome')}
          onSent={(email, res) => {
            setAuthEmail(email);
            setDevHint(res.dev || null);
            setScreen('auth-verify');
          }}
        />
      );
    } else if (!applicationsOpen) {
      label = 'Closed';
      body = (
        <ScreenApplicationsClosed
          applyClose={PROGRAM.applyClose}
          onResume={() => { setAuthMode('resume'); setScreen('auth-email'); }}
        />
      );
    } else {
      label = 'Welcome';
      body = (
        <ScreenWelcome
          onBegin={() => { setAuthMode('new'); setScreen('auth-email'); }}
          onResume={() => { setAuthMode('resume'); setScreen('auth-email'); }}
          applyClose={PROGRAM.applyClose}
          daysLeft={WWProgram.daysUntilClose()}
        />
      );
    }
  } else if (screen === 'home') {
    label = 'Status tracker';
    body = (
      <ScreenHome
        name={name}
        email={authEmail || WWAuth.getEmail()}
        done={done}
        scores={scores}
        status={applicantStatus}
        onOpenStage={openStage}
        onSignOut={signOut}
        applicationsOpen={applicationsOpen}
      />
    );
  } else if (screen === 'stage') {
    const stage = STAGES[stageIdx];
    label = stage.name;
    if (stage.kind === 'form') {
      body = (
        <ApplicationForm
          initialForm={form}
          initialStep={formStep}
          authEmail={authEmail || WWAuth.getEmail()}
          onFormChange={(f) => setForm(f)}
          onFormStepChange={(s) => setFormStep(s)}
          onName={(n) => setName(n)}
          onBack={goHome}
          onComplete={() => completeStage(0)}
          applicationsOpen={applicationsOpen}
        />
      );
    } else {
      body = (
        <StageFlow
          stage={stage}
          applicantEmail={authEmail || WWAuth.getEmail()}
          scores={scores}
          onScoresChange={refreshScores}
          onMilestone1Evaluated={handleMilestone1Evaluated}
          onMilestone2Submitted={handleMilestone2Submitted}
          onBindGuard={(fn) => { leaveGuardRef.current = fn; }}
          onBack={goHome}
          onComplete={() => completeStage(stageIdx)}
          applicationsOpen={applicationsOpen}
        />
      );
    }
  } else {
    body = (
      <ScreenHome
        name={name}
        email={authEmail || WWAuth.getEmail()}
        done={done}
        scores={scores}
        status={applicantStatus}
        onOpenStage={openStage}
        onSignOut={signOut}
        applicationsOpen={applicationsOpen}
      />
    );
    label = 'Status tracker';
  }

  function goHome() {
    if (leaveGuardRef.current && leaveGuardRef.current() === false) return;
    setScreen('home');
  }

  function resolveShell() {
    const force = window.WW_SHELL;
    if (force === 'device') return 'device';
    if (force === 'web') return 'web';
    return viewport.isMobile ? 'mobile' : 'web';
  }

  function wrap(content) {
    const shell = resolveShell();
    const email = authEmail || WWAuth.getEmail();
    const labelAttr = shell === 'device' ? 'Applicant · ' : shell === 'web' ? 'Applicant (web) · ' : 'Applicant · ';

    if (shell === 'web') {
      return (
        <div data-screen-label={labelAttr + (label || '')}>
          <WebShell email={email} onSignOut={authed ? signOut : null}>{content}</WebShell>
        </div>
      );
    }
    if (shell === 'mobile') {
      return (
        <div data-screen-label={labelAttr + (label || '')}>
          <MobileShell email={email} onSignOut={authed ? signOut : null}>{content}</MobileShell>
        </div>
      );
    }
    return (
      <div className="stage-wrap" data-screen-label={labelAttr + (label || '')}>
        <IOSDevice width={390} height={844}>{content}</IOSDevice>
      </div>
    );
  }

  return wrap(body);
}

function MobileShell({ children, email, onSignOut }) {
  return (
    <div style={{ minHeight: '100dvh', height: '100dvh', display: 'flex', flexDirection: 'column', background: WW.cream }}>
      <header style={{ flex: 'none', minHeight: 52, padding: 'max(10px, env(safe-area-inset-top)) 16px 10px',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        borderBottom: `1px solid ${WW.line}`, background: WW.white }}>
        <img src="../assets/wewire-logo-ink.svg" alt="WeWire" style={{ height: 22, display: 'block' }} />
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          {onSignOut && (
            <button type="button" onClick={onSignOut} style={{ background: 'none', border: 'none', cursor: 'pointer',
              fontSize: 13, fontWeight: 600, color: WW.muted, fontFamily: FONT }}>Sign out</button>
          )}
        </div>
      </header>
      <main style={{ flex: 1, overflow: 'hidden', position: 'relative', width: '100%' }}>{children}</main>
    </div>
  );
}

function WebShell({ children, email, onSignOut }) {
  return (
    <div style={{ height: '100vh', display: 'flex', flexDirection: 'column', background: WW.sand }}>
      <header style={{ height: 64, flex: 'none', background: WW.white, borderBottom: `1px solid ${WW.line}`,
        display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 22px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 11 }}>
          <img src="../assets/wewire-logo-ink.svg" alt="WeWire" style={{ height: 24, display: 'block' }} />
          <span style={{ fontSize: 12.5, color: WW.muted, fontWeight: 600, borderLeft: `1px solid ${WW.lineStrong}`, paddingLeft: 11 }}>Graduate Application</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
          {email && (
            <span style={{ fontSize: 12, color: WW.subtle, fontWeight: 600, maxWidth: 160, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={email}>
              {email}
            </span>
          )}
          {onSignOut && (
            <button type="button" onClick={onSignOut} style={{ background: 'none', border: 'none', cursor: 'pointer',
              fontSize: 13, fontWeight: 600, color: WW.muted, fontFamily: FONT }}>Sign out</button>
          )}
          <a href={WWPaths.program()} style={{ fontSize: 13, fontWeight: 600, color: WW.muted, textDecoration: 'none' }}>Program site ↗</a>
        </div>
      </header>
      <main style={{ flex: 1, display: 'flex', justifyContent: 'center', overflow: 'hidden', padding: '0 24px' }}>
        <div style={{ width: '100%', maxWidth: 720, height: '100%', position: 'relative', overflow: 'hidden',
          background: WW.cream, boxShadow: '0 0 60px rgba(27,24,19,0.10)', borderRadius: '0 0 4px 4px' }}>
          {children}
        </div>
      </main>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
