/* global React */
const { useState, useRef, useEffect, useCallback } = React;

/* ---------------------------------------------------------------------------
   Small primitives
--------------------------------------------------------------------------- */

function Eyebrow({ children }) {
  return <span className="eyebrow"><span className="t-label">{children}</span></span>;
}

function Chip({ children, solid }) {
  return <span className={"chip" + (solid ? " chip--solid" : "")}>{children}</span>;
}

function Caption({ title, proof, detail, align }) {
  return (
    <figcaption className="caption" style={{ textAlign: align || "left" }}>
      <span className="caption__title">{title}</span>
      {proof && <span className="caption__proof">{proof}</span>}
      {detail && <span className="caption__detail">{detail}</span>}
    </figcaption>
  );
}

/* A drop-in image slot wrapper that keeps a known aspect ratio.
   `id` MUST be unique + stable for the dropped photo to persist.
   `src` sets the default real photo (user drop overrides it). */
function Photo({ id, ratio = "4 / 5", radius = 12, placeholder, shape = "rounded", src, alt, className, style }) {
  return (
    <image-slot
      id={id}
      shape={shape}
      radius={String(radius)}
      src={src || undefined}
      aria-label={alt || placeholder || "Photographie Poterie du Bousquet"}
      placeholder={placeholder || "Déposez une photo"}
      class={"photo " + (className || "")}
      style={{ width: "100%", height: "auto", aspectRatio: ratio, display: "block", ...(style || {}) }}
    ></image-slot>
  );
}

/* Chapter heading block (roman numeral + kicker + title + intro) */
function ChapterHead({ numeral, kicker, title, intro, align = "left" }) {
  return (
    <header className="chapterhead" style={{ textAlign: align, alignItems: align === "center" ? "center" : "flex-start" }}>
      <div className="chapterhead__num">
        <span className="chapterhead__roman">{numeral}</span>
        <span className="t-chapter">{kicker}</span>
      </div>
      <h2 className="t-h2" style={{ maxWidth: "18ch" }}>{title}</h2>
      {intro && <p className="t-lead measure" style={{ marginInline: align === "center" ? "auto" : 0 }}>{intro}</p>}
    </header>
  );
}

/* ---------------------------------------------------------------------------
   Diptych — Dedans ↔ Dehors, with Salon/Terrasse toggle
--------------------------------------------------------------------------- */
function Diptych({ mode, panels }) {
  // panels: { salon: [{id,placeholder,caption}], terrasse: [...] }
  const set = panels[mode] || panels.salon;
  return (
    <div className="diptych">
      <div className="diptych__pair">
        {set.map((p, i) => (
          <figure className="diptych__panel" key={p.id}>
            <span className={"diptych__tag t-label"} data-side={i === 0 ? "in" : "out"}>
              {i === 0 ? "Dedans" : "Dehors"}
            </span>
            <Photo id={p.id} ratio="1 / 1" radius={12} placeholder={p.placeholder} src={p.src} alt={p.alt} />
            <Caption {...p.caption} />
          </figure>
        ))}
      </div>
    </div>
  );
}

/* ---------------------------------------------------------------------------
   Before / After slider (drag handle on desktop, tabs on mobile)
--------------------------------------------------------------------------- */
function BeforeAfter({ beforeId, afterId, beforePh, afterPh, beforeSrc, afterSrc, note }) {
  const [pos, setPos] = useState(58);   // % from left = how much AVANT is shown
  const [mode, setMode] = useState("split"); // for mobile tabs: 'before' | 'after' | 'split'
  const wrapRef = useRef(null);
  const draggingRef = useRef(false);

  const updateFromClientX = useCallback((clientX) => {
    const el = wrapRef.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    let p = ((clientX - r.left) / r.width) * 100;
    p = Math.max(0, Math.min(100, p));
    setPos(p);
  }, []);

  useEffect(() => {
    const move = (e) => {
      if (!draggingRef.current) return;
      const x = e.touches ? e.touches[0].clientX : e.clientX;
      updateFromClientX(x);
      if (e.cancelable) e.preventDefault();
    };
    const up = () => { draggingRef.current = false; document.body.style.userSelect = ""; };
    window.addEventListener("mousemove", move);
    window.addEventListener("touchmove", move, { passive: false });
    window.addEventListener("mouseup", up);
    window.addEventListener("touchend", up);
    return () => {
      window.removeEventListener("mousemove", move);
      window.removeEventListener("touchmove", move);
      window.removeEventListener("mouseup", up);
      window.removeEventListener("touchend", up);
    };
  }, [updateFromClientX]);

  const startDrag = (e) => {
    draggingRef.current = true;
    document.body.style.userSelect = "none";
    const x = e.touches ? e.touches[0].clientX : e.clientX;
    updateFromClientX(x);
  };

  const onKey = (e) => {
    if (e.key === "ArrowLeft") { setPos((p) => Math.max(0, p - 4)); e.preventDefault(); }
    if (e.key === "ArrowRight") { setPos((p) => Math.min(100, p + 4)); e.preventDefault(); }
    if (e.key === "Home") { setPos(0); e.preventDefault(); }
    if (e.key === "End") { setPos(100); e.preventDefault(); }
  };

  // mobile tab override
  const effectivePos = mode === "before" ? 100 : mode === "after" ? 0 : pos;

  return (
    <div className="ba">
      <div
        className="ba__stage"
        ref={wrapRef}
        onMouseDown={startDrag}
        onTouchStart={startDrag}
      >
        {/* base layer = APRÈS */}
        <div className="ba__layer">
          <Photo id={afterId} ratio="16 / 10" radius={12} placeholder={afterPh} src={afterSrc} />
          <span className="ba__chip ba__chip--after t-label">Après</span>
        </div>
        {/* top layer = AVANT, clipped to left `pos`% */}
        <div className="ba__layer ba__layer--top" style={{ clipPath: `inset(0 ${100 - effectivePos}% 0 0)` }}>
          <Photo id={beforeId} ratio="16 / 10" radius={12} placeholder={beforePh} src={beforeSrc} />
          <span className="ba__chip ba__chip--before t-label">Avant</span>
        </div>
        {/* handle */}
        <div className="ba__handle" style={{ left: `${effectivePos}%` }} aria-hidden={mode !== "split"}>
          <button
            className="ba__grip"
            role="slider"
            aria-label="Comparer avant et après"
            aria-valuemin={0}
            aria-valuemax={100}
            aria-valuenow={Math.round(effectivePos)}
            aria-valuetext={`${Math.round(effectivePos)}% avant`}
            tabIndex={0}
            onKeyDown={onKey}
            onMouseDown={(e) => e.stopPropagation()}
            onTouchStart={(e) => e.stopPropagation()}
          >
            <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <polyline points="9 6 4 12 9 18"></polyline>
              <polyline points="15 6 20 12 15 18"></polyline>
            </svg>
          </button>
        </div>
      </div>

      <div className="ba__foot">
        {/* Mobile-first accessible tabs (also usable on desktop) */}
        <div className="ba__tabs" role="tablist" aria-label="Avant / Après">
          <button role="tab" aria-selected={mode === "before"} className={"ba__tab" + (mode === "before" ? " is-on" : "")} onClick={() => setMode("before")}>Avant</button>
          <button role="tab" aria-selected={mode === "split"} className={"ba__tab" + (mode === "split" ? " is-on" : "")} onClick={() => setMode("split")}>Comparer</button>
          <button role="tab" aria-selected={mode === "after"} className={"ba__tab" + (mode === "after" ? " is-on" : "")} onClick={() => setMode("after")}>Après</button>
        </div>
        {note && <p className="t-caption ba__note">{note}</p>}
      </div>
    </div>
  );
}

/* ---------------------------------------------------------------------------
   Accordion (FAQ)
--------------------------------------------------------------------------- */
function Accordion({ items }) {
  const [open, setOpen] = useState(0);
  return (
    <div className="acc">
      {items.map((it, i) => {
        const isOpen = open === i;
        return (
          <div className={"acc__item" + (isOpen ? " is-open" : "")} key={i}>
            <h3 className="acc__h">
              <button
                className="acc__btn"
                aria-expanded={isOpen}
                onClick={() => setOpen(isOpen ? -1 : i)}
              >
                <span>{it.q}</span>
                <span className="acc__icon" aria-hidden="true"></span>
              </button>
            </h3>
            <div className="acc__panel" role="region" hidden={!isOpen}>
              <p className="t-body" style={{ color: "var(--color-text-1)" }}>{it.a}</p>
            </div>
          </div>
        );
      })}
    </div>
  );
}

/* ---------------------------------------------------------------------------
   Collection card
--------------------------------------------------------------------------- */
function CollectionCard({ photoId, placeholder, src, name, blurb, tags }) {
  return (
    <article className="ccard">
      <Photo id={photoId} ratio="1 / 1" radius={8} placeholder={placeholder} src={src} className="ccard__img" />
      <div className="ccard__body">
        <h3 className="t-h3 ccard__name">{name}</h3>
        <p className="t-small">{blurb}</p>
        <ul className="ccard__tags">
          {tags.map((t) => <li key={t}><Chip>{t}</Chip></li>)}
        </ul>
        <a className="btn btn--tertiary ccard__cta" href="#">Voir la collection
          <svg className="btn__arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
        </a>
      </div>
    </article>
  );
}

/* ---------------------------------------------------------------------------
   Geste (macro matière) card
--------------------------------------------------------------------------- */
function GesteCard({ n, photoId, placeholder, src, title, text }) {
  return (
    <figure className="geste">
      <Photo id={photoId} ratio="1 / 1" radius={8} placeholder={placeholder} src={src} />
      <div className="geste__body">
        <span className="t-chapter">{n}</span>
        <h3 className="t-h3">{title}</h3>
        <p className="t-small">{text}</p>
      </div>
    </figure>
  );
}

/* Icon (monoline) */
function Icon({ name, size = 24 }) {
  const common = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true };
  const paths = {
    inout: <><path d="M3 21V9l9-6 9 6v12" /><path d="M12 3v18" /><path d="M3 13h6M15 13h6" /></>,
    sizes: <><rect x="3" y="13" width="5" height="8" rx="1" /><rect x="9.5" y="8" width="5" height="13" rx="1" /><rect x="16" y="3" width="5" height="18" rx="1" /></>,
    atelier: <><path d="M4 21h16" /><path d="M6 21V10l6-5 6 5v11" /><path d="M10 21v-5h4v5" /><circle cx="12" cy="9" r="1" /></>,
    matiere: <><circle cx="12" cy="12" r="9" /><path d="M12 3a9 9 0 0 0 0 18" /><path d="M5 8c3 1 6 1 9-1M5 16c4 1 8 0 12-3" /></>,
    leaf: <><path d="M11 20A7 7 0 0 1 4 13c0-5 5-9 16-9 0 8-4 13-9 16Z" /><path d="M4 21c4-6 8-9 12-10" /></>,
    pin: <><path d="M12 21s7-6.5 7-12a7 7 0 1 0-14 0c0 5.5 7 12 7 12Z" /><circle cx="12" cy="9" r="2.5" /></>,
  };
  return <svg {...common}>{paths[name] || paths.matiere}</svg>;
}

Object.assign(window, {
  Eyebrow, Chip, Caption, Photo, ChapterHead, Diptych, BeforeAfter, Accordion, CollectionCard, GesteCard, Icon,
});
