/* eslint-disable */
/* ============================================================
   app.jsx — Root React component for LiddellWorks
   ============================================================
   Renders the whole single-page portfolio:
     - 3-column header (title / intro / elsewhere-links)
     - Three "wheel carousel" section bands (apps / prints / writing)
     - Footer
     - Overlay drawer (opens when a centre card is clicked)

   This file used to host a full design-time tweaks panel that let
   you switch palettes, type pairings, hero layouts, etc.  In
   production the prototype is locked to the chosen defaults
   (Fog palette + Bricolage type + Green-soft accent + tinted
   section bands + 3-col header), so all of that switching code
   is gone.  Tokens are now defined statically in tokens.css.
   ============================================================ */

const { useEffect } = React;

/* ------------------------------------------------------------
   useReveal
   ------------------------------------------------------------
   Adds the `.in` class to anything tagged `.reveal` once it
   scrolls into view.  Pairs with the .reveal CSS in index.html
   to fade-and-rise each section band as the user scrolls.

   We only run this once on mount.  IntersectionObserver fires
   on every threshold crossing, so we keep the threshold low
   (8%) — the band is "revealed" almost as soon as any sliver of
   it appears.
*/
const useReveal = () => {
  useEffect(() => {
    const els = document.querySelectorAll('.reveal');
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) e.target.classList.add('in');
      });
    }, { threshold: 0.08 });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);
};

/* ------------------------------------------------------------
   Routing
   ------------------------------------------------------------
   Two views in this app:
     - the home page                 (path "/")
     - per-section archive pages     (paths "/archive/apps",
                                      "/archive/3ddesign",
                                      "/archive/thoughts")

   We use the History API + a single SPA fallback in
   wrangler.jsonc (`not_found_handling: "single-page-application"`)
   so every URL serves index.html and JS decides what to render.

   The route helpers below are intentionally tiny — we don't need
   a router library for two views.
*/
const ARCHIVE_SECTIONS = ['apps', '3ddesign', 'thoughts'];

const parseRoute = (pathname) => {
  const m = (pathname || '/').match(/^\/archive\/([a-z0-9-]+)\/?$/i);
  if (m && ARCHIVE_SECTIONS.includes(m[1].toLowerCase())) {
    return { kind: 'archive', section: m[1].toLowerCase() };
  }
  return { kind: 'home' };
};

// Map archive section slug → source data array + overlay kind label.
const ARCHIVE_DATA = {
  apps:       { items: () => window.APPS,   overlayKind: 'app'   },
  '3ddesign': { items: () => window.PRINTS, overlayKind: 'print' },
  thoughts:   { items: () => window.ESSAYS, overlayKind: 'essay' },
};

/* ------------------------------------------------------------
   App — top-level component
   ------------------------------------------------------------
   Holds:
     - the current route (home / archive)
     - whether the overlay is open (and which item it shows)
     - kicks off scroll-reveal observation
   Everything else is plain markup driven by data.jsx.
*/
const App = () => {
  // Current route — recomputed on popstate so back/forward works.
  const [route, setRoute] = React.useState(() => parseRoute(window.location.pathname));
  useEffect(() => {
    const onPop = () => setRoute(parseRoute(window.location.pathname));
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  // Overlay state — `open` controls visibility, `item` and `kind`
  // describe what the overlay should render.  We keep them in
  // separate slots (rather than a single object) so closing the
  // overlay can still animate out with the previous content.
  const [overlayOpen, setOverlayOpen] = React.useState(false);
  const [overlayItem, setOverlayItem] = React.useState(null);
  const [overlayKind, setOverlayKind] = React.useState(null);

  useReveal();

  // Open / close helpers passed down to every card.
  const openOverlay = (item, kind) => {
    setOverlayItem(item);
    setOverlayKind(kind);
    setOverlayOpen(true);
  };
  const closeOverlay = () => setOverlayOpen(false);

  // Convenience: items in each section split by archived flag.
  const live = (arr) => (arr || []).filter((i) => !i.archived);

  // ────────────── Archive route ──────────────
  if (route.kind === 'archive') {
    const data = ARCHIVE_DATA[route.section];
    const archivedItems = (data.items() || []).filter((i) => i.archived);
    return (
      <>
        <ArchiveView
          section={route.section}
          items={archivedItems}
          openOverlay={openOverlay}
        />
        <Overlay
          open={overlayOpen}
          item={overlayItem}
          kind={overlayKind}
          onClose={closeOverlay}
        />
      </>
    );
  }

  // ────────────── Home route ──────────────
  return (
    <>
      {/* ============ HEADER ============
           Content is driven by window.HOME (data.jsx).
           Edit via the editor's Home tab and Save ↑ to deploy.
      */}
      {(() => {
        const H        = window.HOME || {};
        const tagline  = H.tagline  || 'staying curious';
        const subtitle = H.subtitle || "What I'm thinking about doing,\nand doing about my thinking.";
        const bio      = H.bio      || 'Founder & technology enthusiast in London. Recovering sinologist, Royal Marines, and banker. Now making apps, 3D-printed objects, and the occasional thought piece.';
        const links    = H.links    || [
          { label: 'Email',    href: 'mailto:tom@liddellworks.com' },
          { label: 'GitHub',   href: '#' },
          { label: 'LinkedIn', href: 'https://www.linkedin.com/in/tliddell/', newTab: true },
          { label: 'About',    href: '#' }
        ];
        return (
          <header className="site-header">
            <div className="h-title">
              <div className="h-name">
                <span className="accent-mark">◆</span>
                Tom Liddell <span className="dash">—</span> <em>{tagline}</em>
              </div>
              <div className="h-subtitle">
                {subtitle.split('\n').map((line, i, arr) => (
                  <React.Fragment key={i}>{line}{i < arr.length - 1 && <br />}</React.Fragment>
                ))}
              </div>
            </div>

            <div className="h-intro">
              <p>{bio}</p>
            </div>

            <div className="h-links">
              <div className="h-link-label">Elsewhere</div>
              {links.map((link, i) => (
                <a
                  key={i}
                  className="h-link"
                  href={link.href || '#'}
                  {...(link.newTab ? { target: '_blank', rel: 'noopener noreferrer' } : {})}
                >
                  <span>{link.label}</span><span className="arrow">↗</span>
                </a>
              ))}
            </div>
          </header>
        );
      })()}

      {/* ============ MAIN — three section bands ============
           Each band uses its own background tint via the
           [data-kind] attribute (see index.html CSS).  The
           `.reveal` class fades each band in on scroll.
      */}
      <main>
        <section className="section-band reveal" data-kind="apps">
          <WheelCarousel
            num="01 — APPS"
            title="App design"
            sub="Quiet products for restless minds."
            items={live(APPS)}
            archiveHref="/archive/apps"
            renderCard={(item, active) => (
              <AppCard item={item} active={active} onOpen={openOverlay} />
            )}
          />
        </section>

        <section className="section-band reveal" data-kind="prints">
          <WheelCarousel
            num="02 — PRINTS"
            title="3D prints"
            sub="Functional objects, mostly."
            items={live(PRINTS)}
            archiveHref="/archive/3ddesign"
            renderCard={(item, active) => (
              <PrintCard item={item} active={active} onOpen={openOverlay} />
            )}
          />
        </section>

        <section className="section-band reveal" data-kind="essays">
          <WheelCarousel
            num="03 — WRITING"
            title="Thought pieces"
            sub="On patience, scale, and small machines."
            items={live(ESSAYS)}
            archiveHref="/archive/thoughts"
            renderCard={(item, active) => (
              <EssayCard item={item} active={active} onOpen={openOverlay} />
            )}
          />
        </section>
      </main>

      {/* ============ FOOTER ============ */}
      <footer className="footer">
        <div><span className="accent-dot" />LiddellWorks · London · 2026</div>
        <div>v.2026.05 · Available Q3</div>
      </footer>

      {/* The overlay drawer is always mounted; visibility is
          driven by `overlayOpen`.  Keeping it mounted lets the
          close transition run cleanly. */}
      <Overlay
        open={overlayOpen}
        item={overlayItem}
        kind={overlayKind}
        onClose={closeOverlay}
      />
    </>
  );
};

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