/* global React, ReactDOM, FrogCursor, FrogTrail, Panel, AboutPanel, WorkPanel, JournalPanel,
   SelectedWork, Services, ServicesPanel, Testimonials, ContactBlock,
   TweaksPanel, useTweaks, TweakSection, TweakColor, TweakRadio, TweakSlider */
const { useState, useEffect, createContext, useContext } = React;

/* ── Config context (shared with panel-content.jsx via window) ── */
const ConfigContext = createContext(window.SITE_CONFIG);
window.ConfigContext = ConfigContext; /* expose for other script files */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#F2C84B",
  "type": "serif-mono",
  "heroSize": 11.5,
  "heroLine": 0.88,
  "heroTrack": -0.035,
  "heroGap": 32
} /*EDITMODE-END*/;

const TYPE_OPTIONS = [
  { value: "serif-mono",      label: "Fraunces" },
  { value: "grotesk-mono",    label: "Grotesk"  },
  { value: "condensed-mono",  label: "Cond."    },
  { value: "mono-everything", label: "Mono"     },
];

/* ── Sidebar SVG Icons ── */
function IconHome() {
  return (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="currentColor" aria-hidden="true">
      <path d="M11.47 3.841a.75.75 0 0 1 1.06 0l8.69 8.69a.75.75 0 1 0 1.06-1.061l-8.689-8.69a2.25 2.25 0 0 0-3.182 0l-8.69 8.69a.75.75 0 1 0 1.061 1.06l8.69-8.689Z" />
      <path d="m12 5.432 8.159 8.159c.03.03.06.058.091.086v6.198c0 1.035-.84 1.875-1.875 1.875H15a.75.75 0 0 1-.75-.75v-4.5a.75.75 0 0 0-.75-.75h-3a.75.75 0 0 0-.75.75V21a.75.75 0 0 1-.75.75H5.625a1.875 1.875 0 0 1-1.875-1.875v-6.198c.03-.028.061-.056.091-.086L12 5.432Z" />
    </svg>
  );
}

function IconTag() {
  return (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="currentColor" aria-hidden="true">
      <path fillRule="evenodd" d="M5.25 2.25a3 3 0 0 0-3 3v4.318a3 3 0 0 0 .879 2.121l9.58 9.581c.92.92 2.39 1.028 3.43.26a18.158 18.158 0 0 0 5.013-5.001c.772-1.04.66-2.51-.26-3.43L12.3 3.129a3 3 0 0 0-2.121-.879H5.25ZM6 8.25a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z" clipRule="evenodd" />
    </svg>
  );
}

function IconSmiley() {
  return (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <circle cx="12" cy="12" r="10" />
      <path d="M8 14s1.5 2.5 4 2.5 4-2.5 4-2.5" />
      <circle cx="9" cy="10" r="0.5" fill="currentColor" stroke="none" />
      <circle cx="15" cy="10" r="0.5" fill="currentColor" stroke="none" />
    </svg>
  );
}

function IconMail() {
  return (
    <svg viewBox="0 0 24 24" width="22" height="22" fill="currentColor" aria-hidden="true">
      <path d="M1.5 8.67v8.58a3 3 0 0 0 3 3h15a3 3 0 0 0 3-3V8.67l-8.928 5.493a3 3 0 0 1-3.144 0L1.5 8.67Z" />
      <path d="M22.5 6.908V6.75a3 3 0 0 0-3-3h-15a3 3 0 0 0-3 3v.158l9.714 5.978a1.5 1.5 0 0 0 1.572 0L22.5 6.908Z" />
    </svg>
  );
}

/* ── Sidebar Component ── */
function Sidebar({ onOpen }) {
  const [hovered, setHovered] = useState(null);

  const items = [
    {
      id: "home",
      icon: <IconHome />,
      label: "Home",
      action: () => window.scrollTo({ top: 0, behavior: "smooth" }),
    },
    {
      id: "work",
      icon: <IconTag />,
      label: "Work",
      action: (e) => onOpen("work")(e),
    },
    {
      id: "about",
      icon: <IconSmiley />,
      label: "About",
      action: (e) => onOpen("about")(e),
    },
    {
      id: "contact",
      icon: <IconMail />,
      label: "Contact",
      action: () =>
        document.getElementById("contact")?.scrollIntoView({ behavior: "smooth" }),
    },
  ];

  return (
    <nav className="sidebar" aria-label="Site navigation">
      {items.map((item) => (
        <div
          key={item.id}
          className="sidebar-item"
          onMouseEnter={() => setHovered(item.id)}
          onMouseLeave={() => setHovered(null)}
        >
          <button
            className="sidebar-btn"
            onClick={item.action}
            data-cursor="hover"
            aria-label={item.label}
          >
            {item.icon}
          </button>
          <span className={"sidebar-label" + (hovered === item.id ? " visible" : "")}>
            {item.label}
          </span>
        </div>
      ))}
    </nav>
  );
}

/* ── Project Card (scroll-in) ── */
function ProjectCard({ item, index, onOpen }) {
  const ref = React.useRef(null);
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const obs = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) { setVisible(true); obs.disconnect(); } },
      { threshold: 0.12 }
    );
    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  const hasUrl = item.url && item.url !== "#";

  return (
    <button
      ref={ref}
      className={"project-card" + (visible ? " is-visible" : "")}
      style={{ transitionDelay: `${(index % 3) * 90}ms` }}
      onClick={hasUrl ? () => window.open(item.url, "_blank", "noopener,noreferrer") : onOpen}
      data-cursor="hover"
      aria-label={`Open ${item.title}`}
    >
      <div className="project-card-num">{item.n}</div>
      <h3 className="project-card-title">{item.title}</h3>
      <p className="project-card-note">{item.note}</p>
      <div className="project-card-meta">
        <span>{item.kind}</span>
        <span>{item.year}</span>
      </div>
      <div className="project-card-arrow">↗</div>
    </button>
  );
}

/* ── App ── */
function App() {
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [openPanel, setOpenPanel]       = useState(null);
  const [origin, setOrigin]             = useState(null);
  const [revealed, setRevealed]         = useState(false);
  const [curtainLifted, setCurtainLifted] = useState(false);
  const [config, setConfig]             = useState(window.SITE_CONFIG);

  /* ── Live config updates from editor via postMessage ── */
  useEffect(() => {
    const handler = (e) => {
      if (e.data?.type === "CONFIG_UPDATE") {
        const c = e.data.config;
        setConfig(c);
        /* sync CSS vars */
        const r = document.documentElement;
        r.style.setProperty("--accent",   c.colors.accent);
        r.style.setProperty("--sunshine", c.colors.accent);
        document.body.dataset.type = c.colors.typeface;
        /* sync hero overlay */
        r.style.setProperty("--hero-overlay-opacity", String(c.colors.heroOverlay));
      }
      if (e.data?.type === "SCROLL_TO") {
        if (e.data.target === "top") window.scrollTo({ top: 0, behavior: "smooth" });
        else document.querySelector(e.data.target)?.scrollIntoView({ behavior: "smooth" });
      }
      if (e.data?.type === "OPEN_PANEL") {
        setOrigin({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
        setOpenPanel(e.data.panel);
      }
    };
    window.addEventListener("message", handler);
    /* signal ready to editor */
    window.parent?.postMessage({ type: "SITE_READY" }, "*");
    return () => window.removeEventListener("message", handler);
  }, []);

  useEffect(() => {
    const r = document.documentElement;
    r.style.setProperty("--accent",     tweaks.accent);
    r.style.setProperty("--sunshine",   tweaks.accent);
    r.style.setProperty("--hero-size",  tweaks.heroSize  + "vw");
    r.style.setProperty("--hero-line",  String(tweaks.heroLine));
    r.style.setProperty("--hero-track", tweaks.heroTrack + "em");
    r.style.setProperty("--hero-gap",   tweaks.heroGap   + "px");
    document.body.dataset.type = tweaks.type;
  }, [tweaks]);

  useEffect(() => {
    const t1 = setTimeout(() => setCurtainLifted(true), 350);
    const t2 = setTimeout(() => setRevealed(true),      900);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, []);

  const openWith = (id) => (e) => {
    const x = e?.clientX ?? window.innerWidth  / 2;
    const y = e?.clientY ?? window.innerHeight / 2;
    setOrigin({ x, y });
    setOpenPanel(id);
  };

  const closePanel = () => setOpenPanel(null);

  return (
    <ConfigContext.Provider value={config}>
    <>
      {/* Curtain */}
      <div className={"curtain" + (curtainLifted ? " lifted" : "")}>
        <div className="curtain-half top" />
        <div className="curtain-half bottom" />
        <div className="curtain-mark">— Riley&rsquo;s Living · Joyful Building™ · 2026 —</div>
      </div>

      <FrogCursor />
      <FrogTrail />
      <Sidebar onOpen={openWith} />

      <main className={"page" + (revealed ? " is-revealed" : "")}>

        {/* ── HERO — full-screen, centered, wear.gallery-inspired ── */}
        <section className="hero hero-full hero-v2" data-screen-label="01 Hero">
          <div className="hero-bg">
            <img src="assets/room.png" alt="" aria-hidden="true" />
            <div className="hero-overlay hero-overlay-v2" />
          </div>

          <div className="hero-v2-inner">
            <div className="eyebrow eyebrow--light hero-v2-eyebrow">{config.hero.eyebrow}</div>
            <h1 className="hero-v2-title">
              <span className="reveal-up"><span>riley&rsquo;s <em>living</em></span></span>
            </h1>
            <p className="hero-v2-tagline">{config.hero.tagline}</p>
          </div>

          <div className="hero-scroll-hint">
            <span className="mono">scroll</span>
            <div className="scroll-line" />
          </div>
        </section>

        {/* Marquee */}
        <div className="marquee" aria-hidden="true">
          <div className="marquee-track">
            <span>Joyful Building™</span><span className="dot">✺</span>
            <span>Systems · Stories · Structures</span><span className="dot">✺</span>
            <span>Available for projects · 2026</span><span className="dot">✺</span>
            <span>Writing · Workshops · Brand</span><span className="dot">✺</span>
            <span>Joyful Building™</span><span className="dot">✺</span>
            <span>Systems · Stories · Structures</span><span className="dot">✺</span>
            <span>Available for projects · 2026</span><span className="dot">✺</span>
          </div>
        </div>

        {/* ── PROJECTS — scroll-in card grid ── */}
        <section id="projects" className="projects-section">
          <header className="section-header">
            <div className="mono section-eyebrow">{config.work.sectionEyebrow}</div>
            <h2 className="section-title display">{config.work.sectionTitle}</h2>
          </header>
          <div className="project-cards-grid">
            {config.work.items.map((w, i) => (
              <ProjectCard key={w.n} item={w} index={i} onOpen={openWith("work")} />
            ))}
          </div>
          <div className="section-foot">
            <button className="pill-btn is-light" onClick={openWith("work")} data-cursor="hover">
              View all {config.work.items.length} projects <span className="arrow">&rarr;</span>
            </button>
          </div>
        </section>

        <ContactBlock />

        <footer className="botbar">
          <div className="left mono">
            <div>{config.footer.copyright}</div>
            <div style={{ opacity: 0.7, marginTop: 4 }}>{config.footer.tagline}</div>
          </div>
          <div className="right mono">
            <a href={config.footer.journalHref} target="_blank" rel="noopener noreferrer" data-cursor="hover" style={{ borderBottom: "1px solid currentColor" }}>
              {config.footer.journalLabel}
            </a>
          </div>
        </footer>
      </main>

      {/* Panels */}
      <Panel open={openPanel === "about"} origin={origin} onClose={closePanel} label="About" theme="">
        <AboutPanel />
        <PanelFooter label="About · Riley" />
      </Panel>

      <Panel open={openPanel === "work"} origin={origin} onClose={closePanel} label="Work" theme="theme-room">
        <div>
          <div className="work-intro">Selected <em>work,</em><br />always in construction.</div>
          <WorkPanel />
        </div>
        <PanelFooter label="Work · 8 entries" />
      </Panel>

      <Panel open={openPanel === "journal"} origin={origin} onClose={closePanel} label="Journal" theme="theme-pond">
        <div>
          <div className="work-intro">Field <em>notes</em> &amp;<br /><em>small theories.</em></div>
          <JournalPanel />
        </div>
        <PanelFooter label="Journal · monthly-ish" />
      </Panel>

      <Panel open={openPanel === "services"} origin={origin} onClose={closePanel} label="Products" theme="">
        <div>
          <div className="work-intro">What I can<br /><em>help you</em> build.</div>
          <ServicesPanel />
        </div>
        <PanelFooter label="Products · 3 services" />
      </Panel>

      <TweaksPanel title="Tweaks">
        <TweakSection title="Accent">
          <TweakColor
            label="Color"
            value={tweaks.accent}
            onChange={(v) => setTweak("accent", v)}
            presets={["#F2C84B", "#E86B5F", "#5C7A4E", "#8BAD6E", "#F2A99A", "#1C1A17"]}
          />
        </TweakSection>
        <TweakSection title="Type pairing">
          <TweakRadio value={tweaks.type} onChange={(v) => setTweak("type", v)} options={TYPE_OPTIONS} />
        </TweakSection>
        <TweakSection title="Hero spacing">
          <TweakSlider label="Size"        value={tweaks.heroSize}  onChange={(v) => setTweak("heroSize",  v)} min={6}     max={14}   step={0.25}  suffix="vw" />
          <TweakSlider label="Line height" value={tweaks.heroLine}  onChange={(v) => setTweak("heroLine",  v)} min={0.78}  max={1.2}  step={0.01} />
          <TweakSlider label="Tracking"   value={tweaks.heroTrack} onChange={(v) => setTweak("heroTrack", v)} min={-0.08} max={0.02} step={0.005} suffix="em" />
          <TweakSlider label="Gap"        value={tweaks.heroGap}   onChange={(v) => setTweak("heroGap",   v)} min={0}     max={80}   step={2}     suffix="px" />
        </TweakSection>
      </TweaksPanel>
    </>
    </ConfigContext.Provider>
  );
}

function PanelFooter({ label }) {
  return (
    <div className="botbar">
      <div className="left mono">{label}</div>
      <div className="center mono">— end —</div>
      <div className="right mono">Press ESC to close</div>
    </div>
  );
}

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