/* SATIEN v2 — Components (part 2) */

/* ─── Témoignages ─── */

const REVIEWS = [
  {
    name: 'Inès',
    age: 24,
    initial: 'I',
    quote: 'Je l\'utilise sur toutes mes casquettes depuis des semaines. Mes cheveux sont vraiment moins abîmés.',
  },
  {
    name: 'Karim',
    age: 28,
    initial: 'K',
    quote: 'Parfait pour le sport. Plus de frottements, plus d\'odeurs.',
  },
  {
    name: 'Camille',
    age: 22,
    initial: 'K',
    quote: 'J\'avais pas réalisé à quel point ma casquette abîmait mes cheveux avant d\'essayer le Soyeux.',
  },
];

function TestimonialCard({ r, i, revealDelay }) {
  const extra = revealDelay != null ? { 'data-reveal': true, 'data-reveal-delay': String(revealDelay) } : {};
  return (
    <div className="testimonial" {...extra}>
      <div className="stars">★ ★ ★ ★ ★</div>
      <p className="testimonial-quote">« <Editable id={`testimonials.review${i}.quote`}>{r.quote}</Editable> »</p>
      <div className="testimonial-author">
        <div className="testimonial-avatar">{r.initial}</div>
        <div className="testimonial-author-meta">
          <strong><Editable id={`testimonials.review${i}.name`}>{r.name}</Editable></strong>
          <span><Editable id={`testimonials.review${i}.age`}>{`${r.age} ans · vérifié`}</Editable></span>
        </div>
      </div>
    </div>
  );
}

/* Mobile: one full-width review at a time (2-up made every card too narrow
   to read comfortably) — arrows/swipe step through them, sliding the new
   one in from the side while the old one exits the other way. All 3
   reviews sit stacked in the same grid cell, positioned with inline
   transforms rather than classes; the untouched third is parked
   off-screen, ready to enter from whichever side matches the current
   direction. The wrapper's height is measured off the active card and
   animated to it, so a short review doesn't sit in a box sized for the
   longest one — and the arrows below just follow that height in normal
   flow. Starts on Kilian's review (index 2) — the strongest one. */
function TestimonialCarousel() {
  const N = REVIEWS.length;
  const { content } = useContent();
  const [state, setState] = React.useState({ index: 2, prevIndex: null, dir: 1 });
  const [height, setHeight] = React.useState(null);
  const slideRefs = React.useRef([]);

  const go = (delta) => {
    setState((s) => ({ index: (s.index + delta + N) % N, prevIndex: s.index, dir: delta }));
  };
  const goNext = () => go(1);
  const goPrev = () => go(-1);

  // Re-measure whenever the active card changes AND whenever content.json
  // (fetched async, arrives after the first render) updates — the review
  // text it carries is what actually determines the card's real height,
  // so measuring only once on mount would lock in the shorter placeholder
  // text's height and clip the real, longer quote once it swaps in.
  React.useLayoutEffect(() => {
    const el = slideRefs.current[state.index];
    if (el) setHeight(el.offsetHeight);
  }, [state.index, content]);

  React.useEffect(() => {
    if (state.prevIndex == null) return;
    const t = setTimeout(() => setState((s) => ({ ...s, prevIndex: null })), 520);
    return () => clearTimeout(t);
  }, [state.index, state.prevIndex]);

  const touchRef = React.useRef(null);
  const onTouchStart = (e) => {
    const t = e.touches[0];
    touchRef.current = { x: t.clientX, y: t.clientY };
  };
  const onTouchEnd = (e) => {
    const start = touchRef.current;
    touchRef.current = null;
    if (!start) return;
    const t = e.changedTouches[0];
    const dx = t.clientX - start.x, dy = t.clientY - start.y;
    if (Math.abs(dx) > 40 && Math.abs(dx) > Math.abs(dy) * 1.5) {
      if (dx < 0) goNext(); else goPrev();
    }
  };

  return (
    <div className="testimonial-carousel">
      <div
        className="testimonial-vstack"
        style={height != null ? { height } : undefined}
        onTouchStart={onTouchStart}
        onTouchEnd={onTouchEnd}
      >
        {REVIEWS.map((r, i) => {
          const isActive = i === state.index;
          const isLeaving = i === state.prevIndex;
          const enterFrom = state.dir > 0 ? '100%' : '-100%';
          const exitTo = state.dir > 0 ? '-100%' : '100%';
          const style = isActive
            ? { transform: 'translateX(0)', opacity: 1, zIndex: 2, transition: 'transform .5s cubic-bezier(.2,.65,.3,1), opacity .4s ease' }
            : isLeaving
            ? { transform: `translateX(${exitTo})`, opacity: 0, zIndex: 1, transition: 'transform .5s cubic-bezier(.2,.65,.3,1), opacity .4s ease' }
            : { transform: `translateX(${enterFrom})`, opacity: 0, zIndex: 0, transition: 'none' };
          return (
            <div
              className="testimonial-vslide"
              key={r.name}
              ref={(el) => (slideRefs.current[i] = el)}
              style={{ ...style, pointerEvents: isActive ? 'auto' : 'none' }}
            >
              <TestimonialCard r={r} i={i} />
            </div>
          );
        })}
      </div>
      <div className="testimonial-nav">
        <button type="button" className="testimonial-nav-btn" onClick={goPrev} aria-label="Avis précédents">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"/></svg>
        </button>
        <button type="button" className="testimonial-nav-btn" onClick={goNext} aria-label="Avis suivants">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M9 18l6-6-6-6"/></svg>
        </button>
      </div>
    </div>
  );
}

function Testimonials() {
  const { isMobile } = useContent();
  return (
    <section className="testimonials" id="avis">
      <span className="section-num">— 04</span>
      <div className="wrap">
        <div className="sec-hd" data-reveal>
          <div>
            <span className="sec-num-inline"><Editable id="testimonials.eyebrow">— ils l'ont essayé</Editable></span>
            <h2 className="h-1">
              <Editable id="testimonials.heading1">Trois personnes,</Editable><br/>
              <span className="italic-accent"><Editable id="testimonials.headingItalic">une même</Editable></span> <Editable id="testimonials.heading2">habitude.</Editable>
            </h2>
          </div>
          <p className="lede">
            <Editable id="testimonials.lede">Témoignages collectés auprès des premiers porteurs du Soyeux. Aucune contrepartie, aucune sélection — juste leurs mots.</Editable>
          </p>
        </div>

        {isMobile ? <TestimonialCarousel /> : (
          <div className="testimonial-grid">
            {REVIEWS.map((r, i) => <TestimonialCard r={r} i={i} revealDelay={i} key={r.name} />)}
          </div>
        )}
      </div>
    </section>
  );
}

/* ─── FAQ ─── */

const FAQS = [
  {
    q: 'Le Soyeux est-il compatible avec la plupart des casquettes ?',
    a: 'Oui, avec la grande majorité — casquettes courbes, plates, snapback, trucker, dad cap, fitted. Le bord élastique se glisse sous la sudette intérieure de la plupart des casquettes adultes.',
  },
  {
    q: 'Comment je le mets ? Et combien de temps ça prend ?',
    a: 'Tu déplies le Soyeux, tu glisses son bord sous la sudette intérieure de la casquette en suivant le tour de tête. Quelques secondes, sans outils, sans couture, sans colle.',
  },
  {
    q: 'Est-ce qu\'il se voit de l\'extérieur ?',
    a: 'Non. Le Soyeux remplace la doublure intérieure existante : il reste invisible une fois la casquette portée.',
  },
  {
    q: 'Comment je l\'entretiens ?',
    a: 'Lavable à la main ou en machine à 30° — idéalement dans un filet de lavage pour préserver la fibre. Séchage à plat, à l\'air libre ou en appuyant dessus délicatement avec une serviette sèche. Pas de sèche-linge.',
  },
  {
    q: 'Combien de Soyeux pour combien de casquettes ?',
    a: 'Un seul Soyeux suffit. Tu le retires d\'une casquette, tu le glisses dans une autre. Nous l\'avons en 2 coloris, blanc et noir. Si tu portes une casquette tous les jours, mieux vaut en avoir deux : le temps que l\'un sèche après lavage, l\'autre prend le relais.',
  },
  {
    q: 'Pourquoi une précommande ?',
    a: 'Le premier lot est en cours de fabrication, en petite quantité. Précommander garantit ta place dedans.',
  },
  {
    q: 'Quand je le reçois ?',
    a: 'Expédition prévue fin novembre 2026, email dès l\'envoi.',
  },
  {
    q: 'Je peux annuler ?',
    a: 'Oui, à tout moment avant l\'envoi, remboursement intégral.',
  },
];

// Clicking copies the email to the clipboard instead of opening a mail
// client — clicking a mailto: link takes the visitor off the site
// entirely, which we never want to do.
const SUPPORT_EMAIL = 'support@boutiquesoyeux.fr';

// navigator.clipboard needs a "secure context" (HTTPS, or plain
// http://localhost) — it's silently unavailable when the site is reached
// over a bare LAN IP like http://192.168.x.x:3000 (testing on a phone
// before the real domain is live) or any other non-HTTPS address. The
// old execCommand('copy') route still works there, but plain
// textarea.select() is unreliable on iOS Safari specifically — it needs
// an actual Range/Selection instead. readonly is deliberately left off
// (older iOS versions can refuse to select a readonly field), the
// textarea gets real (if tiny) visible dimensions rather than being
// pushed off-screen (some mobile browsers won't select non-rendered
// content), and font-size 16px stops iOS auto-zooming in on it.
function legacyCopy(text) {
  const ta = document.createElement('textarea');
  ta.value = text;
  Object.assign(ta.style, {
    position: 'fixed', top: '0', left: '0', width: '2em', height: '2em',
    padding: '0', border: 'none', outline: 'none', boxShadow: 'none',
    background: 'transparent', fontSize: '16px', opacity: '0.01',
  });
  document.body.appendChild(ta);

  const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
  if (isIOS) {
    const range = document.createRange();
    range.selectNodeContents(ta);
    const selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range);
    ta.setSelectionRange(0, text.length);
  } else {
    ta.focus();
    ta.select();
  }

  let ok = false;
  try {
    ok = document.execCommand('copy');
  } catch {
    ok = false;
  }
  document.body.removeChild(ta);
  return ok;
}

function CopyEmailButton({ className, style, children }) {
  const [copied, setCopied] = React.useState(false);
  const onClick = async () => {
    let ok = false;
    try {
      await navigator.clipboard.writeText(SUPPORT_EMAIL);
      ok = true;
    } catch {
      ok = legacyCopy(SUPPORT_EMAIL);
    }
    if (ok) {
      setCopied(true);
      setTimeout(() => setCopied(false), 1800);
    }
  };
  const baseStyle = {
    appearance: 'none', border: 0, background: 'none', padding: 0,
    font: 'inherit', color: 'inherit', cursor: 'pointer',
  };
  return (
    <button type="button" className={className} style={Object.assign(baseStyle, style)} onClick={onClick}>
      {copied ? 'Copié ✓' : children}
    </button>
  );
}

function FAQ() {
  const [open, setOpen] = React.useState(0);
  return (
    <section id="faq">
      <span className="section-num">— 05</span>
      <div className="wrap">
        <div className="faq-wrap">
          <div className="faq-side" data-reveal>
            <span className="sec-num-inline"><Editable id="faq.eyebrow">— questions</Editable></span>
            <h2 className="h-1">
              <Editable id="faq.heading1">Tout ce que tu te</Editable> <span className="italic-accent"><Editable id="faq.headingItalic">demandes.</Editable></span>
            </h2>
            <p className="lede" style={{ marginTop: 24 }}>
              <Editable id="faq.supportLede">Et si la réponse n'y est pas, on répond en moins de 24h.</Editable>
              <br/><CopyEmailButton style={{ borderBottom: '1px solid', paddingBottom: 2 }}><Editable id="faq.supportEmail">support@boutiquesoyeux.fr</Editable></CopyEmailButton>
            </p>
          </div>

          <div className="faq-list" data-reveal data-reveal-delay="1">
            {FAQS.map((f, i) => (
              <div className={`faq-item ${open === i ? 'open' : ''}`} key={i}>
                <button className="faq-q" onClick={() => setOpen(open === i ? -1 : i)}>
                  <span><Editable id={`faq.item${i}.q`}>{f.q}</Editable></span>
                  <span className="faq-toggle">+</span>
                </button>
                <div className="faq-a"><p><Editable id={`faq.item${i}.a`}>{f.a}</Editable></p></div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

/* ─── Garantie ─── */

function Guarantee() {
  const { selectedVariant, product, loading, formatPrice } = useShopifyProduct();
  const priceNode = selectedVariant?.price || product?.priceRange?.minVariantPrice;
  const priceLabel = loading
    ? '···'
    : priceNode
      ? formatPrice(priceNode.amount, priceNode.currencyCode)
      : '29,99€';

  return (
    <section className="guarantee" id="garantie">
      <span className="section-num">— 06</span>
      <div className="wrap">
        <div className="guarantee-inner">
          <div data-reveal>
            <span className="eyebrow eyebrow-gold"><Editable id="guarantee.eyebrow">— garantie</Editable></span>
            <h2 className="h-1" style={{ marginTop: 14, lineHeight: 1.18 }}>
              <Editable id="guarantee.heading1">Satisfait, ou remboursé.</Editable><br/>
              <span className="italic-accent"><Editable id="guarantee.headingItalic">14 jours pour l'essayer, vraiment.</Editable></span>
            </h2>
            <div style={{ marginTop: 32, display: 'flex', gap: 16, alignItems: 'center', flexWrap: 'wrap' }}>
              <a href="#produit" className="btn btn-primary">
                <Editable id="guarantee.ctaLabel">Commander</Editable> · {priceLabel}
              </a>
              <span className="body-sm"><Editable id="guarantee.caption">Livraison France métropolitaine offerte dès 50€ d'achats.</Editable></span>
            </div>
          </div>

          <div className="guarantee-seal" data-reveal data-reveal-delay="1">
            <svg className="spin-text" viewBox="0 0 320 320">
              <defs>
                <path id="circ" d="M 160, 160 m -128, 0 a 128,128 0 1,1 256,0 a 128,128 0 1,1 -256,0" />
              </defs>
              <text fontSize="16" fontFamily="Inter" fontWeight="600" letterSpacing="2.5" fill="var(--gold-deep)">
                <textPath href="#circ">SATISFAIT OU REMBOURSÉ · 14 JOURS · SOYEUX · ESSAI LIBRE · SANS RISQUE · </textPath>
              </text>
            </svg>
            <div className="seal-circle" />
            <div className="seal-text">
              <span className="seal-tag"><Editable id="guarantee.sealTag">jours</Editable></span>
              <span className="seal-num"><Editable id="guarantee.sealNum">14</Editable></span>
              <span className="seal-italic"><Editable id="guarantee.sealItalic">essai libre</Editable></span>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ─── Newsletter ─── */

function Newsletter() {
  const [email, setEmail] = React.useState('');
  const [sent, setSent] = React.useState(false);
  const [sending, setSending] = React.useState(false);
  const [error, setError] = React.useState(null);
  const submit = async (e) => {
    e.preventDefault();
    if (!email || sending) return;
    setSending(true);
    setError(null);
    try {
      const res = await fetch('/api/newsletter', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'Échec de l\'inscription');
      setSent(true);
    } catch (err) {
      setError(err.message);
    } finally {
      setSending(false);
    }
  };
  return (
    <section className="newsletter" id="offre">
      <span className="section-num" style={{ color: 'var(--gold-deep)' }}>— 07</span>
      <div className="wrap">
        <div className="newsletter-eyebrow eyebrow eyebrow-rule" data-reveal><Editable id="newsletter.eyebrow">première commande</Editable></div>
        <h2 className="h-1" data-reveal data-reveal-delay="1">
          <Editable id="newsletter.heading1">Dix pourcents.</Editable><br/>
          <span className="italic-accent" style={{ color: 'var(--gold-deep)' }}><Editable id="newsletter.headingItalic">Pour bien commencer.</Editable></span>
        </h2>
        <p className="newsletter-lede lede" data-reveal data-reveal-delay="2">
          <Editable id="newsletter.lede">Inscris-toi, on t'envoie ton code promo. Et puis, parfois, une lettre quand on a quelque chose à raconter. Pas plus.</Editable>
        </p>

        <form className="newsletter-form" onSubmit={submit} data-reveal data-reveal-delay="3">
          <input
            type="email"
            placeholder="ton@email.fr"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            disabled={sent}
            required
          />
          <button type="submit" disabled={sending || sent}>
            {sent ? 'Merci ✓' : sending ? 'Un instant…' : 'Recevoir −10 %'}
          </button>
        </form>
        {error && <p className="newsletter-error">{error}</p>}
        <p className="newsletter-fineprint" data-reveal data-reveal-delay="4">
          <Editable id="newsletter.fineprint">On déteste le spam autant que toi. Désinscription en un clic.</Editable>
        </p>
      </div>
    </section>
  );
}

/* ─── Footer ─── */

function Footer() {
  return (
    <footer className="footer">
      <div className="wrap">
        <div className="footer-top">
          <div className="footer-brand">
            <span className="logo"><Editable id="footer.logo">Soyeux</Editable></span>
            <p><Editable id="footer.description">La soie, directement dans toutes tes casquettes. Une doublure amovible en pure soie mulberry 6A, naturelle et précieuse.</Editable></p>
          </div>
          <div className="footer-col">
            <h4><Editable id="footer.col1Title">Produit</Editable></h4>
            <ul>
              <li><a href="#produit"><Editable id="footer.col1Link1">Le Soyeux</Editable></a></li>
              <li><a href="#bienfaits"><Editable id="footer.col1Link2">Bienfaits</Editable></a></li>
              <li><a href="#methode"><Editable id="footer.col1Link3">Comment ça marche</Editable></a></li>
              <li><a href="#garantie"><Editable id="footer.col1Link4">Garantie</Editable></a></li>
            </ul>
          </div>
          <div className="footer-col">
            <h4><Editable id="footer.col2Title">Maison</Editable></h4>
            <ul>
              <li><a href="#"><Editable id="footer.col2Link1">À propos</Editable></a></li>
              <li><a href="#"><Editable id="footer.col2Link2">Journal</Editable></a></li>
              <li><a href="#"><Editable id="footer.col2Link3">Presse</Editable></a></li>
              <li><CopyEmailButton className="footer-copy-btn"><Editable id="footer.col2Link4">Contact</Editable></CopyEmailButton></li>
            </ul>
          </div>
          <div className="footer-col">
            <h4><Editable id="footer.col3Title">Légal</Editable></h4>
            <ul>
              <li><a href="/legal/mentions-legales.html"><Editable id="footer.col3Link1">Mentions légales</Editable></a></li>
              <li><a href="/legal/cgv.html"><Editable id="footer.col3Link2">CGV</Editable></a></li>
              <li><a href="/legal/confidentialite.html"><Editable id="footer.col3Link3">Confidentialité</Editable></a></li>
              <li><a href="https://www.instagram.com/boutiquesoyeux" target="_blank" rel="noopener"><Editable id="footer.col3Link4">Instagram</Editable></a></li>
              <li><a href="https://www.tiktok.com/@boutiquesoyeux" target="_blank" rel="noopener"><Editable id="footer.col3Link5">TikTok</Editable></a></li>
            </ul>
          </div>
        </div>

        <div className="footer-mega" aria-hidden="true"><Editable id="footer.mega">soyeux.</Editable></div>

        <div className="footer-bottom">
          <span><Editable id="footer.copyright">Soyeux © 2026 — La soie dans toutes tes casquettes.</Editable></span>
          <span></span>
        </div>
      </div>
    </footer>
  );
}

window.Testimonials = Testimonials;
window.FAQ = FAQ;
window.Guarantee = Guarantee;
window.Newsletter = Newsletter;
window.Footer = Footer;
