// Marketing footer — ported from BambuPartners' smith3d-bambu-promo template
// (printers.ts + PrinterCard/PrinterSheet), reskinned to the Smith3D design
// system and converted TSX → in-browser JSX. Promo-specific details (event
// freebies, per-product bonus blocks) are intentionally dropped; every buy CTA
// points at one Smith3D shop URL. Rendered at the bottom of the reward page for
// product exposure + a WhatsApp CTA. Gated on config.marketing_footer.enabled.
//
// Catalogue stays in code (not the DB) so non-marketing edits don't need an
// admin trip — same rationale as the source. Prices/specs verified May 2026
// against Bambu Lab public pages (carried over from honors3d); confirm before deploy.

const ANNIVERSARY_PRINTERS = [
  {
    id: 'a1-mini', name: 'A1 Mini', family: 'A series', tagline: 'Quiet. Quick. Easy.',
    klass: 'STARTER', glow: '#00AE42',
    blurb: 'Plug-and-play bed-slinger with auto-calibration. Whisper-quiet at 48 dB — happy on a bedroom desk. Pair with AMS Lite for 4-colour prints.',
    price: 'RM 999', priceFrom: 'from', priceNote: 'Combo (with AMS Lite) from RM 1,599',
    buildVolume: '180 × 180 × 180 mm', speed: 'Up to 500 mm/s',
    bestFor: ['Beginners', 'Miniatures', 'Multi-colour'],
    bullets: [
      'Pre-assembled, calibrates itself for every print',
      'Pairs with AMS Lite for 4-colour prints',
      'Whisper-quiet — Silent Mode under 48 dB',
      'Active Flow Rate Compensation for crisp surfaces',
    ],
    photo: '/products/a1-mini.png', photoScale: 0.95,
    buyUrl: 'https://www.smith3d.com/shop/3d-printers/fdm-printer/bambu-lab-a1-series/',
    variants: [
      { id: 'a1-mini', name: 'A1 Mini', price: 'RM 999', includes: 'Printer only' },
      { id: 'a1-mini-combo', name: 'A1 Mini Combo', price: 'RM 1,599', includes: 'With AMS Lite — 4-colour printing' },
    ],
  },
  {
    id: 'a1', name: 'A1', family: 'A series', tagline: 'Big bed. Big colour.',
    klass: 'ALL-ROUNDER', glow: '#00AE42', badge: 'POPULAR', badgeTone: 'green',
    blurb: '256 mm³ bed-slinger with auto bed-levelling, vibration compensation, and up to 4-colour printing via AMS Lite. Fast PLA at 500 mm/s.',
    price: 'RM 1,399', priceFrom: 'from', priceNote: 'Combo (with AMS Lite) from RM 1,999',
    buildVolume: '256 × 256 × 256 mm', speed: 'Up to 500 mm/s',
    bestFor: ['Families', 'Cosplay', 'Multi-colour'],
    bullets: [
      'Full 256 mm³ build — same as P-series',
      'Up to 4 colours with AMS Lite',
      'Auto bed-level, vibration & flow calibration',
      'Reinforced heatbed cable (post-2024 batches)',
    ],
    photo: '/products/a1.png', photoScale: 0.95,
    buyUrl: 'https://www.smith3d.com/shop/3d-printers/fdm-printer/bambu-lab-a1-series/',
    variants: [
      { id: 'a1', name: 'A1', price: 'RM 1,399', includes: 'Printer only' },
      { id: 'a1-combo', name: 'A1 Combo', price: 'RM 1,999', includes: 'With AMS Lite — 4-colour printing' },
    ],
  },
  {
    id: 'p2s', name: 'P2S', family: 'P series', tagline: 'Flagship DNA. Pro price.',
    klass: 'PRO', glow: '#3a86ff',
    blurb: "The P1S story refined: same enclosed CoreXY platform with the latest toolhead and quieter operation. Bambu's most accessible single-nozzle enclosed printer.",
    price: 'RM 2,999', priceFrom: 'from', priceNote: 'Combo (with AMS 2 Pro) from RM 3,999',
    buildVolume: '256 × 256 × 256 mm', speed: 'Up to 600 mm/s',
    bestFor: ['P1S upgraders', 'Pro workflows'],
    bullets: [
      'Enclosed CoreXY for engineering filaments',
      'Refined toolhead — quieter & smoother',
      'AMS 2 Pro included in Combo',
      'Up to 16 colours with stacked AMS units',
    ],
    photo: '/products/p2s.png', photoScale: 0.95,
    buyUrl: 'https://www.smith3d.com/shop/3d-printers/enclosed-printers/p2s-combo/',
    variants: [
      { id: 'p2s', name: 'P2S', price: 'RM 2,999', includes: 'Printer only' },
      { id: 'p2s-combo', name: 'P2S Combo', price: 'RM 3,999', includes: 'With AMS 2 Pro — 4 colours, expandable to 16 by stacking 4 AMS units' },
    ],
  },
  {
    id: 'x2d', name: 'X2D', family: 'X series', tagline: 'Dual-nozzle flagship.',
    klass: 'FLAGSHIP', glow: '#F5731F',
    blurb: "X1 Carbon's successor with dual-nozzle switching, 65 °C heated chamber, and up to 25-colour AMS support. Clean breakaway supports without manual swaps.",
    price: 'RM 4,599', priceFrom: 'combo', priceNote: 'X2D Combo (with AMS 2 Pro)',
    buildVolume: '256 × 256 × 260 mm', speed: 'Up to 1000 mm/s',
    bestFor: ['Engineering', 'Dual material', 'Pros'],
    bullets: [
      'Dual-nozzle switching — main + auxiliary',
      '65 °C heated chamber for ABS/ASA/Nylon',
      'Up to 25 colours with AMS 2 Pro',
      'Vision Encoder + AI nozzle monitoring',
      'UL 2904 certified for indoor air quality',
    ],
    photo: '/products/x2d.png', photoScale: 0.95,
    buyUrl: 'https://www.smith3d.com/shop/3d-printers/enclosed-printers/bambu-lab-x2d-combo/',
  },
  {
    id: 'h2s', name: 'H2S', family: 'H series', tagline: 'Goes big. Stays solid.',
    klass: 'ELITE', glow: '#a855f7',
    blurb: 'Large-format single-nozzle CoreXY built for massive engineering parts with superior thermal stability and 320 mm³ build volume.',
    price: 'RM 6,999', priceFrom: 'from', priceNote: 'H2S — single-nozzle large-format',
    buildVolume: '340 × 320 × 340 mm', speed: 'Up to 1000 mm/s',
    bestFor: ['Pro single-material', 'Large parts'],
    bullets: [
      'Largest build volume in the Bambu lineup',
      'Active heated chamber (65 °C) for engineering filaments',
      'Smaller-pitch belts eliminate VFAs',
      'Optional 10W laser, blade, and pen modules',
      'AMS 2 Pro / AMS HT compatible',
    ],
    photo: '/products/h2s.png', photoScale: 0.95,
    buyUrl: 'https://www.smith3d.com/shop/3d-printers/enclosed-printers/bambu-lab-h2s/',
  },
  {
    id: 'h2d', name: 'H2D', family: 'H series', tagline: 'Personal manufacturer.',
    klass: 'BEAST', glow: '#a855f7',
    blurb: "350×320×325 mm dual-extruder flagship with optional laser engraving and blade cutting modules. Bambu's most versatile desktop platform.",
    price: 'RM 8,499', priceFrom: 'from', priceNote: 'H2D — dual-nozzle multi-function platform',
    buildVolume: '350 × 320 × 325 mm', speed: 'Up to 1000 mm/s',
    bestFor: ['Engineering', 'Production', 'Laser/cut'],
    bullets: [
      'Dual direct-drive extruders on one toolhead',
      'Optional 10W/40W laser, blade, and pen modules',
      'Active heated chamber (65 °C) for engineering filaments',
      'BirdsEye top-down camera with vision align',
      'High-flow hotend — 600 mm/s sustained print',
    ],
    photo: '/products/h2d.png', photoScale: 0.95,
    buyUrl: 'https://www.smith3d.com/shop/3d-printers/enclosed-printers/bambu-lab-h2d/',
  },
  {
    id: 'h2c', name: 'H2C', family: 'H series', tagline: 'Waste-free multi-material.',
    klass: 'MULTI-MAT', glow: '#a855f7',
    blurb: 'H-series with the Vortek hot-end swap system — one fixed left nozzle plus six interchangeable induction hotends on the right. Up to 24 filaments in a single print with minimal purge.',
    price: 'RM 10,499', priceFrom: 'from', priceNote: 'H2C — Vortek multi-material',
    buildVolume: '330 × 320 × 325 mm', speed: 'Up to 1000 mm/s',
    bestFor: ['Multi-material', 'Print farms', 'Pros'],
    bullets: [
      'Vortek hot-end swap — 1 fixed + 6 induction hotends',
      'Up to 24 filaments in a single print',
      'Minimises purge waste across materials',
      'Active heated chamber (65 °C) for engineering filaments',
    ],
    photo: '/products/h2c.png', photoScale: 0.95,
    buyUrl: 'https://www.smith3d.com/shop/3d-printers/fdm-printer/bambu-lab-h2c-combo/',
  },
];

function badgeColor(tone) {
  return { green: '#00AE42', dark: '#14151a', orange: 'var(--s3-orange)' }[tone] || 'var(--s3-orange)';
}

// Darken a bright series colour so tagline/tick text clears contrast on white.
// Blends the hue toward near-black; keeps the brand hue, just deeper.
function darken(hex, amt) {
  const h = String(hex || '').replace('#', '');
  if (!/^[0-9a-fA-F]{6}$/.test(h)) return hex;
  const n = parseInt(h, 16);
  const f = 1 - amt;
  const d = (c) => Math.max(0, Math.min(255, Math.round(c * f + 18 * amt)));
  return `rgb(${d((n >> 16) & 255)},${d((n >> 8) & 255)},${d(n & 255)})`;
}

// WhatsApp glyph (the app's icon set doesn't ship one).
function WaIcon({ size = 18, className }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor" className={className} aria-hidden>
      <path d="M.057 24l1.687-6.163a11.867 11.867 0 01-1.587-5.946C.16 5.335 5.495 0 12.05 0a11.817 11.817 0 018.413 3.488 11.824 11.824 0 013.48 8.414c-.003 6.557-5.338 11.892-11.893 11.892a11.9 11.9 0 01-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.884-.001 2.225.651 3.891 1.746 5.634l-.999 3.648 3.742-.981zm11.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.016-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-.695.248-1.29.173-1.414z"/>
    </svg>
  );
}

function buildVolumeShort(buildVolume) {
  const build = buildVolume.replace(' mm', '').replace(/ × /g, '×');
  const parts = build.split('×').map(s => s.trim());
  return (parts.length === 3 && parts[0] === parts[1] && parts[1] === parts[2])
    ? `${parts[0]}³ mm` : `${build} mm`;
}

// Full-width horizontal card ported from honors3d's `fcard`: glow-tinted body on
// the left, printer image bleeding off the right. Styled via the .fcard-* CSS in
// index.html; --glow + --photo-scale are passed per card.
function PrinterCard({ p, onTap }) {
  const buildShort = buildVolumeShort(p.buildVolume);
  return (
    <button className="fcard" onClick={onTap}
      style={{ '--glow': p.glow, '--photo-scale': String(p.photoScale || 1) }}>
      <div className="fcard-inner">
        <div className="fcard-class">{p.klass}</div>
        <div className="fcard-glow" aria-hidden/>
        <svg className="fcard-grid" viewBox="0 0 200 100" preserveAspectRatio="none" aria-hidden>
          <defs>
            <pattern id={`fp-${p.id}`} width="10" height="10" patternUnits="userSpaceOnUse">
              <path d="M 10 0 L 0 0 0 10" fill="none" stroke="currentColor" strokeWidth="0.3"/>
            </pattern>
          </defs>
          <rect width="200" height="100" fill={`url(#fp-${p.id})`}/>
        </svg>
        <div className="fcard-body">
          <div className="fcard-family">{p.family}</div>
          <h3 className="fcard-name">{p.name}</h3>
          <div className="fcard-tag" style={{ color: darken(p.glow, 0.42) }}>{p.tagline}</div>
          <div className="fcard-stats">
            <div>
              <div className="fcard-stat-lbl">BUILD</div>
              <div className="fcard-stat-val">{buildShort}</div>
            </div>
            {p.speed && (
              <div>
                <div className="fcard-stat-lbl">SPEED</div>
                <div className="fcard-stat-val">{p.speed.replace('Up to ', '')}</div>
              </div>
            )}
          </div>
          <div className="fcard-foot">
            <div className="fcard-price">
              {p.priceFrom && <span className="fcard-from">{p.priceFrom}</span>}
              <span className="fcard-amount">{p.price}</span>
            </div>
            <span className="fcard-cta"><IconChevronRight size={13}/></span>
          </div>
        </div>
        {/* ground shadow under the overflowing photo — stays clipped inside the card */}
        <div className="fcard-floor" aria-hidden/>
      </div>
      {/* portrait + badge are SIBLINGS of fcard-inner so they overflow the card
          (fcard-inner is overflow:hidden; the fcard button is overflow:visible) */}
      <img className="fcard-portrait" src={p.photo} alt={p.name} loading="lazy" draggable={false}/>
      {p.badge && (
        <div className="fcard-badge" style={{ background: badgeColor(p.badgeTone) }}>{p.badge}</div>
      )}
    </button>
  );
}

// Detail bottom-sheet (mirrors the app's other sheets). Shows specs/variants/
// bullets, then a WhatsApp CTA (custom prefilled message) + a "Buy" link to the
// single Smith3D shop URL.
function PrinterSheet({ printer, onClose, waUrl, shopUrl }) {
  // Ported to honors3d's .sh-* CSS (index.html) so the sheet is parity by
  // construction, not hand-matched Tailwind. dragY follows the finger; the
  // `closing` class plays sheetOut/scrimOut, then we unmount after the anim.
  const [dragY, setDragY] = React.useState(0);
  const [closing, setClosing] = React.useState(false);
  const startY = React.useRef(null);
  const scrollRef = React.useRef(null);
  const scrollStartY = React.useRef(null);

  const handleClose = React.useCallback(() => {
    setClosing(true);
    setTimeout(() => { setClosing(false); setDragY(0); onClose(); }, 220);
  }, [onClose]);

  React.useEffect(() => {
    if (!printer) return;
    const onKey = (e) => { if (e.key === 'Escape') handleClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [printer, handleClose]);

  // Lock the page behind the sheet so wheel/touch can't bleed-scroll it.
  React.useEffect(() => {
    if (!printer) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = prev; };
  }, [printer]);

  if (!printer) return null;
  const p = printer;
  const tickColor = darken(p.glow, 0.42);

  return (
    <div className={'sh-scrim' + (closing ? ' closing' : '')}
      onClick={(e) => { if (e.target === e.currentTarget) handleClose(); }}>
      <div className={'sh-sheet' + (closing ? ' closing' : '')}
        style={{ transform: `translateY(${dragY}px)`, '--glow': p.glow }}>
        <div className="sh-handle-zone"
          onTouchStart={(e) => { startY.current = e.touches[0].clientY; }}
          onTouchMove={(e) => { if (startY.current == null) return; const dy = e.touches[0].clientY - startY.current; if (dy > 0) setDragY(dy); }}
          onTouchEnd={() => { if (dragY > 120) handleClose(); else setDragY(0); startY.current = null; }}>
          <div className="sh-handle"/>
        </div>
        <button className="sh-x" onClick={handleClose} aria-label="Close"><IconX size={16}/></button>

        <div className="sh-scroll" ref={scrollRef}
          onTouchStart={(e) => { const el = scrollRef.current; scrollStartY.current = (el && el.scrollTop <= 0) ? e.touches[0].clientY : null; }}
          onTouchMove={(e) => { if (scrollStartY.current == null) return; const dy = e.touches[0].clientY - scrollStartY.current; setDragY(dy > 0 ? dy : 0); }}
          onTouchEnd={() => { if (scrollStartY.current != null && dragY > 120) handleClose(); else setDragY(0); scrollStartY.current = null; }}>

          <div className="sh-hero">
            <img className="sh-hero-img" src={p.photo} alt={p.name} draggable={false}/>
            <div className="sh-hero-class">{p.klass}</div>
            {p.badge && (
              <div className="sh-hero-badge" style={{ background: badgeColor(p.badgeTone) }}>{p.badge}</div>
            )}
          </div>

          <div className="sh-head">
            <div className="sh-eyebrow">Bambu Lab · {p.family}</div>
            <h2 className="sh-title">{p.name}</h2>
            <p className="sh-tagline">{p.tagline}</p>
            <p className="sh-blurb">{p.blurb}</p>
          </div>

          {p.variants ? (
            <>
              <div className="sh-meta-strip">
                <div><span className="sh-meta-lbl">Build</span><span className="sh-meta-val">{p.buildVolume}</span></div>
                {p.speed && <div><span className="sh-meta-lbl">Speed</span><span className="sh-meta-val">{p.speed.replace('Up to ', '')}</span></div>}
              </div>
              <div className="sh-section">
                <div className="sh-section-lbl">Configurations</div>
                <div className="sh-variants">
                  {p.variants.map(v => (
                    <div key={v.id} className="sh-variant">
                      <div className="sh-variant-head">
                        <div className="sh-variant-name">{v.name}</div>
                        <div className="sh-variant-price">{v.price}</div>
                      </div>
                      <div className="sh-variant-includes">{v.includes}</div>
                    </div>
                  ))}
                </div>
              </div>
            </>
          ) : (
            <div className="sh-price-row">
              <div>
                <div className="sh-price">{p.price}</div>
                <div className="sh-price-note">{p.priceNote}</div>
              </div>
              <div className="sh-build">
                <div className="sh-build-lbl">Build volume</div>
                <div className="sh-build-val">{p.buildVolume}</div>
              </div>
            </div>
          )}

          <div className="sh-section">
            <div className="sh-section-lbl">What it does well</div>
            <ul className="sh-bullets">
              {p.bullets.map((b, i) => (
                <li key={i}><span className="sh-tick" style={{ color: tickColor }}>✓</span><span>{b}</span></li>
              ))}
            </ul>
          </div>

          <div className="sh-section">
            <div className="sh-section-lbl">Best for</div>
            <div className="sh-tags">
              {p.bestFor.map((t, i) => (<span key={i} className="sh-tag">{t}</span>))}
            </div>
          </div>

          <div className="sh-cta-spacer"/>
        </div>

        <div className="sh-ctas">
          <a className="sh-cta sh-cta-wa" href={waUrl(p.name)} target="_blank" rel="noopener noreferrer">
            <WaIcon size={18}/> WhatsApp us
          </a>
          <a className="sh-cta sh-cta-buy" href={p.buyUrl || shopUrl} target="_blank" rel="noopener noreferrer">
            Buy now <IconExternalLink size={14}/>
          </a>
        </div>
      </div>
    </div>
  );
}

// The footer section itself. Gated on config.marketing_footer.enabled so it only
// shows for events that opt in (Anniversary). Reads shop URL + WhatsApp number +
// prefilled message from config, with safe Smith3D defaults.
function MarketingFooter({ campaign }) {
  const cfg = campaign?.config || {};
  const mf = cfg.marketing_footer || {};
  const [selected, setSelected] = React.useState(null);
  const flistRef = React.useRef(null);

  // Touch "in-focus" election (parity with the honors3d BambuPartners page): the
  // card nearest the viewport centre gets the `in-focus` class, which pops its
  // product photo out of the card as you scroll. rAF-throttled, pure DOM class
  // toggle (no React re-render). `capture:true` so it works whether the page or
  // an inner element is the scroller. Desktop gets the same pop via :hover (CSS).
  React.useEffect(() => {
    const root = flistRef.current;
    if (!root) return;
    let rafId = 0, current = null;
    const elect = () => {
      rafId = 0;
      const cards = root.querySelectorAll('.fcard');
      const vh = window.innerHeight, center = vh / 2;
      let best = null, bestDist = Infinity;
      cards.forEach(el => {
        const r = el.getBoundingClientRect();
        const d = Math.abs(r.top + r.height / 2 - center);
        if (d < vh * 0.4 && d < bestDist) { bestDist = d; best = el; }
      });
      if (best !== current) {
        if (current) current.classList.remove('in-focus');
        if (best) best.classList.add('in-focus');
        current = best;
      }
    };
    const schedule = () => { if (!rafId) rafId = requestAnimationFrame(elect); };
    schedule();
    window.addEventListener('scroll', schedule, { passive: true, capture: true });
    window.addEventListener('resize', schedule);
    return () => {
      window.removeEventListener('scroll', schedule, { capture: true });
      window.removeEventListener('resize', schedule);
      if (rafId) cancelAnimationFrame(rafId);
      if (current) current.classList.remove('in-focus');
    };
  }, [mf.enabled]);

  if (!mf.enabled) return null;

  const whatsapp = String(mf.whatsapp || '60103443128').replace(/[^0-9]/g, '');
  const shopUrl = mf.shop_url || 'https://smith3d.com';
  const waMessage = mf.wa_message
    || "Hi Smith3D! I'm interested in the Bambu Lab Anniversary Deals — can you help me with {product}?";
  const waUrl = (product) =>
    `https://api.whatsapp.com/send/?phone=${whatsapp}&text=${encodeURIComponent(waMessage.replace('{product}', product || 'the Anniversary Deals'))}`;

  return (
    <section className="mt-8 pt-4 border-t border-neutral-200">
      <div className="cat-header">
        <div>
          <div className="cat-eyebrow">Choose your fighter</div>
          <h2 className="cat-title">Pick your Bambu Lab</h2>
        </div>
        <div className="cat-count">{ANNIVERSARY_PRINTERS.length} models</div>
      </div>

      <div className="flist" ref={flistRef}>
        {ANNIVERSARY_PRINTERS.map(p => (
          <PrinterCard key={p.id} p={p} onTap={() => setSelected(p)}/>
        ))}
      </div>

      {/* Still deciding? — WhatsApp help card (matches honors3d footer) */}
      <div className="mt-4 rounded-2xl border border-green-100 p-4 flex items-center gap-3" style={{ background: '#f0faf3' }}>
        <div className="w-11 h-11 rounded-full grid place-items-center text-white shrink-0" style={{ background: '#128C7E' }}>
          <WaIcon size={20}/>
        </div>
        <div className="flex-1 min-w-0">
          <div className="text-[14px] font-bold text-neutral-900">Still deciding?</div>
          <div className="text-[12.5px] text-neutral-600 leading-snug">Chat us on WhatsApp — we'll help you pick the right printer for your prints.</div>
        </div>
        <a href={waUrl(null)} target="_blank" rel="noopener noreferrer"
          className="shrink-0 h-10 px-4 rounded-full text-white text-[13px] font-semibold inline-flex items-center gap-1.5 active:scale-95"
          style={{ background: '#128C7E' }}>
          WhatsApp <IconExternalLink size={13}/>
        </a>
      </div>

      <PrinterSheet printer={selected} onClose={() => setSelected(null)} waUrl={waUrl} shopUrl={shopUrl}/>
    </section>
  );
}

Object.assign(window, { MarketingFooter });
