// Center-emphasis ("coverflow") carousel for the home Featured section.
// 5 cards visible at once, the middle one is scaled up. Autoplay every 4s,
// pauses on hover and during drag. Click a side card to center it, click
// the center card to open its PDP. Pointer drag works for mouse + touch
// (with a tap-vs-drag threshold so a quick click isn't read as a drag).
function FeaturedCarousel({ products, onOpen, onAdd }) {
  const [index, setIndex] = useState(0);
  // Two independent states: hovering (mouse only) and dragging. Autoplay
  // is paused if EITHER is true. Releasing the mouse after a drag does NOT
  // restart autoplay — only moving the cursor off the carousel does.
  const [isHovering, setIsHovering] = useState(false);
  const [isDragging, setIsDragging] = useState(false);
  const [vw, setVw] = useState(typeof window !== "undefined" ? window.innerWidth : 1200);
  const dragRef = useRef({ startX: 0, startIndex: 0, moved: false });
  // Remember the previous index so each render can tell which cards actually
  // wrapped (off-screen left → off-screen right or vice versa) vs which ones
  // just naturally went off-screen. Only the wrappers need transition:none.
  const prevIndexRef = useRef(0);
  useEffect(() => { prevIndexRef.current = index; }, [index]);

  useEffect(() => {
    const onResize = () => setVw(window.innerWidth);
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, []);

  const visibleRadius = vw < 700 ? 1 : 2;
  const cardW         = vw < 480 ? 210 : vw < 700 ? 250 : vw < 1100 ? 310 : 360;
  const gap           = vw < 480 ? 14  : vw < 700 ? 18  : vw < 1100 ? 24  : 30;
  const vpH           = vw < 480 ? 380 : vw < 700 ? 460 : vw < 1100 ? 560 : 620;

  const scaleAt = (abs) => abs === 0 ? 1 : abs === 1 ? 0.82 : abs === 2 ? 0.64 : 0.5;
  const positionAt = (offset) => {
    if (offset === 0) return 0;
    const sign = offset > 0 ? 1 : -1;
    const abs  = Math.abs(offset);
    let pos = 0;
    for (let i = 1; i <= abs; i++) {
      pos += (scaleAt(i - 1) + scaleAt(i)) * cardW / 2 + gap;
    }
    return sign * pos;
  };
  const stepWidth = positionAt(1) || cardW;

  // Autoplay — re-runs whenever isHovering or isDragging flips. Clearing
  // and re-creating the interval gives every interaction a fresh 4s pause
  // instead of advancing the moment the user lets go.
  useEffect(() => {
    if (isHovering || isDragging || !products || products.length < 2) return;
    const id = setInterval(() => setIndex(i => (i + 1) % products.length), 4000);
    return () => clearInterval(id);
  }, [isHovering, isDragging, products && products.length]);

  // Safety net: a release of the pointer ANYWHERE (not just on the carousel)
  // clears the drag state. Without this, dragging off the carousel, switching
  // tabs mid-drag, or alt-tabbing while held could leave the carousel stuck
  // in "isDragging = true" forever, blocking all subsequent interactions.
  useEffect(() => {
    const release = () => {
      if (dragRef.current.startX !== 0) {
        setIsDragging(false);
        // Keep .moved true briefly so the click handler that fires right
        // after pointerup still sees it (and short-circuits the click).
        setTimeout(() => {
          dragRef.current.startX = 0;
          dragRef.current.moved = false;
        }, 80);
      } else {
        setIsDragging(false);
      }
    };
    document.addEventListener("pointerup", release);
    document.addEventListener("pointercancel", release);
    window.addEventListener("blur", release);
    return () => {
      document.removeEventListener("pointerup", release);
      document.removeEventListener("pointercancel", release);
      window.removeEventListener("blur", release);
    };
  }, []);

  if (!products || products.length === 0) return null;
  const total = products.length;
  const active = products[index];

  const goTo = (i) => setIndex(((i % total) + total) % total);
  const goPrev = () => goTo(index - 1);
  const goNext = () => goTo(index + 1);

  const wrappedOffsetFor = (i, idx) => {
    let d = i - idx;
    if (d >  total / 2) d -= total;
    if (d <= -total / 2) d += total;
    return d;
  };
  const wrappedOffset = (i) => wrappedOffsetFor(i, index);

  // Hover handlers — mouse only. Touch never sets isHovering (there's no
  // such thing as "hovering" on touch) so autoplay isn't perma-paused on
  // mobile after a tap.
  const onPointerEnter = (e) => {
    if (e.pointerType === "mouse") setIsHovering(true);
  };
  const onPointerLeave = (e) => {
    if (e.pointerType === "mouse") setIsHovering(false);
  };

  const onPointerDown = (e) => {
    dragRef.current = { startX: e.clientX, startIndex: index, moved: false };
    setIsDragging(true);
  };
  const onPointerMove = (e) => {
    if (dragRef.current.startX === 0) return;
    const dx = e.clientX - dragRef.current.startX;
    if (Math.abs(dx) < 8) return;                  // tap-vs-drag threshold
    if (!dragRef.current.moved) {
      dragRef.current.moved = true;
      try { e.currentTarget.setPointerCapture(e.pointerId); } catch (_) {}
    }
    const steps = Math.round(-dx / stepWidth);
    goTo(dragRef.current.startIndex + steps);
  };

  return (
    <div
      className="carousel"
      onPointerEnter={onPointerEnter}
      onPointerLeave={onPointerLeave}
    >
      <button className="carousel__arrow carousel__arrow--prev" onClick={goPrev} aria-label="Vorheriges Produkt">
        <Icon name="chevron-left" size={22} />
      </button>

      <div
        className="carousel__viewport"
        style={{ height: vpH }}
        onPointerDown={onPointerDown}
        onPointerMove={onPointerMove}
      >
        {products.map((p, i) => {
          const offset = wrappedOffset(i);
          const prevOffset = wrappedOffsetFor(i, prevIndexRef.current);
          const abs    = Math.abs(offset);
          const isCenter = offset === 0;
          const offscreen = abs > visibleRadius;
          const dx      = positionAt(offset);
          const scale   = scaleAt(abs);
          // Opacity is now full for all visible cards — the viewport's
          // edge mask does the smooth fade at the left/right rails.
          const opacity = offscreen ? 0 : 1;
          // Suppress the transition ONLY when this card wrapped — i.e. its
          // wrapped offset crossed from one off-screen side to the other.
          // Cards just going off-screen normally keep the CSS transition.
          const wrapped = offset * prevOffset < 0
                       && Math.abs(prevOffset) > visibleRadius
                       && Math.abs(offset)     > visibleRadius;
          const transition = wrapped ? "none" : undefined;
          const b = BADGE_MAP[p.badge];
          return (
            <div
              key={p.id}
              className={`carousel__item${isCenter ? " is-center" : ""}`}
              style={{
                width: cardW,
                marginLeft: -cardW / 2,
                transform: `translateX(${dx}px) scale(${scale})`,
                opacity,
                transition,
                zIndex: 10 - abs,
                pointerEvents: offscreen ? "none" : "auto",
              }}
              onClick={() => {
                if (dragRef.current.moved) { dragRef.current.moved = false; return; }
                if (isCenter) onOpen(p);
                else goTo(i);
              }}
            >
              <div className="carousel__item-img">
                {/* Secondary photo stacked underneath the primary. On hover
                    the primary fades out and this one peeks through, same as
                    the grid cards in the shop. */}
                {p.image && p.imageSecondary && (
                  <img className="carousel__item-photo-alt" src={p.imageSecondary} alt="" loading="lazy" draggable={false} />
                )}
                {p.image && <img className="carousel__item-photo" src={p.image} alt={p.name} loading="lazy" draggable={false} />}
                {b && <span className="pcard__badge"><Badge kind={b[0]}>{b[1]}</Badge></span>}
              </div>
            </div>
          );
        })}
      </div>

      <button className="carousel__arrow carousel__arrow--next" onClick={goNext} aria-label="Nächstes Produkt">
        <Icon name="chevron-right" size={22} />
      </button>

      <div className="carousel__caption">
        {/* Anlass – Geschmackswelt from the product's Shopify tags (e.g.
            "Apéro – Fruchtig & Lebendig"). Falls back to the drink type
            until the tags are set — nothing hardcoded per product. */}
        <span className="eyebrow">
          {(() => {
            const a = active.anlass && active.anlass[0] ? taxLabel("anlass", active.anlass[0]) : null;
            const g = active.geschmack && active.geschmack[0] ? taxLabel("geschmack", active.geschmack[0]) : null;
            return [a, g].filter(Boolean).join(" – ") || active.category;
          })()}
        </span>
        <h3>{active.name}</h3>
        <p>{active.tagline}</p>
        <div className="carousel__cta">
          <span className="price">{money(active.price)}</span>
          <Button variant="primary" size="md" onClick={(e) => {
            const media = document.querySelector(".carousel__item.is-center .carousel__item-img");
            onAdd(active, 1, media || e.currentTarget);
          }}>{t("featured.add")}</Button>
        </div>
      </div>
    </div>
  );
}

// Inga's hand-drawn 8-ray flower silhouette — the hero's flower cursor.
// Same path data as public/site/assets/flower-mask.svg; inlined here so
// the JS-driven animation can write a transform attribute to the path
// without an HTTP round-trip per frame.
const SPYGLASS_FLOWER_D = "M961.52,464.26l-195.38-19.9c-45.51-4.63-67.61-58-38.71-93.46l124.09-152.23c11.56-14.18,10.51-34.81-2.42-47.74h0c-12.94-12.94-33.56-13.98-47.74-2.43l-152.23,124.09c-35.46,28.9-88.82,6.8-93.46-38.71l-19.9-195.38c-1.85-18.2-17.18-32.04-35.47-32.04h0c-18.29,0-33.62,13.84-35.47,32.04l-19.9,195.38c-4.63,45.51-58,67.61-93.46,38.71l-152.23-124.09c-14.18-11.56-34.81-10.51-47.74,2.42h0c-12.94,12.94-13.98,33.56-2.42,47.74l124.09,152.23c28.9,35.46,6.8,88.82-38.71,93.46l-195.38,19.9c-18.2,1.85-32.04,17.18-32.04,35.47h0c0,18.29,13.84,33.62,32.04,35.47l195.38,19.9c45.51,4.63,67.61,58,38.71,93.46l-124.09,152.23c-11.56,14.18-10.51,34.81,2.42,47.74h0c12.94,12.94,33.56,13.98,47.74,2.42l152.23-124.09c35.46-28.9,88.82-6.8,93.46,38.71l19.9,195.38c1.85,18.2,17.18,32.04,35.47,32.04h0c18.29,0,33.62-13.84,35.47-32.04l19.9-195.38c4.63-45.51,58-67.61,93.46-38.71l152.23,124.09c14.18,11.56,34.81,10.51,47.74-2.42h0c12.94-12.94,13.98-33.56,2.42-47.74l-124.09-152.23c-28.9-35.46-6.8-88.82,38.71-93.46l195.38-19.9c18.2-1.85,32.04-17.18,32.04-35.47h0c0-18.29-13.84-33.62-32.04-35.47Z";

// Home page
function Home({ onNav, onOpen, onAdd, onOpenRecipe }) {
  const heroRef = useRef(null);
  const heroMediaRef = useRef(null);
  const flowerPathRef = useRef(null);
  useEffect(() => {
    const el = heroRef.current;
    if (el) requestAnimationFrame(() => requestAnimationFrame(() => el.classList.add("in")));
  }, []);

  // Flower cursor — a SOLID Poppy flower glides over the hero image,
  // following the mouse, slowly rotating, growing toward the centre and
  // shrinking at the edges. (It used to be a mask revealing a second photo
  // underneath; Inga asked for the solid version so the effect never
  // depends on her producing matching image pairs.) One requestAnimation-
  // Frame loop tweens the radius on hover-in / hover-out, increments the
  // rotation while hovering, and writes ONE transform attribute onto the
  // overlay <path>. Refs everywhere so mousemove + animation never trigger
  // React re-renders.
  const animRef = useRef({
    hovering: false,
    cursorX: 0,
    cursorY: 0,
    targetRadius: 0,
    currentRadius: 0,
    rotation: 0,
    lastTime: null,
    rafId: null,
  });

  const applyFlowerTransform = () => {
    const s = animRef.current;
    if (!flowerPathRef.current) return;
    // While the flower is essentially invisible, park it far off-screen so
    // a sub-pixel render at (0, 0) doesn't leave a smudge in the corner.
    if (s.currentRadius < 1) {
      flowerPathRef.current.setAttribute("transform", "translate(-99999 -99999) scale(0.001)");
      return;
    }
    // Path lives at 0..1000 user units; the overlay <svg> has no viewBox so
    // user units = CSS pixels. Centre the path on the cursor, scale its
    // 1000-unit bbox to 2R wide, rotate around the path centre (500, 500).
    // SVG transforms apply right-to-left.
    const scale = (2 * s.currentRadius) / 1000;
    flowerPathRef.current.setAttribute(
      "transform",
      `translate(${s.cursorX} ${s.cursorY}) scale(${scale}) rotate(${s.rotation}) translate(-500 -500)`
    );
  };

  const tick = (time) => {
    const s = animRef.current;
    if (s.lastTime === null) s.lastTime = time;
    const dt = Math.min(50, time - s.lastTime);   // cap dt across tab switches
    s.lastTime = time;

    // Exponential ease: currentRadius → targetRadius. k = 1/time-constant.
    const k = 0.012;
    s.currentRadius += (s.targetRadius - s.currentRadius) * (1 - Math.exp(-k * dt));

    // Continuous slow rotation only while hovering.
    if (s.hovering) s.rotation = (s.rotation + dt * 0.025) % 360;

    applyFlowerTransform();

    // Keep the loop running while hovering OR while the radius is still
    // tweening back to 0 on hover-out. Then snap to target and stop.
    const stillAnimating = s.hovering || Math.abs(s.targetRadius - s.currentRadius) > 0.5;
    if (stillAnimating) {
      s.rafId = requestAnimationFrame(tick);
    } else {
      s.rafId = null;
      s.lastTime = null;
      s.currentRadius = s.targetRadius;
      applyFlowerTransform();
    }
  };

  const ensureTicking = () => {
    const s = animRef.current;
    if (s.rafId === null) {
      s.lastTime = null;
      s.rafId = requestAnimationFrame(tick);
    }
  };

  const computeTargetRadius = (x, y, rect) => {
    const dx = (x - rect.width / 2) / (rect.width / 2);
    const dy = (y - rect.height / 2) / (rect.height / 2);
    const dist = Math.min(1, Math.hypot(dx, dy));
    const minR = 90;
    const maxR = Math.min(rect.width, rect.height) * 0.42;
    return minR + (maxR - minR) * (1 - dist);
  };

  const onHeroMouseMove = (e) => {
    const el = heroMediaRef.current;
    if (!el) return;
    const rect = el.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    const s = animRef.current;
    s.cursorX = x;
    s.cursorY = y;
    s.hovering = true;
    s.targetRadius = computeTargetRadius(x, y, rect);
    ensureTicking();
  };

  const onHeroMouseLeave = () => {
    const s = animRef.current;
    s.hovering = false;
    s.targetRadius = 0;
    ensureTicking();
  };
  // Editorial slot driven by Shopify tag. Inga tags the product she wants
  // featured on the home page with "highlight"; first product is the fallback.
  const highlight = PRODUCTS.find(p => p.tags && p.tags.includes("highlight")) || PRODUCTS[0];
  const values = [
    { icon: "sparkles", h: t("values.1h"), p: t("values.1p") },
    { icon: "sprout",   h: t("values.2h"), p: t("values.2p") },
    { icon: "truck",    h: t("values.3h"), p: t("values.3p") },
  ];
  return (
    <div>
      {/* HERO */}
      <section className="hero" ref={heroRef}>
        <div className="wrap hero__inner">
          <div>
            <span className="eyebrow">{t("hero.eyebrow")}</span>
            <h1>{t("hero.h1")}</h1>
            <p className="lead">{t("hero.lead")}</p>
            <div className="hero__cta">
              <Button variant="primary" size="lg" onClick={() => onNav("collection")}>{t("hero.cta1")}</Button>
              <Button variant="ghost" size="lg" onClick={() => onNav("about")}>{t("hero.cta2")}</Button>
            </div>
          </div>
          {/* Hero image = whichever product Inga tagged "Highlight-produkt"  */}
          {/* in Shopify. Click takes you to that product's PDP. If no       */}
          {/* highlight is tagged we fall back to the brand sprig artwork.   */}
          <div
            className={`hero__media${highlight && highlight.image ? " hero__media--has-reveal" : ""}`}
            ref={heroMediaRef}
            onClick={highlight ? () => onOpen(highlight) : undefined}
            onMouseMove={highlight && highlight.image ? onHeroMouseMove : undefined}
            onMouseLeave={highlight && highlight.image ? onHeroMouseLeave : undefined}
            role={highlight ? "button" : undefined}
            aria-label={highlight ? `${highlight.name} ansehen` : undefined}
          >
            {highlight && highlight.image ? (
              <React.Fragment>
                <img className="product-photo" src={highlight.image} alt={highlight.name} />
                {/* Solid Poppy flower that follows the cursor (see the
                    animation block above). No viewBox on purpose: user
                    units = CSS pixels, so the JS transform positions the
                    path directly in element space. pointer-events: none so
                    the hero stays clickable through it. */}
                <svg className="hero__flower" aria-hidden="true" focusable="false">
                  <path ref={flowerPathRef} transform="translate(-99999 -99999) scale(0.001)" d={SPYGLASS_FLOWER_D} />
                </svg>
              </React.Fragment>
            ) : (
              <div className="hero__bottle"></div>
            )}
          </div>
        </div>
      </section>

      {/* FEATURED */}
      <section className="section">
        <div className="wrap">
          <div className="section__head">
            <div>
              <span className="eyebrow">{t("featured.eyebrow")}</span>
              <h2>{t("featured.h2")}</h2>
            </div>
            <Button variant="secondary" size="md" onClick={() => onNav("collection")}>{t("featured.cta")}</Button>
          </div>
          <FeaturedCarousel products={PRODUCTS} onOpen={onOpen} onAdd={onAdd} />
        </div>
      </section>

      {/* GESCHMACKSWELTEN — discovery navigation into the pre-filtered
          shop. Four numbered cards on a single DELIBERATE color system:
          the green scale ramps light → dark in step with the taste
          narrative (Frisch & Leicht on the lightest green, Komplex &
          Besonders on the deep forest). Reads as one scale, not four
          random pastels. */}
      <section className="section" style={{ paddingTop: 0 }}>
        <div className="wrap">
          <div className="section__head">
            <div>
              <span className="eyebrow">{t("home.gw.eyebrow")}</span>
              <h2>{t("home.gw.h2")}</h2>
            </div>
          </div>
          <div className="gw-grid">
            {TAXONOMY.geschmack.map((g, i) => (
              <button key={g.key} className={`gw-card ${g.wash}`} onClick={() => onNav("collection", { geschmack: g.key })}>
                <span className="gw-card__num">0{i + 1}</span>
                <span className="gw-card__name">{taxLabel("geschmack", g.key)} <span className="gw-card__arrow" aria-hidden="true">→</span></span>
                <span className="gw-card__desc">{taxDesc("geschmack", g.key)}</span>
              </button>
            ))}
          </div>
        </div>
      </section>

      {/* BRAND STORY — the highlight product lives in the hero now, so this */}
      {/* band is back to its original brand/process copy.                    */}
      <section className="section section--tint">
        <div className="wrap">
          <div className="feature">
            <div>
              <span className="eyebrow" style={{ color: "var(--clay-300)" }}>{t("story.eyebrow")}</span>
              <h2>{t("story.h2")}</h2>
              <p>{t("story.p")}</p>
              <Button variant="ondark" size="md" onClick={() => onNav("about")}>{t("story.cta")}</Button>
            </div>
            <div className="feature__media">
              <img className="product-photo" src="../../assets/lifestyle/feature-curation.webp" alt="Inga prüft eine Auswahl alkoholfreier Apéritifs im Garten" />
            </div>
          </div>
        </div>
      </section>

      {/* RECIPES — 3x3 grid of non/low-alcohol re-interpretations of classics. */}
      <RecipesSection onOpenRecipe={onOpenRecipe} onNav={onNav} />

      {/* B2B — Inga wants the business segment visibly on the home page
          ("might be some business potential there", site notes 2026-06-12). */}
      <section className="section">
        <div className="wrap">
          <div className="b2b-band">
            <div>
              <span className="eyebrow">{t("b2b.eyebrow")}</span>
              <h2>{t("b2b.h2")}</h2>
              <p>{t("b2b.p")}</p>
              <div className="b2b-band__cta">
                <Button variant="primary" size="md" onClick={() => onNav("geschaeftskunden")}>{t("b2b.cta")}</Button>
                <Button variant="ghost" size="md" onClick={() => onNav("haendler")}>{t("b2b.cta2")}</Button>
              </div>
            </div>
            <ul className="b2b-band__points">
              <li><Icon name="package" size={20} /> {t("b2b.point1")}</li>
              <li><Icon name="glass-water" size={20} /> {t("b2b.point2")}</li>
              <li><Icon name="user" size={20} /> {t("b2b.point3")}</li>
            </ul>
          </div>
        </div>
      </section>

      {/* VALUES */}
      <section className="section" style={{ paddingTop: 0 }}>
        <div className="wrap">
          <div className="values">
            {values.map((v) => (
              <div className="value" key={v.h}>
                <div className="vic"><Icon name={v.icon} size={22} /></div>
                <h3>{v.h}</h3>
                <p>{v.p}</p>
              </div>
            ))}
          </div>
        </div>
      </section>
    </div>
  );
}
Object.assign(window, { Home });
