/* ── Stien — visual pieces: Blobs, Wordmark, small UI ──────────────────── */

const { useState, useEffect, useRef } = React;

/* A single watercolor / riso stamp — one organic shape with a roughened,
   mottled (under-inked) edge via an svg filter. Placed individually around
   the page so each stamp lives on its own, bleeding off the edges. */
function Blob({ color, w, h, radius, rot = 0, filter = "riso-a", className = "", style = {} }) {
  return (
    <div className={"stamp " + className} style={style} aria-hidden="true">
      <div
        className="stamp-ink"
        style={{
          background: color,
          width: w,
          height: h,
          borderRadius: radius,
          transform: `rotate(${rot}deg)`,
          filter: `url(#${filter})`,
        }}
      />
    </div>
  );
}

/* The STIEN wordmark — chunky letters, each in a palette colour, with a
   hand-placed wobble and a painterly roughened edge (svg filter). */
function Wordmark({ colors, className = "", style = {} }) {
  const letters = "STIEN".split("");
  const tilt = [-3, 2, -1.5, 2.5, -2];
  const dy = [2, -3, 1, -2, 3];
  return (
    <h1 className={"wordmark " + className} style={style} aria-label="Stien">
      {letters.map((ch, i) => (
        <span
          key={i}
          style={{
            color: colors[i % colors.length],
            transform: `rotate(${tilt[i]}deg) translateY(${dy[i]}px)`,
          }}
        >
          {ch}
        </span>
      ))}
    </h1>
  );
}

/* tiny inline icons (simple shapes only) */
function CopyIcon({ done }) {
  return done ? (
    <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 8.5l3.2 3.2L13 4.5" />
    </svg>
  ) : (
    <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.5">
      <rect x="5.5" y="5.5" width="8" height="8" rx="1.5" />
      <path d="M10.5 5.5V4A1.5 1.5 0 0 0 9 2.5H4A1.5 1.5 0 0 0 2.5 4v5A1.5 1.5 0 0 0 4 10.5h1.5" />
    </svg>
  );
}

/* a value row with a copy button, used in the Overschrijving tab */
function CopyRow({ label, value, mono = true }) {
  const [done, setDone] = useState(false);
  function copy() {
    navigator.clipboard && navigator.clipboard.writeText(value);
    setDone(true);
    setTimeout(() => setDone(false), 1400);
  }
  return (
    <button className="copyrow" onClick={copy} title="Kopieer">
      <span className="copyrow-label">{label}</span>
      <span className="copyrow-value" style={{ fontFamily: mono ? "var(--mono)" : "inherit" }}>
        {value}
      </span>
      <span className={"copyrow-icon" + (done ? " done" : "")}>
        <CopyIcon done={done} />
      </span>
    </button>
  );
}

/* The product preview shown at the top of the pay-modal — a short description
   of what the gift actually is, plus a drop-in photo. Layout is switchable via
   the `variant` tweak (geen · banner · compact · groot). The photo slot
   persists per-gift, so a dropped image survives reloads. */
function GiftPreview({ gift, variant }) {
  if (variant === "geen") return null;

  const text = gift.detail || gift.omschrijving;
  const visual = gift.image
    ? <img className="gp-img" src={gift.image} alt="" aria-hidden="true" />
    : null;
  const slot = (shape, radius) =>
    React.createElement("image-slot", {
      id: "shot-" + gift.id,
      shape,
      radius: String(radius),
      placeholder: "sleep een foto van " + gift.titel.toLowerCase(),
    });

  if (variant === "compact") {
    return (
      <div className="gp gp-compact">
        {visual || slot("rounded", 12)}
        <p className="gp-desc">{text}</p>
      </div>
    );
  }

  if (variant === "groot") {
    return (
      <div className="gp gp-groot">
        {visual || slot("rounded", 18)}
        <p className="gp-desc">{text}</p>
      </div>
    );
  }

  /* banner (default) */
  return (
    <div className="gp gp-banner">
      {visual || slot("rounded", 16)}
      <p className="gp-desc">{text}</p>
    </div>
  );
}

/* The "mark as given" control in the pay-modal. Three test variants:
   · vinkje   — original checkbox (easy to mis-tap, easy to silently un-do)
   · knop     — one-tap to mark, but UN-marking (the risky bit) asks to confirm
   · bevestig — both marking and un-marking ask to confirm
   Confirm state is local and resets each time the modal re-opens. */
function ReserveControl({ variant, reserved, giftId, onReserve }) {
  const [step, setStep] = useState(null); // null | "give" | "undo"
  const mark = () => onReserve(giftId);

  if (variant === "vinkje") {
    return (
      <label className="reserve">
        <input type="checkbox" checked={reserved} onChange={mark} />
        <span>markeer als gegeven — zo weten anderen dat dit al gekozen is</span>
      </label>
    );
  }

  /* already given — un-marking is always confirmed (this is the dangerous edge) */
  if (reserved) {
    if (step === "undo") {
      return (
        <div className="reserve-confirm">
          <p>Toch niet gegeven? Anderen zien dit dan weer als beschikbaar.</p>
          <div className="reserve-confirm-row">
            <button className="rc-no" onClick={() => setStep(null)}>Laat staan</button>
            <button className="rc-yes" onClick={() => { mark(); setStep(null); }}>Ja, vrijgeven</button>
          </div>
        </div>
      );
    }
    return (
      <div className="reserve-done">
        <span className="rd-label">
          <span className="rd-check"><CheckMark /></span> Jij geeft dit cadeau
        </span>
        <button className="rd-undo" onClick={() => setStep("undo")}>toch niet?</button>
      </div>
    );
  }

  /* not yet given */
  if (variant === "bevestig" && step === "give") {
    return (
      <div className="reserve-confirm">
        <p>Zeker? Anderen zien dit cadeau dan als al gekozen.</p>
        <div className="reserve-confirm-row">
          <button className="rc-no" onClick={() => setStep(null)}>Annuleer</button>
          <button className="rc-yes" onClick={() => { mark(); setStep(null); }}>Ja, ik gaf dit</button>
        </div>
      </div>
    );
  }
  return (
    <button className="reserve-btn"
      onClick={variant === "bevestig" ? () => setStep("give") : mark}>
      Ik heb dit gegeven <span className="btn-arrow">→</span>
    </button>
  );
}

/* small check mark for the "given" state */
function CheckMark() {
  return (
    <svg viewBox="0 0 16 16" width="15" height="15" fill="none" stroke="currentColor"
      strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M3 8.5l3.2 3.2L13 4.5" />
    </svg>
  );
}

/* small thematic mark for the "fijn" card foot — sits where the index was.
   Simple geometric line icons to match the editorial, muted feel. */
function GiftMark({ name, size = 20 }) {
  const common = { width: size, height: size, viewBox: "0 0 24 24", className: "f-mark",
    fill: "none", stroke: "currentColor", strokeWidth: 1.6, "aria-hidden": true };
  if (name === "cookie") {
    return (
      <svg {...common} strokeLinejoin="round">
        {/* cookie outline with a scalloped bite cut from the top-right */}
        <path d="M12.3 3.2
                 A 9 9 0 1 0 20.8 15.0
                 A 3 3 0 0 1 15.2 9.4
                 A 3 3 0 0 1 12.3 3.2 Z" />
        <circle cx="9" cy="11" r="1.15" fill="currentColor" stroke="none" />
        <circle cx="11.6" cy="15" r="1.1" fill="currentColor" stroke="none" />
        <circle cx="7.7" cy="14.6" r="0.95" fill="currentColor" stroke="none" />
        <circle cx="9.6" cy="8" r="0.9" fill="currentColor" stroke="none" />
      </svg>
    );
  }
  if (name === "coin") {
    return (
      <svg {...common}>
        <circle cx="12" cy="12" r="9" />
        <text x="12" y="12.4" textAnchor="middle" dominantBaseline="central" stroke="none"
          fill="currentColor" style={{ font: "600 11px 'DM Mono', monospace" }}>€</text>
      </svg>
    );
  }
  return null;
}

Object.assign(window, { Blob, Wordmark, CopyIcon, CopyRow, GiftPreview, ReserveControl, CheckMark, GiftMark });
