/* ============================================================
   TIMELINE — experience + projects
   ============================================================ */

function Bullet({ b }) {
  return (
    <li>
      {b.text}
      {b.metric && <span className="metric">{b.metric}</span>}
      {b.tail}
      {b.metric2 && <span className="metric">{b.metric2}</span>}
      {b.tail2}
    </li>
  );
}

/* ----- Gallery bundles: one visible stacked preview opens a modal carousel ----- */
function GalleryBundle({ gallery, onOpen }) {
  const images = gallery.images || [];
  const cover = images[0];
  const [errored, setErrored] = useState(false);
  const count = images.length;
  return (
    <button
      type="button"
      className="tl-bundle"
      title={`open ${gallery.label}`}
      aria-label={`Open ${gallery.label} gallery`}
      onClick={() => onOpen(gallery)}
    >
      <span className="bundle-stack" aria-hidden="true" />
      <span className="bundle-cover">
        {cover && !errored
          ? <img src={cover} alt={gallery.label} onError={() => setErrored(true)} />
          : <span className="ph-label">[ {gallery.label} ]</span>}
      </span>
      <span className="bundle-meta">
        <span className="bundle-name">{gallery.label}</span>
        <span className="bundle-count">{count} {count === 1 ? "image" : "images"}</span>
      </span>
    </button>
  );
}

function GalleryModal({ gallery, onClose }) {
  const [idx, setIdx] = useState(0);
  const [errors, setErrors] = useState({});
  const images = gallery?.images || [];
  const active = images[idx];
  const count = images.length;

  useEffect(() => {
    if (!gallery) return;
    setIdx(0);
    setErrors({});
    document.body.classList.add("modal-open");
    const onKey = (e) => {
      if (e.key === "Escape") onClose();
      if (count > 1 && e.key === "ArrowRight") setIdx(i => (i + 1) % count);
      if (count > 1 && e.key === "ArrowLeft") setIdx(i => (i - 1 + count) % count);
    };
    window.addEventListener("keydown", onKey);
    return () => {
      document.body.classList.remove("modal-open");
      window.removeEventListener("keydown", onKey);
    };
  }, [gallery, count, onClose]);

  if (!gallery) return null;

  const markError = (src) => setErrors(prev => ({ ...prev, [src]: true }));
  const next = () => { if (count > 1) setIdx(i => (i + 1) % count); };
  const prev = () => { if (count > 1) setIdx(i => (i - 1 + count) % count); };

  return (
    <div
      className="gallery-modal"
      role="dialog"
      aria-modal="true"
      aria-label={`${gallery.label} images`}
      onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}
    >
      <div className="gallery-modal-panel">
        <div className="gallery-modal-head">
          <div>
            <span className="gm-label">{gallery.label}</span>
            <span className="gm-count">{idx + 1}/{count}</span>
          </div>
          <button type="button" className="gm-close" aria-label="Close gallery" onClick={onClose}>×</button>
        </div>

        <div className="gallery-modal-stage">
          {active && !errors[active]
            ? <img src={active} alt={`${gallery.label} ${idx + 1}`} onError={() => markError(active)} />
            : (
              <div className="gm-empty">
                <span>[ {gallery.label} {idx + 1} ]</span>
                {active && <code>{active}</code>}
              </div>
            )}
          {count > 1 && (
            <>
              <button type="button" className="gm-nav prev" aria-label="Previous image" onClick={prev}>‹</button>
              <button type="button" className="gm-nav next" aria-label="Next image" onClick={next}>›</button>
            </>
          )}
        </div>

        {count > 1 && (
          <div className="gallery-modal-thumbs">
            {images.map((src, i) => (
              <button
                type="button"
                key={`${src}-${i}`}
                className={"gm-thumb " + (i === idx ? "active " : "") + (errors[src] ? "missing" : "")}
                onClick={() => setIdx(i)}
                aria-label={`Show image ${i + 1}`}
              >
                {src && !errors[src]
                  ? <img src={src} alt="" onError={() => markError(src)} />
                  : <span>{i + 1}</span>}
              </button>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

function TimelineItem({ item, kind = "exp" }) {
  const [ref, inView] = useInView();
  const [modalGallery, setModalGallery] = useState(null);
  return (
    <div ref={ref} className={"tl-item " + (inView ? "in" : "")}>
      <div className="tl-node" />
      <div className="tl-meta">
        {item.date && <span className="date">{item.date}</span>}
        {item.location && <span className="loc">{item.location}</span>}
        {item.tagline && <span style={{ color: "var(--fg-dim)", fontStyle: "italic" }}>{item.tagline}</span>}
      </div>
      <h3 className="tl-title">
        {kind === "exp" ? (
          <>
            <span className="role">{item.role}</span>
            <span className="at">@</span>
            <span className="company">{item.company}</span>
          </>
        ) : (
          <span className="company">{item.name}</span>
        )}
      </h3>
      {item.url && (
        <a className="tl-url" href={item.url} target="_blank" rel="noopener">
          <span className="tl-url-arrow">↗</span> {item.urlLabel || item.url}
        </a>
      )}
      <ul className="tl-bullets">
        {item.bullets.map((b, i) => <Bullet key={i} b={b} />)}
      </ul>
      {item.galleries && item.galleries.length > 0 && (
        <div className="tl-images">
          {item.galleries.map((g, i) => (
            <GalleryBundle key={i} gallery={g} onOpen={setModalGallery} />
          ))}
        </div>
      )}
      <GalleryModal gallery={modalGallery} onClose={() => setModalGallery(null)} />
      <div className="tl-stack">
        {item.stack.map((t, i) => <span key={i} className="tag">{t}</span>)}
      </div>
    </div>
  );
}

function ExperienceSection() {
  return (
    <section data-screen-label="experience">
      <PromptRow cmd="cat" flags={["experience.log"]} comment="current + past roles" />
      <SectionHeader hash="01" title="experience" subtitle="shipping at startups. backend, AI, infra." />
      <div className="timeline">
        {EXPERIENCE.map((e, i) => <TimelineItem key={i} item={e} kind="exp" />)}
      </div>
    </section>
  );
}

function ProjectsSection() {
  return (
    <section data-screen-label="projects">
      <PromptRow cmd="ls" flags={["-lah", "~/projects/"]} comment="selected works" />
      <SectionHeader hash="02" title="projects" subtitle="tools built because the existing ones weren't good enough." />
      <div className="timeline">
        {PROJECTS.map((p, i) => <TimelineItem key={i} item={p} kind="proj" />)}
      </div>
    </section>
  );
}

Object.assign(window, { ExperienceSection, ProjectsSection });
