// Root app: hash-based router + tweaks panel + accent color binding.

const { useState, useEffect, useMemo } = React;

const DEFAULT_TWEAKS = /*EDITMODE-BEGIN*/{
  "accent": "#7c7cff",
  "heroDensity": 1.6,
  "glassOpacity": 5,
  "metagraphEnabled": false
}/*EDITMODE-END*/;

function useHashRoute() {
  const [route, setRoute] = useState(() => (window.location.hash || '#/').slice(1) || '/');
  useEffect(() => {
    const onHash = () => setRoute((window.location.hash || '#/').slice(1) || '/');
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  const navigate = (path) => {
    if (!path.startsWith('/')) path = '/' + path;
    window.location.hash = '#' + path;
    window.scrollTo({ top: 0, behavior: 'instant' });
  };
  return [route, navigate];
}

function App() {
  const [route, navigate] = useHashRoute();
  const [tweaks, setTweak] = useTweaks(DEFAULT_TWEAKS);

  // Sync env flag with tweak so toggling the tweak hides the route too.
  useEffect(() => {
    window.__ENV.METAGRAPH_ENABLED = !!tweaks.metagraphEnabled;
  }, [tweaks.metagraphEnabled]);

  // Push accent to CSS vars
  useEffect(() => {
    const root = document.documentElement;
    root.style.setProperty('--accent', tweaks.accent);
    // derive a near-accent for the gradient end
    root.style.setProperty('--accent-2', mix(tweaks.accent, '#ffffff', 0.35));
    root.style.setProperty('--accent-glow', hexToRgba(tweaks.accent, 0.35));
  }, [tweaks.accent]);

  // Push glass tint to CSS vars. Slider goes 0–100; we map to a tint alpha
  // that goes from "barely there" (0.01) to "clearly visible glass" (0.20).
  useEffect(() => {
    const root = document.documentElement;
    const t = Math.max(0, Math.min(100, tweaks.glassOpacity ?? 30)) / 100;
    const tint = 0.01 + t * 0.19;          // 0.01 .. 0.20
    const tintLow = tint * 0.3;             // gradient endpoint
    root.style.setProperty('--lg-tint', tint.toFixed(3));
    root.style.setProperty('--lg-tint-low', tintLow.toFixed(3));
  }, [tweaks.glassOpacity]);

  // Document title per route
  useEffect(() => {
    const titles = {
      '/': 'graphite · structured world knowledge',
      '/graphs': 'Knowledge Graphs · graphite',
      '/graphs/financial': 'Financial Knowledge Graph · graphite',
      '/metagraph': 'Metagraph · graphite',
      '/portal': 'API Portal · graphite',
      '/pricing': 'Pricing · graphite',
      '/admin': 'Admin · graphite',
    };
    document.title = titles[route] || 'graphite';
  }, [route]);

  // /admin renders full-screen (no global Nav, its own header) so we
  // branch on it before the rest of the routing.
  if (route === '/admin') {
    return <Admin navigate={navigate} />;
  }

  let page;
  if (route === '/' || route === '') {
    page = <Landing navigate={navigate} density={tweaks.heroDensity} />;
  } else if (route === '/graphs') {
    page = <Graphs navigate={navigate} />;
  } else if (route === '/graphs/financial') {
    page = <Viewer navigate={navigate} />;
  } else if (route === '/metagraph') {
    if (!tweaks.metagraphEnabled) {
      page = <NotFound navigate={navigate} reason="The Metagraph tab is disabled in this build." />;
    } else {
      page = <Metagraph navigate={navigate} />;
    }
  } else if (route === '/portal') {
    page = <Portal navigate={navigate} />;
  } else if (route === '/pricing') {
    page = <Pricing navigate={navigate} />;
  } else {
    page = <NotFound navigate={navigate} />;
  }

  return (
    <>
      <Nav route={route} navigate={navigate} />
      {page}
      <TweaksPanel title="Tweaks">
        <TweakSection label="Branding">
          <TweakColor
            label="Accent color"
            value={tweaks.accent}
            onChange={(v) => setTweak('accent', v)}
            options={['#7c7cff', '#a78bfa', '#5ed694', '#ff9a5b', '#ff6d6d']}
          />
        </TweakSection>
        <TweakSection label="Hero scene">
          <TweakSlider
            label="Node density"
            value={tweaks.heroDensity}
            min={0.4} max={1.6} step={0.1}
            onChange={(v) => setTweak('heroDensity', v)}
          />
        </TweakSection>
        <TweakSection label="Liquid glass">
          <TweakSlider
            label="Panel opacity"
            value={tweaks.glassOpacity ?? 30}
            min={0} max={100} step={5} unit="%"
            onChange={(v) => setTweak('glassOpacity', v)}
          />
        </TweakSection>
        <TweakSection label="Feature flags">
          <TweakToggle
            label="Show Metagraph tab"
            value={!!tweaks.metagraphEnabled}
            onChange={(v) => setTweak('metagraphEnabled', v)}
          />
          <div style={{fontSize:11.5,color:'#8a8a96',marginTop:6,lineHeight:1.45}}>
            Mirrors <code style={{fontFamily:'Geist Mono,ui-monospace,monospace'}}>METAGRAPH_ENABLED</code> in <code style={{fontFamily:'Geist Mono,ui-monospace,monospace'}}>env.js</code>. Off → tab disappears and the route stops resolving.
          </div>
        </TweakSection>
      </TweaksPanel>
    </>
  );
}

function NotFound({ navigate, reason }) {
  return (
    <div className="page" style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'80vh'}}>
      <div style={{textAlign:'center',maxWidth:480}}>
        <div className="mono" style={{fontSize:11,letterSpacing:'0.14em',color:'var(--fg-mute)',textTransform:'uppercase'}}>404</div>
        <h2 style={{marginTop:14}}>Nothing here.</h2>
        <p style={{color:'var(--fg-dim)',marginTop:12}}>{reason || "We couldn't find that page."}</p>
        <a className="btn btn-ghost" style={{marginTop:24}} href="#/" onClick={(e)=>{e.preventDefault();navigate('/');}}>Back to home <Icon name="arrow" /></a>
      </div>
    </div>
  );
}

// tiny color helpers
function hexToRgba(hex, a) {
  const h = hex.replace('#', '');
  const r = parseInt(h.slice(0,2), 16), g = parseInt(h.slice(2,4), 16), b = parseInt(h.slice(4,6), 16);
  return `rgba(${r},${g},${b},${a})`;
}
function mix(a, b, t) {
  const A = a.replace('#',''), B = b.replace('#','');
  const ar = parseInt(A.slice(0,2),16), ag = parseInt(A.slice(2,4),16), ab = parseInt(A.slice(4,6),16);
  const br = parseInt(B.slice(0,2),16), bg = parseInt(B.slice(2,4),16), bb = parseInt(B.slice(4,6),16);
  const r = Math.round(ar + (br-ar)*t), g = Math.round(ag + (bg-ag)*t), bl = Math.round(ab + (bb-ab)*t);
  return '#' + [r,g,bl].map(n => n.toString(16).padStart(2,'0')).join('');
}

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