// components-hero.jsx — Single-focus hero. Left: copy + CTAs. Right: hero image slot.
// No more decorative quill SVG; the typewriter mock lives as a fallback inside the slot.

function useTypewriter(paragraphs, opts = {}) {
  const { charDelay = 80, paraGap = 1400, restart = 0 } = opts;
  const [text, setText] = React.useState("");
  const [paraIdx, setParaIdx] = React.useState(0);

  React.useEffect(() => {
    setText("");
    setParaIdx(0);
  }, [restart]);

  React.useEffect(() => {
    if (!paragraphs.length) return;
    let active = true;
    let i = 0;
    const para = paragraphs[paraIdx % paragraphs.length];

    function typeNext() {
      if (!active) return;
      if (i <= para.length) {
        setText(para.slice(0, i));
        i++;
        const jitter = (Math.random() * 60) - 20;
        const last = para[i - 1];
        const punctPause = /[，。、；：!?？！,.;:]/.test(last) ? 240 : 0;
        setTimeout(typeNext, charDelay + jitter + punctPause);
      } else {
        setTimeout(() => {
          if (!active) return;
          setParaIdx((p) => p + 1);
        }, paraGap);
      }
    }
    const start = setTimeout(typeNext, 500);
    return () => { active = false; clearTimeout(start); };
  }, [paraIdx, paragraphs, charDelay, paraGap]);

  return text;
}

function DownloadSplit({ copy }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    function onDoc(e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, []);
  return (
    <div className="dl-split" data-open={open} ref={ref}>
      <button
        className="btn btn-ghost"
        onClick={() => setOpen((v) => !v)}
        aria-expanded={open}
      >
        {copy.hero.ctaSecondary}
        <svg className="icon" viewBox="0 0 24 24" style={{ width: 14, height: 14 }}>
          <polyline points="6 9 12 15 18 9" />
        </svg>
      </button>
      <div className="dl-menu" role="menu">
        <a href="/download/#desktop" role="menuitem"><span>{copy.hero.dlMac}</span><small>·dmg</small></a>
        <a href="/download/#desktop" role="menuitem"><span>{copy.hero.dlMacIntel}</span><small>·dmg</small></a>
        <a href="/download/#desktop" role="menuitem"><span>{copy.hero.dlWin}</span><small>·exe</small></a>
        <a href="/app/" role="menuitem"><span>{copy.hero.dlWeb}</span><small>·web</small></a>
      </div>
    </div>
  );
}

// Typewriter mock — shown as a styled fallback INSIDE the hero PicSlot
// until the user drops in a real screenshot at uploads/hero.webp.
function HeroProseFallback({ copy, lang }) {
  const txt = useTypewriter(copy.typewriter.paragraphs, {
    charDelay: lang === "zh" ? 95 : 35,
    paraGap: 1600,
    restart: lang,
  });
  return (
    <div className="hero-fallback">
      <div className="hero-fallback__chrome">
        <div className="hero-fallback__traffic"><i></i><i></i><i></i></div>
        <div className="hero-fallback__crumb">
          {lang === "zh" ? "雨中客 / 卷一 / 第 1 章 · 破庙夜雨" : "Rainy Guest / Book I / Ch. 1 · Rain at the Temple"}
        </div>
      </div>
      <div className="hero-fallback__page">
        <h4>{copy.typewriter.title}</h4>
        <p>
          {txt}
          <span className="caret" />
        </p>
      </div>
      <div className="hero-fallback__foot">
        <span>{lang === "zh" ? "第 1 章 · 破庙夜雨" : "Ch. 1 · Rain at the Temple"}</span>
        <span>· {lang === "zh" ? "3,182 字" : "3,182 words"}</span>
        <span>· {lang === "zh" ? "已保存 09:42" : "Saved 09:42"}</span>
        <span>· {lang === "zh" ? "本地" : "Local"}</span>
      </div>
    </div>
  );
}

function Hero({ copy, lang }) {
  const heroSrc = "uploads/hero.png";
  return (
    <section className="hero" id="top">
      <div className="shell hero-grid">
        <div className="hero-copy">
          <h1 className="h1 hero-title">
            <span className="line"><span className="ink-stroke">{copy.hero.titleA}</span></span>
            <span className="line"><span className="ink-stroke">{copy.hero.titleB}</span></span>
          </h1>
          <p className="hero-sub">{copy.hero.sub}</p>
        </div>

        <div className="hero-stage">
          <HeroShot src={heroSrc} copy={copy} lang={lang} />
        </div>
      </div>
    </section>
  );
}

// Tries to load the hero image; falls back to the prose-mockup component above.
// Wrapped in a card so the fallback feels intentional, not broken.
function HeroShot({ src, copy, lang }) {
  const [errored, setErrored] = React.useState(false);
  const [loaded, setLoaded]   = React.useState(false);
  const showImg = src && window.UPLOADED_IMAGES && window.UPLOADED_IMAGES.has(src) && !errored;

  return (
    <div className="hero-shot" data-loaded={loaded ? "1" : "0"}>
      {showImg && (
        <img
          src={src}
          alt={lang === "zh" ? "笔随写作界面截图" : "Novel Studio writing interface"}
          className="hero-shot__img"
          onLoad={() => setLoaded(true)}
          onError={() => setErrored(true)}
        />
      )}
      {(!showImg || !loaded) && (
        <div className="hero-shot__fallback">
          <HeroProseFallback copy={copy} lang={lang} />
          <div className="hero-shot__hint">
            <span className="pic-slot__dot" />
            HERO · <code>{src}</code>
            <small>{lang === "zh"
              ? "上传一张真实写作界面截图替换此区域"
              : "Drop a real product screenshot here"}</small>
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { Hero, HeroShot, HeroProseFallback, DownloadSplit, useTypewriter });
