/* Shared UI bits — Plate placeholder, Reveal wrapper, image-slot wrapper */
const { useEffect, useRef, useState } = React;

/* Plate — Color-tinted block holding either a name stamp or an image-slot.
   `tile` is the CSS color used as the placeholder's base tint. */
function Plate({ tile, name, subName, corner, className = "", style, light = false, children }) {
  const cssVar = tile ? { "--tile": tile } : {};
  return (
    <div className={`plate-wrap ${className}`} style={style}>
      <div className={`plate ${light ? "plate--light" : ""}`} style={cssVar}>
        {children}
        {name && (
          <div className="name-stamp">
            {name}
            {subName && <span className="sub">{subName}</span>}
          </div>
        )}
        {corner && <span className="corner">{corner}</span>}
      </div>
    </div>
  );
}

/* ImagePlate — user-fillable image-slot stacked on a Plate so the design
   looks complete with no images dropped, and beautifully when they are.
   `src` is an author-provided fallback image (catalog AI renders); a user
   drop on the slot always overrides it. */
function ImagePlate({ id, src, tile, name, subName, corner, placeholder, shape, className = "", style, light = false }) {
  const cssVar = tile ? { "--tile": tile } : {};
  // Light tile = use dark text for slot's empty hint
  const slotStyle = {
    position: "absolute",
    inset: 0,
    "--slot-bg": "transparent",
    "--slot-border": light ? "rgba(20,20,20,0.25)" : "rgba(241,238,232,0.4)",
    "--slot-color": light ? "rgba(20,20,20,0.55)" : "rgba(241,238,232,0.85)",
  };
  return (
    <div className={`plate-wrap ${className}`} style={style}>
      <div className={`plate ${light ? "plate--light" : ""}`} style={cssVar}>
        <image-slot
          id={id}
          src={src || undefined}
          shape={shape || "rect"}
          placeholder={placeholder || (name ? `${name}${subName ? " · " + subName : ""}` : "")}
          style={slotStyle}
        ></image-slot>
        {corner && <span className="corner" style={{ pointerEvents: "none" }}>{corner}</span>}
      </div>
    </div>
  );
}

/* Reveal — fade + lift on intersect */
function Reveal({ children, delay = 0, as: As = "div", className = "", ...rest }) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(
      (entries) => entries.forEach((e) => {
        if (e.isIntersecting) { setSeen(true); io.unobserve(e.target); }
      }),
      { threshold: 0.1, rootMargin: "0px 0px -8% 0px" }
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return (
    <As ref={ref} className={`reveal ${delay ? `d${delay}` : ""} ${seen ? "is-in" : ""} ${className}`} {...rest}>
      {children}
    </As>
  );
}

/* Decide if a tile color is "light" (so text on it should be dark) */
function isLightTile(hex) {
  const m = /^#?([a-f\d]{6})$/i.exec(hex || "");
  if (!m) return false;
  const v = parseInt(m[1], 16);
  const r = (v >> 16) & 255, g = (v >> 8) & 255, b = v & 255;
  const L = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;
  return L > 0.62;
}

Object.assign(window, { Plate, ImagePlate, Reveal, isLightTile });
