// app.jsx — main shell with History API router + real auth
const { useState: useStateApp, useEffect: useEffectApp } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#b4623a",
  "dark": false,
  "density": "regular",
  "view": "list",
  "fontDisplay": "serif-italic"
}/*EDITMODE-END*/;

const ACCENT_OPTIONS = [
  "#2f5d3f",
  "#b4623a",
  "#1f3a5f",
  "#7a2d3a",
  "#5d4ba0",
];

const ACCENT_INK = {
  "#2f5d3f": "#ffffff",
  "#b4623a": "#ffffff",
  "#1f3a5f": "#ffffff",
  "#7a2d3a": "#ffffff",
  "#5d4ba0": "#ffffff",
};

function parseRoute() {
  // Handle ?action=reset-password&token=xxx from password-reset emails
  const params = new URLSearchParams(window.location.search);
  if (params.get('action') === 'reset-password' && params.get('token')) {
    return '/login';
  }
  return window.location.pathname || '/';
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [route, setRoute] = useStateApp(parseRoute);
  const [user, setUser] = useStateApp(null);
  const [authReady, setAuthReady] = useStateApp(false);

  // Restore auth on load; also handles the Google OAuth callback (?code=...)
  useEffectApp(() => {
    (async () => {
      const params = new URLSearchParams(window.location.search);
      const code = params.get('code');
      const state = params.get('state');
      const oauthError = params.get('error');

      function cleanOAuthParams() {
        const url = new URL(window.location.href);
        url.searchParams.delete('code');
        url.searchParams.delete('state');
        url.searchParams.delete('error');
        url.searchParams.delete('error_description');
        window.history.replaceState({}, '', url.pathname + url.search + url.hash);
      }

      function failOAuth() {
        window.history.replaceState({}, '', '/login?oauth_error=true');
        setRoute('/login');
        setAuthReady(true);
      }

      if (oauthError) {
        cleanOAuthParams();
        failOAuth();
        return;
      }

      if (code) {
        const expectedState = sessionStorage.getItem('bm_oauth_state');
        sessionStorage.removeItem('bm_oauth_state');
        cleanOAuthParams();

        if (!expectedState || !state || expectedState !== state) {
          failOAuth();
          return;
        }

        const cfg = window.BUKMAK_CONFIG || {};
        const redirectUri = cfg.googleRedirectUri || (window.location.origin + '/');
        try {
          const data = await api.googleExchange(code, redirectUri);
          setUser(await api.resolveUser(data));
          setAuthReady(true);
          window.history.pushState({}, '', '/spaces');
          setRoute('/spaces');
        } catch {
          api.clearTokens();
          failOAuth();
        }
        return;
      }

      if (api.isAuthenticated()) {
        try {
          const me = await api.getMe();
          setUser(me);
        } catch {
          api.clearTokens();
        }
      }
      setAuthReady(true);
    })();
  }, []);

  useEffectApp(() => {
    if (route === '/login' && user && authReady) navigate('/spaces');
  }, [route, user]);

  // Popstate listener (browser back/forward)
  useEffectApp(() => {
    const onPop = () => {
      const params = new URLSearchParams(window.location.search);
      if (params.get('action') === 'reset-password') return;
      setRoute(window.location.pathname || '/');
    };
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  const navigate = (path) => {
    window.history.pushState({}, '', path);
    setRoute(path);
    window.scrollTo(0, 0);
  };

  const onAuth = (u) => setUser(u);

  const onLogout = async () => {
    await api.logout();
    setUser(null);
    navigate('/');
  };

  // Apply theme / accent
  useEffectApp(() => {
    document.body.setAttribute('data-theme', t.dark ? 'dark' : 'light');
    document.body.setAttribute('data-density', t.density);
    document.documentElement.style.setProperty('--accent', t.accent);
    document.documentElement.style.setProperty('--accent-ink', ACCENT_INK[t.accent] || '#fff');
  }, [t.dark, t.accent, t.density]);

  const floatThemeClass = route === '/spaces' ? 'spaces'
    : (route === '/account' || route === '/privacy') ? 'lifted'
    : '';
  const showFloatingTheme = route === '/spaces' || route === '/account' || route === '/privacy';

  if (!authReady) {
    return (
      <div style={{
        minHeight: '100vh', display: 'flex',
        alignItems: 'center', justifyContent: 'center',
        color: 'var(--muted)', fontSize: 14,
      }}>
        <div className="shell-bg-grain" />
        Loading…
      </div>
    );
  }

  let view;
  if (route === '/' || route === '')
    view = <LandingPage navigate={navigate} user={user} onLogout={onLogout} />;
  else if (route === '/login')
    view = <LoginPage navigate={navigate} onAuth={onAuth} />;
  else if (route === '/spaces') {
    if (!user) { navigate('/login'); return null; }
    view = <SpacesPage navigate={navigate} user={user} onLogout={onLogout} />;
  } else if (route === '/account') {
    if (!user) { navigate('/login'); return null; }
    view = <AccountPage navigate={navigate} user={user} onLogout={onLogout} onUserUpdate={onAuth} />;
  } else if (route === '/privacy')
    view = <PrivacyPage navigate={navigate} />;
  else
    view = <NotFound navigate={navigate} />;

  return (
    <>
      <div className="shell-bg-grain" />
      {view}

      {showFloatingTheme && (
        <button className={`float-theme ${floatThemeClass}`}
                onClick={() => setTweak('dark', !t.dark)}
                title={t.dark ? 'Light mode' : 'Dark mode'}>
          {t.dark ? <I.Sun size={16} /> : <I.Moon size={16} />}
        </button>
      )}

      <TweaksPanel>
        <TweakSection label="Library" />
        <TweakColor label="Accent" value={t.accent}
                    options={ACCENT_OPTIONS}
                    onChange={(v) => setTweak('accent', v)} />
        <TweakToggle label="Dark mode" value={t.dark}
                     onChange={(v) => setTweak('dark', v)} />

        <TweakSection label="Density" />
        <TweakRadio label="Row size" value={t.density}
                    options={['compact', 'regular', 'comfy']}
                    onChange={(v) => setTweak('density', v)} />

        <TweakSection label="Navigate" />
        <TweakButton onClick={() => navigate('/')}>Landing page</TweakButton>
        <TweakButton onClick={() => navigate('/login')}>Login</TweakButton>
        <TweakButton onClick={() => navigate('/spaces')}>Spaces (library)</TweakButton>
        <TweakButton onClick={() => navigate('/account')}>Account</TweakButton>
        <TweakButton onClick={() => navigate('/privacy')}>Privacy</TweakButton>
      </TweaksPanel>
    </>
  );
}

function NotFound({ navigate }) {
  return (
    <div style={{
      minHeight: '100vh',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      flexDirection: 'column', padding: 32, textAlign: 'center',
    }}>
      <div className="eyebrow" style={{ marginBottom: 12 }}>404</div>
      <h1 style={{
        fontSize: 48, fontWeight: 400, letterSpacing: '-0.02em',
        margin: '0 0 12px',
      }}>Not <span className="serif-italic" style={{ color: 'var(--accent)' }}>found.</span></h1>
      <p style={{ color: 'var(--ink-2)', margin: '0 0 24px' }}>That page isn't in your library.</p>
      <button className="btn btn-accent btn-lg" onClick={() => navigate('/')}>Take me home</button>
    </div>
  );
}

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