// Octopak website — shared helpers, icons, and the placeholder/flag system.
// No invented Octopak copy lives here; <PH>/<Flag> mark anything that needs
// real words or confirmed facts.
const { Button, ProductCard } = window.OctopakDesignSystem_bc06ed;

/* --- Contact constants (from the build brief) ----------------------------- */
const WA_NUMBER = "+6588628680";
const waLink = (text) =>
  `https://wa.me/${WA_NUMBER.replace(/[^0-9]/g, "")}?text=${encodeURIComponent(text || "Hello! I'd like to customise some packaging for my brand")}`;
const WA_DEFAULT = "Hello! I'd like to customise some packaging for my brand";

/* --- Routing -----------------------------------------------------------------
   The app's internal "route" strings (e.g. "products/coffee-cups",
   "contact?family=pouches", "guide#flexo") are also the shape `onNavigate`
   expects. This turns one into the real, shareable URL path so every <a href>
   points at where a click actually goes — not just a "#" placeholder — and
   index.html's history.pushState can reuse the same conversion. */
function routeToHref(route) {
  const hashIdx = route.indexOf("#");
  const routeNoHash = hashIdx >= 0 ? route.slice(0, hashIdx) : route;
  const anchor = hashIdx >= 0 ? route.slice(hashIdx + 1) : "";
  const [path, qs] = routeNoHash.split("?");
  const base = !path || path === "home" ? "/" : `/${path}`;
  return base + (qs ? `?${qs}` : "") + (anchor ? `#${anchor}` : "");
}

/* --- Icons (Lucide-style, 1.75px stroke) ---------------------------------- */
function Icon({ name, size = 24, className = "" }) {
  const common = {
    width: size, height: size, viewBox: "0 0 24 24", fill: "none",
    stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round",
    strokeLinejoin: "round", className,
  };
  const paths = {
    "arrow-right": <><path d="M5 12h14" /><path d="m13 5 7 7-7 7" /></>,
    menu: <><path d="M4 6h16" /><path d="M4 12h16" /><path d="M4 18h16" /></>,
    x: <><path d="M18 6 6 18" /><path d="M6 6l12 12" /></>,
    message: <path d="M7.9 20A9 9 0 1 0 4 16.1L2 22z" />,
    pen: <><path d="M12 20h9" /><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z" /></>,
    check: <><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" /><path d="m9 11 3 3L22 4" /></>,
    box: <><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z" /><path d="m3.3 7 8.7 5 8.7-5" /><path d="M12 22V12" /></>,
    truck: <><path d="M14 18V6a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h1" /><path d="M14 9h4l3 3v5a1 1 0 0 1-1 1h-1" /><circle cx="7.5" cy="18.5" r="2" /><circle cx="17.5" cy="18.5" r="2" /></>,
    users: <><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" /><circle cx="9" cy="7" r="4" /><path d="M22 21v-2a4 4 0 0 0-3-3.87" /><path d="M16 3.13a4 4 0 0 1 0 7.75" /></>,
    palette: <><circle cx="13.5" cy="6.5" r=".9" /><circle cx="17.5" cy="10.5" r=".9" /><circle cx="8.5" cy="7.5" r=".9" /><circle cx="6.5" cy="12.5" r=".9" /><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.9 0 1.6-.7 1.6-1.5 0-.4-.2-.8-.4-1-.3-.3-.4-.6-.4-1 0-.8.7-1.5 1.5-1.5H16c3.3 0 6-2.7 6-6 0-4.9-4.5-9-10-9Z" /></>,
    sliders: <><line x1="4" x2="4" y1="21" y2="14" /><line x1="4" x2="4" y1="10" y2="3" /><line x1="12" x2="12" y1="21" y2="12" /><line x1="12" x2="12" y1="8" y2="3" /><line x1="20" x2="20" y1="21" y2="16" /><line x1="20" x2="20" y1="12" y2="3" /><line x1="2" x2="6" y1="14" y2="14" /><line x1="10" x2="14" y1="8" y2="8" /><line x1="18" x2="22" y1="16" y2="16" /></>,
    leaf: <><path d="M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z" /><path d="M2 21c0-3 1.85-5.36 5.08-6" /></>,
    ruler: <><path d="M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.4 2.4 0 0 1 0-3.4l2.6-2.6a2.4 2.4 0 0 1 3.4 0Z" /><path d="m14.5 12.5 2-2" /><path d="m11.5 9.5 2-2" /><path d="m8.5 6.5 2-2" /><path d="m17.5 15.5 2-2" /></>,
    droplet: <path d="M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z" />,
    layers: <><path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z" /><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65" /><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65" /></>,
    printer: <><path d="M6 9V2h12v7" /><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2" /><rect x="6" y="14" width="12" height="8" rx="1" /></>,
    mail: <><rect width="20" height="16" x="2" y="4" rx="2" /><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" /></>,
    phone: <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92Z" />,
    chevron: <path d="m6 9 6 6 6-6" />,
    map: <><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" /><circle cx="12" cy="10" r="3" /></>,
    file: <><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" /><path d="M14 2v6h6" /></>,
    sparkle: <path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.6 5.6l2.8 2.8M15.6 15.6l2.8 2.8M18.4 5.6l-2.8 2.8M8.4 15.6l-2.8 2.8" />,
  };
  return <svg {...common} aria-hidden="true">{paths[name] || null}</svg>;
}

/* WhatsApp brand glyph (filled) */
function WhatsAppGlyph({ size = 22 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
      <path d="M.057 24l1.687-6.163a11.867 11.867 0 0 1-1.587-5.946C.16 5.335 5.495 0 12.05 0a11.817 11.817 0 0 1 8.413 3.488 11.824 11.824 0 0 1 3.48 8.414c-.003 6.557-5.338 11.892-11.893 11.892a11.9 11.9 0 0 1-5.688-1.448L.057 24zm6.597-3.807c1.676.995 3.276 1.591 5.392 1.592 5.448 0 9.886-4.434 9.889-9.885.002-5.462-4.415-9.89-9.881-9.892-5.452 0-9.887 4.434-9.889 9.884a9.86 9.86 0 0 0 1.51 5.26l-.999 3.648 3.978-1.607zm11.387-5.464c-.074-.124-.272-.198-.57-.347-.297-.149-1.758-.868-2.031-.967-.272-.099-.47-.149-.669.149-.198.297-.768.967-.941 1.165-.173.198-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.501-.669-.51l-.57-.01c-.198 0-.52.074-.792.372s-1.04 1.017-1.04 2.479 1.065 2.876 1.213 3.074c.149.198 2.095 3.2 5.076 4.487.709.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.29.173-1.414z" />
    </svg>
  );
}

/* --- Placeholder + flag primitives ---------------------------------------- */
// Inline draft copy. Renders the descriptive note in placeholder style.
function PH({ children }) {
  return <span className="ph" title="Placeholder, final copy to be written against the brand guide">{children}</span>;
}
// Block of draft body copy.
function PHBlock({ children, style }) {
  return <p className="ph-block" style={style} title="Placeholder, final copy to be written against the brand guide">{children}</p>;
}
// Unconfirmed fact flag (open decisions, brief §14).
function Flag({ children = "to confirm", block = false }) {
  return <span className={`flag ${block ? "flag--block" : ""}`} title="Unconfirmed, open decision for Gail (brief §14)">{children}</span>;
}

/* --- Section head --------------------------------------------------------- */
function SectionHead({ eyebrow, title, intro, center, action }) {
  return (
    <div className={`section__head ${center ? "section__head--center" : ""}`}>
      <div>
        {eyebrow && <p className="octo-eyebrow">{eyebrow}</p>}
        <h2 className="section__title">{title}</h2>
        {intro && <p className="section__intro">{intro}</p>}
      </div>
      {action}
    </div>
  );
}

/* --- Image slot wrapper --------------------------------------------------- */
// Drop-in image placeholder. Pass `src` to wire a real photo (e.g. from
// assets/photos/). Distinct id per slot.
// Wrapped in a .media-frame: the frame is the fixed box that scroll-reveals and
// clips, while the inner slot carries the slow framed hover-zoom (Aesop-style).
// A `src` is only handed to the slot once we have confirmed the file actually
// loads, so a missing photo falls back to the placeholder rather than showing a
// broken image.
function MediaSlot({ id, placeholder = "Drop a photo", radius = 14, shape = "rounded", src, style, className = "" }) {
  const [okSrc, setOkSrc] = React.useState(null);
  React.useEffect(() => {
    if (!src) { setOkSrc(null); return; }
    let live = true;
    const probe = new Image();
    probe.onload = () => { if (live) setOkSrc(src); };
    probe.onerror = () => { if (live) setOkSrc(null); };
    probe.src = src;
    return () => { live = false; };
  }, [src]);

  const attrs = {
    id, placeholder, shape, radius: String(radius),
    class: `media-slot ${className}`.trim(),
  };
  if (okSrc) attrs.src = okSrc;

  return React.createElement(
    "div",
    { className: "media-frame", style: { ...style, borderRadius: Number(radius) || 0 } },
    React.createElement("image-slot", attrs)
  );
}

/* --- Product grid tile ------------------------------------------------------
   Wraps the design-system ProductCard. When a family has `image` +
   `imageHover`, the hover photo is layered on top (fades in on hover) — the
   design-system bundle itself isn't touched, this just overlays a second
   <img> sized to match ProductCard's media block. Families without photos
   yet fall back to ProductCard's plain title-on-kraft placeholder. */
function ProductTile({ family, onNavigate }) {
  return (
    <a className={`product-link ${family.secondary ? "is-secondary" : ""}`}
      href={routeToHref(`products/${family.slug}`)}
      onClick={(e) => { e.preventDefault(); onNavigate(`products/${family.slug}`); }}>
      <ProductCard title={family.name} description={family.wedge} image={family.image} />
      {family.image && family.imageHover && (
        <img className="product-link__hover-img" src={family.imageHover} alt="" aria-hidden="true" />
      )}
    </a>
  );
}

/* --- Carousel (multi-photo case studies, product galleries) ---------------
   `slides` is an array of { src, placeholder }. Renders one MediaSlot per
   slide, cross-fading between them — arrows + dots only appear once there's
   more than one photo, so a single-photo carousel degrades to a plain frame. */
function Carousel({ id, slides = [], radius = 0, style }) {
  const [index, setIndex] = React.useState(0);
  const count = slides.length;
  if (!count) return null;
  const go = (delta) => setIndex((i) => (i + delta + count) % count);

  return (
    <div className="carousel">
      <div className="carousel__viewport" style={{ ...style, borderRadius: Number(radius) || 0 }}>
        {slides.map((s, i) => (
          <div className={`carousel__slide${i === index ? " is-active" : ""}`} key={i} aria-hidden={i !== index}>
            <MediaSlot id={`${id}-${i}`} src={s.src} placeholder={s.placeholder || "Customised work photo"} radius={radius} shape="rect" style={{ width: "100%", height: "100%" }} />
          </div>
        ))}
      </div>
      {count > 1 && (
        <>
          <button type="button" className="carousel__arrow carousel__arrow--prev" onClick={() => go(-1)} aria-label="Previous photo">‹</button>
          <button type="button" className="carousel__arrow carousel__arrow--next" onClick={() => go(1)} aria-label="Next photo">›</button>
          <div className="carousel__dots" role="tablist">
            {slides.map((_, i) => (
              <button type="button" key={i} role="tab" aria-selected={i === index}
                className={`carousel__dot${i === index ? " is-active" : ""}`}
                onClick={() => setIndex(i)} aria-label={`Photo ${i + 1} of ${count}`} />
            ))}
          </div>
        </>
      )}
    </div>
  );
}

/* --- Closing CTA block (every page) --------------------------------------- */
function ClosingCTA({ onNavigate, title, sub, waText, prefillFamily }) {
  return (
    <section className="section">
      <div className="octo-container">
        <div className="closing">
          <h2 className="closing__title">{title || "Tell us what you're packaging."}</h2>
          {sub ? <p className="closing__sub">{sub}</p> : <p className="closing__sub"><PH>One-line invitation. Final copy TBD.</PH></p>}
          <div className="closing__cta">
            <Button size="lg" variant="primary" onClick={() => onNavigate(prefillFamily ? `contact?family=${prefillFamily}` : "contact")}>Start an enquiry</Button>
            <Button as="a" href={waLink(waText)} target="_blank" rel="noreferrer" size="lg" variant="kraft"
              iconLeft={<WhatsAppGlyph size={20} />}>Talk to us on WhatsApp</Button>
          </div>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, {
  Icon, WhatsAppGlyph, PH, PHBlock, Flag, SectionHead, MediaSlot, Carousel, ProductTile, ClosingCTA,
  waLink, WA_NUMBER, WA_DEFAULT, routeToHref,
});
