// Main app — wires screens together with state

const { useState: useS, useEffect: useE } = React;

// ── Hash-based routing ────────────────────────────────────────────────
//
// URL fragment is the source of truth. Mapping:
//   ''                 → home
//   '/'                → home
//   '/workapps'        → directory
//   '/w/<slug>'        → detail        (params.slug)
//   '/experts'         → experts
//   '/experts/<s>'     → expert        (params.expertSlug)
//   '/about'           → about
//   '/become'          → become
//   '/auth'            → auth
//   '/my-runs'         → myruns
//   '/account'         → account
//   '/run/<id>'        → streaming     (params.runId)
//   '/run/<id>/result' → result        (params.runId)
//
// setView(view, extraParams) bridges existing callsites to navigateTo(),
// which sets window.location.hash. parseHash() reads the hash on hashchange.

function parseHash() {
  const raw = (window.location.hash || '').replace(/^#/, '').replace(/^\//, '');
  const segs = raw.split('/').filter(Boolean);
  if (segs.length === 0) return { view: 'home', params: {} };
  if (segs[0] === 'workapps') return { view: 'directory', params: {} };
  if (segs[0] === 'w' && segs[1]) return { view: 'detail', params: { slug: segs[1] } };
  if (segs[0] === 'experts' && !segs[1]) return { view: 'experts', params: {} };
  if (segs[0] === 'experts' && segs[1]) return { view: 'expert', params: { expertSlug: segs[1] } };
  if (segs[0] === 'about') return { view: 'about', params: {} };
  if (segs[0] === 'privacy') return { view: 'privacy', params: {} };
  if (segs[0] === 'terms') return { view: 'terms', params: {} };
  if (segs[0] === 'become') return { view: 'become', params: {} };
  if (segs[0] === 'auth') return { view: 'auth', params: {} };
  if (segs[0] === 'my-runs') return { view: 'myruns', params: {} };
  if (segs[0] === 'account') return { view: 'account', params: {} };
  if (segs[0] === 'run' && segs[1] && segs[2] === 'result') return { view: 'result', params: { runId: segs[1] } };
  if (segs[0] === 'run' && segs[1]) return { view: 'streaming', params: { runId: segs[1] } };
  if (segs[0] === 'r' && segs[1]) return { view: 'shared-result', params: { token: segs[1] } };
  if (segs[0] === 'marketplace') return { view: 'marketplace', params: {} };
  if (segs[0] === 'publish' && segs[1]) {
    // Tolerate an optional `?t=<token>` after the workapp id (the publish
    // token minted by the draft_marketplace_content MCP tool).
    const [wid, query] = segs[1].split('?');
    const tokenMatch = (query || '').match(/(?:^|&)t=([^&]+)/);
    const token = tokenMatch ? decodeURIComponent(tokenMatch[1]) : undefined;
    return { view: 'publish', params: { workappId: wid, token: token } };
  }
  return { view: 'home', params: {} };
}

function navigateTo(path) {
  window.location.hash = '#' + (path.startsWith('/') ? path : '/' + path);
}

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "aesthetic": "warm",
  "density": "comfortable",
  "accent": "#111111",
  "signedIn": false,
  "simulateError": false
}/*EDITMODE-END*/;

const ACCENT_OPTIONS = [
  '#111111',  // monochrome (default)
  '#54b879',  // status green
  '#6f95ff',  // action blue
  '#9b7cff',  // workflow purple
  '#72bdd0',  // signal cyan
];

function InternalNav({ current, resultState, signedIn, authMode, errorVariant, simulateError, signInModalOpen, shareModalOpen, onJump }) {
  const groups = [
    {
      label: 'Core loop',
      items: [
        ['home', 'Homepage'],
        ['home-alt', 'Homepage alt'],
        ['directory', 'WorkApps'],
        ['detail', 'WorkApp detail'],
        ['input', 'Run input'],
        ['streaming', 'Streaming'],
        ['streaming-error', 'Streaming error'],
        ['result', 'Result'],
      ],
    },
    {
      label: 'Result states',
      items: [
        ['result-shared', 'Shared'],
        ['result-outreach', 'Outreach'],
      ],
    },
    {
      label: 'Discovery',
      items: [
        ['experts', 'Experts'],
        ['expert', 'Expert profile'],
        ['about', 'About'],
        ['become', 'For experts'],
      ],
    },
    {
      label: 'Account states',
      items: [
        ['myruns-locked', 'My runs locked'],
        ['myruns', 'My runs signed in'],
        ['account-locked', 'Account locked'],
        ['account', 'Account signed in'],
        ['auth-signin', 'Auth sign in'],
        ['auth-signup', 'Auth sign up'],
      ],
    },
    {
      label: 'Errors',
      items: [
        ['error-unreachable', 'Unreachable'],
        ['error-paywall', 'Paywall'],
        ['error-blocked', 'Blocked'],
        ['error-thin', 'Thin content'],
      ],
    },
    {
      label: 'Modals',
      items: [
        ['modal-signin', 'Sign-in modal'],
        ['modal-share', 'Share modal'],
      ],
    },
  ];

  const activeKey = shareModalOpen ? 'modal-share'
    : signInModalOpen ? 'modal-signin'
    : current === 'streaming' && simulateError ? 'streaming-error'
    : current === 'auth' ? `auth-${authMode}`
    : current === 'error' ? `error-${errorVariant}`
    : current === 'myruns' && !signedIn ? 'myruns-locked'
    : current === 'account' && !signedIn ? 'account-locked'
    : current === 'result' && resultState === 'shared' ? 'result-shared'
    : current === 'result' && resultState === 'outreach' ? 'result-outreach'
    : current;

  return (
    <div className="internal-nav" aria-label="Internal prototype navigation">
      <div className="internal-nav-inner">
        <div className="internal-nav-head">
          <div>
            <div className="internal-nav-kicker">Internal nav</div>
            <h2>Prototype pages & states</h2>
          </div>
          <div className="internal-nav-status">
            Current: <b>{activeKey}</b>
          </div>
        </div>
        <div className="internal-nav-groups">
          {groups.map((group) => (
            <div className="internal-nav-group" key={group.label}>
              <div className="internal-nav-label">{group.label}</div>
              <div className="internal-nav-links">
                {group.items.map(([key, label]) => (
                  <button
                    key={key}
                    type="button"
                    className={'internal-nav-link' + (activeKey === key ? ' active' : '')}
                    onClick={() => onJump(key)}
                  >
                    {label}
                  </button>
                ))}
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

function App() {
  // Hash-driven route state (sharable URLs).
  const [route, setRoute] = useS(parseHash);
  useE(() => {
    const onHash = () => setRoute(parseHash());
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  const { view, params } = route;
  // Bridge: existing setView('detail') callsites stay; setView now mirrors
  // to the hash. Optional second arg passes route params for view types
  // that need them (slug, runId, expertSlug).
  const setView = (v, extraParams) => {
    if (v === 'detail' && extraParams && extraParams.slug) return navigateTo('/w/' + extraParams.slug);
    if (v === 'expert' && extraParams && extraParams.expertSlug) return navigateTo('/experts/' + extraParams.expertSlug);
    if (v === 'streaming' && extraParams && extraParams.runId) return navigateTo('/run/' + extraParams.runId);
    if (v === 'result' && extraParams && extraParams.runId) return navigateTo('/run/' + extraParams.runId + '/result');
    const map = {
      home: '/', 'home-alt': '/', directory: '/workapps',
      experts: '/experts', about: '/about', become: '/become',
      auth: '/auth', myruns: '/my-runs', account: '/account',
      // Fallbacks for views that need params we don't have here — stay on
      // current hash by re-using the existing route segment if any.
      detail: '/workapps', expert: '/experts', streaming: '/', result: '/',
      input: '/', error: '/',
    };
    return navigateTo(map[v] || '/');
  };
  const [resultState, setResultState] = useS('standard'); // standard | shared | outreach
  const [authMode, setAuthMode] = useS('signin');
  const [errorVariant, setErrorVariant] = useS('unreachable');
  const [inputs, setInputs] = useS(null);
  const [selectedExpert, setSelectedExpert] = useS(EXPERT);
  const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS);

  const [user, setUser] = useS(null);

  useE(() => {
    if (!window.AppData || !window.AppData.me) return;
    let cancelled = false;
    window.AppData.me()
      .then(function(u) {
        if (!cancelled) {
          setUser(u);
          if (u) localStorage.removeItem('sb_guest_id');
        }
      })
      .catch(function() { if (!cancelled) setUser(null); });
    return function() { cancelled = true; };
  }, []);

  const signedIn = !!user;

  const [qualificationModal, setQualificationModal] = useS(false);
  const [signInModal, setSignInModal] = useS({ open: false, reason: '' });
  const [shareModal, setShareModal] = useS(false);
  const [toast, setToast] = useS('');

  // Apply aesthetic + density to root
  useE(() => {
    document.body.dataset.aesthetic = t.aesthetic;
    document.body.dataset.density = t.density;
    document.documentElement.style.setProperty('--accent', t.accent);
    const darken = (hex) => {
      const m = hex.match(/^#([0-9a-f]{6})$/i);
      if (!m) return hex;
      const n = parseInt(m[1], 16);
      const r = Math.max(0, ((n >> 16) & 255) - 30);
      const g = Math.max(0, ((n >> 8) & 255) - 30);
      const b = Math.max(0, (n & 255) - 30);
      return `#${[r, g, b].map(v => v.toString(16).padStart(2, '0')).join('')}`;
    };
    document.documentElement.style.setProperty('--accent-ink', darken(t.accent));
  }, [t.aesthetic, t.density, t.accent]);

  // Toast auto-dismiss
  useE(() => {
    if (!toast) return;
    const x = setTimeout(() => setToast(''), 2200);
    return () => clearTimeout(x);
  }, [toast]);

  useE(() => {
    window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
  }, [view, resultState, authMode, errorVariant]);

  const showToast = (m) => setToast(m);

  useE(() => {
    if (signedIn && window.sessionStorage?.getItem('pendingQualification') === '1') {
      setQualificationModal(true);
    }
  }, [signedIn]);

  const openAccountQualification = () => {
    window.sessionStorage?.setItem('pendingQualification', '1');
    setQualificationModal(true);
  };
  const closeQualification = () => {
    window.sessionStorage?.removeItem('pendingQualification');
    setQualificationModal(false);
  };
  const requireAuth = function(reason) {
    // Redirect to WorkOS hosted login, preserving current URL for return
    window.AppData.redirectToLogin();
  };
  const doSignIn = function() { window.AppData.redirectToLogin(); };
  const completeQualification = () => {
    closeQualification();
    showToast('Profile saved — welcome.');
  };
  const doSignOut = function() {
    fetch('/logout', { method: 'POST', credentials: 'include', headers: { 'x-csrf-token': '1' } })
      .finally(function() { setUser(null); navigateTo('/'); });
    closeQualification();
    showToast('Signed out');
  };

  const goHome = () => setView('home');
  // Kick off a real run via the API, then navigate to /run/<runId>. The
  // StreamingScreen subscribes to SSE off runId; workappSlug is recovered
  // via getRun() server-side so direct URL visits also work.
  const startRunAndNavigate = (data) => {
    if (!data) return;
    setInputs(data);
    const slug = data.slug;
    if (!slug || !window.AppData || !window.AppData.startRun) {
      requireAuth('Sign in to run this WorkApp.');
      return;
    }

    const runCount = window.AppData.getRunCount ? window.AppData.getRunCount() : 1;

    // Second run onwards: require login if the user is not signed in.
    if (!signedIn && runCount >= 1) {
      setSignInModal({ open: true, reason: 'Create a free account to run more WorkApps.' });
      return;
    }

    const input = Object.assign({}, data);
    delete input.slug;
    window.AppData.startRun(slug, input).then(function(r) {
      if (r && r.runId) {
        if (window.AppData.incrementRunCount) window.AppData.incrementRunCount();
        setView('streaming', { runId: r.runId, workappSlug: slug });
      } else {
        showToast('Could not start run — please try again.');
      }
    }).catch(function(err) {
      if (err && err.status === 401) {
        window.AppData.redirectToLogin();
      } else {
        showToast('Could not start run — please try again.');
      }
    });
  };
  const sampleInputs = () => setInputs({ url: 'https://acme.com', context: 'Sample run' });
  const openExpert = (expert = EXPERT) => {
    const e = expert || EXPERT;
    setSelectedExpert(e);
    const expertSlug = e && e.slug
      ? e.slug
      : e && e.name
        ? e.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '')
        : null;
    if (expertSlug) setView('expert', { expertSlug });
    else setView('expert');
  };
  const openMethodNote = () => {
    setView('detail', params.slug ? { slug: params.slug } : undefined);
    window.setTimeout(() => {
      document.getElementById('method-note')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }, 0);
  };
  const jumpInternal = (target) => {
    setShareModal(false);
    setSignInModal({ open: false, reason: '' });
    setQualificationModal(false);
    setTweak('simulateError', false);

    if (target === 'streaming') {
      setInputs({ url: 'https://acme.com', context: 'Sample run' });
      setView('streaming');
      return;
    }
    if (target === 'streaming-error') {
      setInputs({ url: 'https://acme.com', context: 'Sample run' });
      setTweak('simulateError', true);
      setView('streaming');
      return;
    }
    if (target === 'result') {
      sampleInputs();
      setResultState('standard');
      setView('result');
      return;
    }
    if (target === 'result-shared') {
      setInputs({ url: 'https://acme.com', context: 'Shared sample run' });
      setResultState('shared');
      setView('result');
      return;
    }
    if (target === 'result-outreach') {
      setInputs({ url: 'https://vault.so', context: 'Personalized outreach sample' });
      setResultState('outreach');
      setView('result');
      return;
    }
    if (target === 'myruns-locked') {
      setTweak('signedIn', false);
      setView('myruns');
      return;
    }
    if (target === 'myruns') {
      setTweak('signedIn', true);
      setView('myruns');
      return;
    }
    if (target === 'account-locked') {
      setTweak('signedIn', false);
      setView('account');
      return;
    }
    if (target === 'account') {
      setTweak('signedIn', true);
      setView('account');
      return;
    }
    if (target === 'auth-signin' || target === 'auth-signup') {
      setAuthMode(target === 'auth-signin' ? 'signin' : 'signup');
      setView('auth');
      return;
    }
    if (target.startsWith('error-')) {
      setInputs({ url: 'https://acme.com', context: 'Sample run' });
      setErrorVariant(target.replace('error-', ''));
      setView('error');
      return;
    }
    if (target === 'modal-signin') {
      sampleInputs();
      setView('result');
      setSignInModal({ open: true, reason: 'Create a free account to continue' });
      return;
    }
    if (target === 'modal-share') {
      sampleInputs();
      setView('result');
      setShareModal(true);
      return;
    }
    if (target !== 'result') setResultState('standard');
    setView(target);
  };

  return (
    <>
      {view !== 'home' && (
        <Nav
          signedIn={signedIn}
          onSignIn={function() { window.AppData.redirectToLogin(); }}
          onSignOut={doSignOut}
          onHome={goHome}
          onNav={(v) => setView(v)}
        />
      )}

      {view === 'home' && (
        <HomeScreen
          onWorkApp={(w) => setView('detail', { slug: w && w.slug })}
          onDirectory={() => setView('directory')}
          onExpert={openExpert}
          onExperts={() => setView('experts')}
          onAbout={() => setView('about')}
          onBecomeExpert={() => setView('become')}
          onRun={startRunAndNavigate}
          onSeeSample={() => { setInputs({ url: 'https://acme.com', context: 'Sample run' }); setResultState('standard'); setView('result'); }}
        />
      )}

      {view === 'home-alt' && (
        <HomeAltScreen
          onWorkApp={(w) => setView('detail', { slug: w && w.slug })}
          onDirectory={() => setView('directory')}
          onExpert={openExpert}
          onRun={startRunAndNavigate}
          onSeeSample={() => { setInputs({ url: 'https://acme.com', context: 'Sample run' }); setResultState('standard'); setView('result'); }}
        />
      )}

      {view === 'marketplace' && (
        <HomeScreenOriginal
          onWorkApp={(w) => setView('detail', { slug: w && w.slug })}
          onDirectory={() => setView('directory')}
          onExpert={openExpert}
          onExperts={() => setView('experts')}
          onAbout={() => setView('about')}
          onBecomeExpert={() => setView('become')}
          onRun={startRunAndNavigate}
          onSeeSample={() => { setInputs({ url: 'https://acme.com', context: 'Sample run' }); setResultState('standard'); setView('result'); }}
        />
      )}

      {view === 'directory' && (
        <DirectoryScreen onWorkApp={(w) => setView('detail', { slug: w && w.slug })} />
      )}

      {view === 'detail' && (
        <DetailScreen
          slug={params.slug}
          onRun={startRunAndNavigate}
          onSeeSample={() => { setInputs({ url: 'https://acme.com', context: 'Sample run' }); setResultState('standard'); setView('result'); }}
          onRelatedClick={(w) => w && w.slug ? setView('detail', { slug: w.slug }) : showToast('(prototype) Would navigate to related WorkApp')}
          onExpert={openExpert}
        />
      )}

      {view === 'expert' && (
        <ExpertProfileScreen
          expertSlug={params.expertSlug}
          onWorkApp={(w) => setView('detail', { slug: w && w.slug })}
          expert={selectedExpert}
          onRequireAuth={requireAuth}
          signedIn={signedIn}
        />
      )}

      {view === 'myruns' && (
        <MyRunsScreen
          signedIn={signedIn}
          onOpenResult={(run) => {
            const rid = run && (run.runId || run.id);
            if (!rid) return;
            const slug = run.workappSlug || '';
            setResultState('standard');
            if (run.status === 'running' || run.status === 'queued' || run.status === 'pending') {
              setView('streaming', { runId: rid, workappSlug: slug });
            } else {
              setView('result', { runId: rid, workappSlug: slug });
            }
          }}
          onWorkApp={(w) => w && w.slug ? setView('detail', { slug: w.slug }) : setView('directory')}
          onRequireAuth={requireAuth}
        />
      )}

      {view === 'account' && (
        <AccountScreen
          signedIn={signedIn}
          onSignOut={doSignOut}
          onRequireAuth={requireAuth}
        />
      )}

      {view === 'experts' && (
        <ExpertsDirectoryScreen
          onExpert={openExpert}
          onBecomeExpert={() => setView('become')}
        />
      )}

      {view === 'become' && (
        <BecomeExpertScreen onSubmit={() => showToast('Application received')} />
      )}

      {view === 'about' && (
        <AboutScreen
          onWorkApp={() => setView('directory')}
          onExperts={() => setView('experts')}
          onBecomeExpert={() => setView('become')}
        />
      )}

      {view === 'privacy' && <PrivacyScreen />}
      {view === 'terms' && <TermsScreen />}

      {view === 'auth' && (
        <React.Fragment>
          {(function() { window.AppData.redirectToLogin(); return null; })()}
        </React.Fragment>
      )}

      {view === 'error' && (
        <RunErrorScreen
          variant={errorVariant}
          inputs={inputs}
          onRetry={() => setView('streaming', params.runId ? { runId: params.runId } : undefined)}
          onBack={() => setView('detail', params.slug ? { slug: params.slug } : undefined)}
          onDifferentUrl={() => setView('detail', params.slug ? { slug: params.slug } : undefined)}
        />
      )}

      {view === 'input' && (
        <RunInputScreen
          initial={inputs}
          onBack={() => setView('detail', params.slug ? { slug: params.slug } : undefined)}
          onSubmit={(data) => { startRunAndNavigate(data); }}
        />
      )}

      {view === 'streaming' && (
        <StreamingScreen
          runId={params.runId}
          workappSlug={params.workappSlug || ''}
          inputs={inputs}
          simulateError={t.simulateError}
          onComplete={() => { setResultState('standard'); setView('result', { runId: params.runId }); }}
          onCancel={() => setView('detail', params.slug ? { slug: params.slug } : undefined)}
          onRetry={() => { setTweak('simulateError', false); setView('streaming', params.runId ? { runId: params.runId } : undefined); }}
        />
      )}

      {view === 'result' && (
        <ResultScreen
          runId={params.runId}
          workappSlug={params.workappSlug || ''}
          resultState={resultState}
          inputs={inputs}
          signedIn={signedIn}
          onShare={() => setShareModal(true)}
          onSave={() => {
            if (!signedIn) { requireAuth('Create a free account to save this result'); return; }
            if (!params.runId) return;
            showToast('Saving…');
            window.AppData.saveRun(params.runId)
              .then(() => showToast('Saved to your library'))
              .catch((e) => showToast('Could not save: ' + (e && e.message ? e.message : e)));
          }}
          onRerun={() => setView('detail', params.slug ? { slug: params.slug } : undefined)}
          onCompareUrl={(url) => { setInputs({ url, context: '' }); setView('streaming', params.runId ? { runId: params.runId } : undefined); }}
          onRequireAuth={requireAuth}
          onExpert={() => setView('expert', params.expertSlug ? { expertSlug: params.expertSlug } : undefined)}
          onMethodNote={openMethodNote}
          onRelatedClick={(w) => w && w.slug ? setView('detail', { slug: w.slug }) : setView('directory')}
        />
      )}

      {view === 'shared-result' && (
        <SharedResultScreen token={params.token} />
      )}

      {view === 'publish' && (
        <PublishContentScreen workappId={params.workappId} token={params.token} />
      )}

      {/* InternalNav is the prototype's dev-only navigation panel — hidden in production */}

      <SignInModal
        open={signInModal.open}
        reason={signInModal.reason}
        onClose={() => setSignInModal({ open: false, reason: '' })}
        onSignIn={() => {
          setSignInModal({ open: false, reason: '' });
          window.AppData.redirectToLogin();
        }}
      />

      <QualificationModal
        open={qualificationModal}
        onClose={closeQualification}
        onComplete={completeQualification}
      />

      <ShareModal
        open={shareModal}
        runId={params.runId}
        signedIn={signedIn}
        onClose={() => setShareModal(false)}
        onSignIn={function() { setShareModal(false); window.AppData.redirectToLogin(); }}
        onToast={showToast}
      />

      <Toast message={toast} />

      <window.TweaksPanel>
        <window.TweakSection label="Aesthetic">
          <window.TweakRadio
            label="Variant"
            value={t.aesthetic}
            options={[
              { value: 'warm', label: 'Mono' },
              { value: 'stark', label: 'Stark' },
              { value: 'literary', label: 'Literary' },
            ]}
            onChange={(v) => setTweak('aesthetic', v)}
          />
          <window.TweakColor
            label="Accent"
            value={t.accent}
            options={ACCENT_OPTIONS}
            onChange={(v) => setTweak('accent', v)}
          />
          <window.TweakRadio
            label="Density"
            value={t.density}
            options={[
              { value: 'comfortable', label: 'Cozy' },
              { value: 'compact', label: 'Compact' },
            ]}
            onChange={(v) => setTweak('density', v)}
          />
        </window.TweakSection>

        <window.TweakSection label="State">
          <window.TweakToggle
            label="Signed in"
            value={t.signedIn}
            onChange={(v) => setTweak('signedIn', v)}
          />
          <window.TweakToggle
            label="Simulate run error"
            value={t.simulateError}
            onChange={(v) => setTweak('simulateError', v)}
          />
        </window.TweakSection>

      </window.TweaksPanel>
    </>
  );
}

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