/* NEKTAR v2 — Sections (Hero, Histoire, Sélection, Livraison, Lieu, Suivre, Footer) */
const { useState, useEffect, useRef, useCallback, useContext, createContext } = React;
const D = window.NEKTAR_DATA;

/* ============================================================
   LangContext — partagé par toute l'app
   ============================================================ */
const LangContext = createContext({ lang: 'fr', setLang: () => {} });
window.LangContext = LangContext;

function useCopy() {
  const { lang } = useContext(LangContext);
  return D.COPY[lang] || D.COPY.fr;
}
window.useCopy = useCopy;

/* ============================================================
   HERO
   ============================================================ */
function HeroSection() {
  const c = useCopy();
  const imgRef = useRef(null);
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    const img = imgRef.current;
    if (img && img.complete && img.naturalWidth > 0) setLoaded(true);
  }, []);

  return (
    <section className="hero" id="accueil" data-layout="centered"
      style={{ '--hero-overlay': 'linear-gradient(180deg, rgba(13,27,62,0.45) 0%, rgba(13,27,62,0.25) 35%, rgba(13,27,62,0.70) 100%)' }}>

      <div className="hero__photo">
        <img ref={imgRef}
          className={loaded ? 'is-loaded' : ''}
          src={D.HERO_IMG}
          alt=""
          onLoad={() => setLoaded(true)}
          loading="eager" decoding="async" />
      </div>
      <div className="hero__grain" aria-hidden="true"></div>
      <div className="hero__overlay" aria-hidden="true"></div>

      <div className="hero__inner" id="content">
        <div className="hero__copy">
          <span className="hero__eyebrow">{c.hero.eyebrow}</span>
          <h1 className="hero__title">
            <span className="hero__title-or">{c.hero.word}</span>
          </h1>
          <div className="hero__cta-row">
            <a className="hero__cta"
              href={D.OPENTABLE_URL}
              target="_blank" rel="noopener noreferrer">
              {c.hero.cta}&nbsp;&nbsp;→
            </a>
          </div>
        </div>
      </div>

      <div className="hero__foot">
        <div className="addr">
          {c.hero.addrLine}<br />
          {c.hero.hoursLine}
        </div>
        <a className="scroll" href="#histoire">
          <span className="rule"></span>
          <span>{c.hero.discover}</span>
        </a>
      </div>
    </section>
  );
}

/* ============================================================
   NOTRE HISTOIRE
   ============================================================ */
function HistoireSection() {
  const c = useCopy();
  return (
    <section className="histoire" id="histoire" aria-label={c.histoire.aria}>
      <h2 className="visually-hidden">{c.histoire.aria}</h2>
      <div className="histoire__photo">
        <img src={D.HISTOIRE_IMG} alt="Un verre de vin — Nektar" loading="lazy" />
      </div>
      <div className="histoire__text">
        <p className="histoire__body" dangerouslySetInnerHTML={{ __html: c.histoire.body }} />
        <div className="histoire__rule" aria-hidden="true"></div>
        <p className="histoire__signature">
          {c.histoire.signaturePrefix} <span className="histoire__signature-cinq">{c.histoire.signatureWord}</span>
        </p>
      </div>
    </section>
  );
}

/* ============================================================
   SÉLECTION — bulles physiques
   ============================================================ */
function formatName(name) {
  const parts = name.split(' ');
  if (parts.length <= 1) return name;
  if (parts.length === 2) return parts[0] + '\n' + parts[1];
  const mid = Math.ceil(parts.length / 2);
  return parts.slice(0, mid).join(' ') + '\n' + parts.slice(mid).join(' ');
}

function makeSrand(seed) {
  let s = seed;
  return () => { s = (s * 9301 + 49297) % 233280; return s / 233280; };
}

function initPhysics({ count, r, w, h }) {
  const rand = makeSrand(99);
  const gap  = 10;
  const minD = r * 2 + gap;
  const pad  = r + 8;
  const ctaR = Math.min(w, h) * 0.17;

  const bubbles = [];
  const shuffled = [...D.DOMAINS].sort(() => rand() - 0.5);

  for (const name of shuffled) {
    if (bubbles.length >= count) break;
    for (let attempt = 0; attempt < 400; attempt++) {
      const cx = pad + rand() * (w - pad * 2);
      const cy = pad + rand() * (h - pad * 2);
      const dx0 = cx - w / 2, dy0 = cy - h / 2;
      if (dx0 * dx0 + dy0 * dy0 < (ctaR + r) * (ctaR + r)) continue;
      const clash = bubbles.some(b => {
        const dx = b.cx - cx, dy = b.cy - cy;
        return dx * dx + dy * dy < minD * minD;
      });
      if (clash) continue;
      const angle = rand() * Math.PI * 2;
      const speed = 0.25 + rand() * 0.35;
      bubbles.push({
        name, formatted: formatName(name),
        cx, cy,
        vx: Math.cos(angle) * speed,
        vy: Math.sin(angle) * speed,
        el: null,
      });
      break;
    }
  }
  return bubbles;
}

function tickPhysics(bubbles, r, w, h) {
  const ctaR = Math.min(w, h) * 0.17;
  const cx0 = w / 2, cy0 = h / 2;
  for (const b of bubbles) {
    b.cx += b.vx; b.cy += b.vy;
    if (b.cx - r < 0)  { b.cx = r;     b.vx =  Math.abs(b.vx); }
    if (b.cx + r > w)  { b.cx = w - r; b.vx = -Math.abs(b.vx); }
    if (b.cy - r < 0)  { b.cy = r;     b.vy =  Math.abs(b.vy); }
    if (b.cy + r > h)  { b.cy = h - r; b.vy = -Math.abs(b.vy); }
    const dxC = b.cx - cx0, dyC = b.cy - cy0;
    const distC = Math.sqrt(dxC * dxC + dyC * dyC);
    const minC = ctaR + r + 6;
    if (distC < minC) {
      const nx = dxC / (distC || 1), ny = dyC / (distC || 1);
      const dot = b.vx * nx + b.vy * ny;
      if (dot < 0) { b.vx -= 2 * dot * nx; b.vy -= 2 * dot * ny; }
      b.cx += nx * (minC - distC);
      b.cy += ny * (minC - distC);
    }
  }
  for (let i = 0; i < bubbles.length; i++) {
    for (let j = i + 1; j < bubbles.length; j++) {
      const a = bubbles[i], b = bubbles[j];
      const dx = b.cx - a.cx, dy = b.cy - a.cy;
      const dist = Math.sqrt(dx * dx + dy * dy);
      const minD = r * 2 + 4;
      if (dist < minD && dist > 0) {
        const nx = dx / dist, ny = dy / dist;
        const dvx = a.vx - b.vx, dvy = a.vy - b.vy;
        const dot = dvx * nx + dvy * ny;
        if (dot > 0) {
          a.vx -= dot * nx; a.vy -= dot * ny;
          b.vx += dot * nx; b.vy += dot * ny;
        }
        const push = (minD - dist) / 2;
        a.cx -= nx * push; a.cy -= ny * push;
        b.cx += nx * push; b.cy += ny * push;
      }
    }
  }
}

function paramsFor(w) {
  if (w >= 1200) return { size: 138, count: 12 };
  if (w >= 768)  return { size: 116, count: 8 };
  return            { size: 96,  count: 6 };
}

function SelectionSection() {
  const c = useCopy();
  const containerRef = useRef(null);
  const physRef = useRef(null);
  const [ready, setReady] = useState(false);
  const [version, setVersion] = useState(0);

  useEffect(() => {
    let animId = null;

    function init() {
      if (animId) cancelAnimationFrame(animId);
      const el = containerRef.current;
      if (!el) return;
      const rect = el.getBoundingClientRect();
      const w = rect.width;
      const h = rect.height;
      if (h < 200 || w < 200) return;

      const { size, count } = paramsFor(window.innerWidth);
      const r = size / 2;
      const bubbles = initPhysics({ count, r, w, h });
      physRef.current = { bubbles, r, w, h };
      setReady(true);
      setVersion(v => v + 1);

      const loop = () => {
        const ph = physRef.current;
        if (!ph) return;
        tickPhysics(ph.bubbles, ph.r, ph.w, ph.h);
        for (const b of ph.bubbles) {
          if (b.el) {
            b.el.style.left = (b.cx - ph.r).toFixed(1) + 'px';
            b.el.style.top  = (b.cy - ph.r).toFixed(1) + 'px';
          }
        }
        animId = requestAnimationFrame(loop);
      };
      animId = requestAnimationFrame(loop);
    }

    init();

    let resizeTimer;
    const onResize = () => {
      clearTimeout(resizeTimer);
      resizeTimer = setTimeout(init, 80);
    };
    window.addEventListener('resize', onResize);

    // ResizeObserver sur la section pour re-init au changement de hauteur
    let ro;
    if (window.ResizeObserver && containerRef.current) {
      ro = new ResizeObserver(onResize);
      ro.observe(containerRef.current);
    }

    return () => {
      if (animId) cancelAnimationFrame(animId);
      window.removeEventListener('resize', onResize);
      clearTimeout(resizeTimer);
      if (ro) ro.disconnect();
    };
  }, []);

  const ph = physRef.current;
  const bubbles = ph ? ph.bubbles : [];
  const r = ph ? ph.r : 69;

  return (
    <section className="selection" id="carte" ref={containerRef} aria-label={c.selection.cta}>
      <h2 className="visually-hidden">{c.selection.cta}</h2>
      {ready && bubbles.map(b => (
        <div key={b.name + '-' + version}
          className="bubble"
          ref={el => { b.el = el; }}
          aria-hidden="true"
          style={{
            left: (b.cx - r).toFixed(1) + 'px',
            top:  (b.cy - r).toFixed(1) + 'px',
            width: r * 2 + 'px',
            height: r * 2 + 'px',
          }}>
          {b.formatted}
        </div>
      ))}
      <nav className="selection__center" aria-label={c.selection.cta}>
        <a className="selection__cta"
          href={D.SOMMIT_URL}
          target="_blank" rel="noopener noreferrer"
          aria-label={c.selection.cta}>
          {c.selection.cta}
        </a>
      </nav>
    </section>
  );
}

/* ============================================================
   LIVRAISON — formulaire Formspree
   ============================================================ */
function DrawerForm({ open, onClose }) {
  const c = useCopy();
  const lang = c.lang;
  const liv = c.livraison;
  const [sent, setSent] = useState(false);
  const [errors, setErrors] = useState({});
  const [submitError, setSubmitError] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [form, setForm] = useState({ nom: '', tel: '', email: '', date: '', type: '', message: '' });
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const today = new Date().toISOString().split('T')[0];

  const validate = () => {
    const e = {};
    if (!form.nom.trim())   e.nom   = true;
    if (!form.tel.trim())   e.tel   = true;
    if (!form.email.trim() || !/^[^@]+@[^@]+\.[^@]+$/.test(form.email)) e.email = true;
    if (!form.date || form.date < today) e.date = true;
    if (!form.message.trim()) e.message = true;
    return e;
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    const errs = validate();
    if (Object.keys(errs).length) { setErrors(errs); return; }
    setErrors({}); setSubmitError(false); setSubmitting(true);
    try {
      const res = await fetch(D.FORMSPREE_URL, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
        body: JSON.stringify(form),
      });
      if (res.ok) setSent(true);
      else setSubmitError(true);
    } catch (err) {
      setSubmitError(true);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <>
      <div className={'livraison__backdrop' + (open ? ' is-open' : '')} onClick={onClose} aria-hidden="true" />
      <div className={'livraison__drawer' + (open ? ' is-open' : '')} role="dialog" aria-modal="true" aria-label={liv.drawerTitle}>
        <div className="livraison__drawer-head">
          <h2 className="livraison__drawer-title">{liv.drawerTitle}</h2>
          <button className="livraison__close" onClick={onClose} aria-label={liv.close}>{liv.close}</button>
        </div>
        {sent ? (
          <p className="livraison__confirm">{liv.confirm}</p>
        ) : (
          <form className="livraison__form" onSubmit={handleSubmit} noValidate>
            <div>
              <label className="livraison__label" htmlFor="lr-nom">{liv.labels.nom} *</label>
              <input id="lr-nom" className={'livraison__input' + (errors.nom ? ' is-error' : '')} type="text" autoComplete="name" value={form.nom} onChange={e => set('nom', e.target.value)} />
            </div>
            <div>
              <label className="livraison__label" htmlFor="lr-tel">{liv.labels.tel} *</label>
              <input id="lr-tel" className={'livraison__input' + (errors.tel ? ' is-error' : '')} type="tel" autoComplete="tel" value={form.tel} onChange={e => set('tel', e.target.value)} />
            </div>
            <div>
              <label className="livraison__label" htmlFor="lr-email">{liv.labels.email} *</label>
              <input id="lr-email" className={'livraison__input' + (errors.email ? ' is-error' : '')} type="email" autoComplete="email" value={form.email} onChange={e => set('email', e.target.value)} />
            </div>
            <div>
              <label className="livraison__label" htmlFor="lr-date">{liv.labels.date} *</label>
              <input id="lr-date" className={'livraison__input' + (errors.date ? ' is-error' : '')} type="date" min={today} value={form.date} onChange={e => set('date', e.target.value)} />
            </div>
            <div>
              <label className="livraison__label" htmlFor="lr-type">{liv.labels.type}</label>
              <input id="lr-type" className="livraison__input" type="text" placeholder={liv.placeholder.type} value={form.type} onChange={e => set('type', e.target.value)} />
            </div>
            <div className="livraison__field--full">
              <label className="livraison__label" htmlFor="lr-msg">{liv.labels.msg} *</label>
              <textarea id="lr-msg" className={'livraison__textarea' + (errors.message ? ' is-error' : '')} placeholder={liv.placeholder.msg} value={form.message} onChange={e => set('message', e.target.value)} />
            </div>
            {Object.keys(errors).length > 0 && (
              <p className="livraison__error-msg">{liv.errFields}</p>
            )}
            {submitError && (
              <p className="livraison__error-msg">{liv.errSubmit}</p>
            )}
            <button type="submit" className="livraison__submit" disabled={submitting}>
              {submitting ? liv.sending : liv.labels.submit}
            </button>
          </form>
        )}
      </div>
    </>
  );
}

function LivraisonSection() {
  const c = useCopy();
  const liv = c.livraison;
  const [formOpen, setFormOpen] = useState(false);

  const handleOption = (opt) => {
    if (opt.action === 'form') setFormOpen(true);
    else if (opt.action) window.open(opt.action, '_blank', 'noopener,noreferrer');
  };

  return (
    <>
      <main className="livraison" id="livraison" aria-label={liv.ariaMain}>
        <h2 className="livraison__hero-title">
          <span className="livraison__hero-or">{liv.title}</span>
          <span className="livraison__hero-creme"> {liv.titleSub}</span>
        </h2>
        <div className="livraison__options" role="list">
          {liv.options.map(opt => (
            <button key={opt.id}
              className={'livraison__option' + (opt.soon ? ' is-soon' : '')}
              role="listitem"
              onClick={() => !opt.soon && handleOption(opt)}
              disabled={!!opt.soon}
              aria-label={opt.name}>
              <div className="livraison__opt-label">
                <span className="livraison__opt-num">{opt.num}</span>
                <span className="livraison__opt-name">{opt.name}</span>
              </div>
              <span className="livraison__opt-desc">
                {opt.soon ? liv.soon : opt.desc}
              </span>
            </button>
          ))}
        </div>
      </main>
      <DrawerForm open={formOpen} onClose={() => setFormOpen(false)} />
    </>
  );
}

/* ============================================================
   LIEU — galerie 8 photos auto-défilement
   ============================================================ */
function ArrowSvg({ dir }) {
  const points = dir === 'left' ? '20,6 12,16 20,26' : '12,6 20,16 12,26';
  return (
    <svg width="32" height="32" viewBox="0 0 32 32" fill="none" aria-hidden="true">
      <polyline points={points} stroke="currentColor" strokeWidth="1" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

function LieuSection() {
  const c = useCopy();
  const [current, setCurrent] = useState(0);
  const [paused, setPaused]   = useState(false);
  const [progKey, setProgKey] = useState(0);
  const total = D.LIEU_PHOTOS.length;
  const autoRef   = useRef(null);
  const resumeRef = useRef(null);
  const touchX    = useRef(null);

  const goTo = useCallback((idx) => {
    setCurrent(((idx % total) + total) % total);
    setProgKey(k => k + 1);
  }, [total]);

  const goNext = useCallback(() => goTo(current + 1), [goTo, current]);
  const goPrev = useCallback(() => goTo(current - 1), [goTo, current]);

  const manual = useCallback((fn) => {
    setPaused(true);
    clearTimeout(resumeRef.current);
    fn();
    resumeRef.current = setTimeout(() => setPaused(false), 4000);
  }, []);

  useEffect(() => {
    if (paused) { clearInterval(autoRef.current); return; }
    autoRef.current = setInterval(() => {
      setCurrent(prev => (prev + 1) % total);
      setProgKey(k => k + 1);
    }, 3000);
    return () => clearInterval(autoRef.current);
  }, [paused, total]);

  const onTouchStart = (e) => { touchX.current = e.touches[0].clientX; };
  const onTouchEnd = (e) => {
    if (touchX.current === null) return;
    const dx = e.changedTouches[0].clientX - touchX.current;
    touchX.current = null;
    if (Math.abs(dx) < 44) return;
    manual(dx < 0 ? goNext : goPrev);
  };

  return (
    <section id="galerie" aria-label={c.lieu.aria}>
      <h2 className="visually-hidden">{c.lieu.aria}</h2>
      <div className="gallery"
        role="region"
        aria-label={c.lieu.aria}
        onMouseEnter={() => setPaused(true)}
        onMouseLeave={() => setPaused(false)}
        onTouchStart={onTouchStart}
        onTouchEnd={onTouchEnd}>
        {D.LIEU_PHOTOS.map((url, i) => (
          <div key={url}
            className={'gallery__slide' + (i === current ? ' is-active' : '')}
            aria-hidden={i !== current}>
            <img src={url} alt={`Nektar — photo ${i + 1}`}
              loading={i === 0 ? 'eager' : 'lazy'} decoding="async" />
          </div>
        ))}
        <button className="gallery__arrow gallery__arrow--prev"
          onClick={() => manual(goPrev)} aria-label={c.lieu.prevPhoto}>
          <ArrowSvg dir="left" />
        </button>
        <button className="gallery__arrow gallery__arrow--next"
          onClick={() => manual(goNext)} aria-label={c.lieu.nextPhoto}>
          <ArrowSvg dir="right" />
        </button>
        <div className="gallery__label" aria-hidden="true">{c.lieu.label}</div>
        <div className="gallery__dots" aria-hidden="true">
          {D.LIEU_PHOTOS.map((_, i) => (
            <button key={i}
              className={'gallery__dot' + (i === current ? ' is-active' : '')}
              onClick={() => manual(() => goTo(i))}
              aria-label={`Photo ${i + 1}`} />
          ))}
        </div>
        <div key={`prog-${progKey}`}
          className={'gallery__progress' + (!paused ? ' is-running' : '')} />
      </div>
    </section>
  );
}

/* ============================================================
   SUIVRE — grille Instagram
   ============================================================ */
function SuivreSection() {
  const c = useCopy();
  return (
    <section className="suivre" id="suivre" aria-label={c.suivre.aria}>
      <header className="suivre__header">
        <h2 className="suivre__titre">{c.suivre.title}</h2>
      </header>
      <div className="suivre__grid">
        {D.INSTA_PHOTOS.map((p, i) => (
          <a key={i} className="suivre__slot"
            href={p.href}
            target="_blank" rel="noopener noreferrer"
            aria-label={`Photo Instagram ${i + 1}`}>
            <img src={p.src} alt={p.alt} loading="lazy" />
          </a>
        ))}
      </div>
      <div className="suivre__cta">
        <a className="suivre__follow"
          href={D.INSTAGRAM_URL}
          target="_blank" rel="noopener noreferrer">
          @nektar_paris
        </a>
      </div>
    </section>
  );
}

/* ============================================================
   FOOTER
   ============================================================ */
function FooterSection({ onScrollToLivraison }) {
  const c = useCopy();
  const f = c.footer;
  return (
    <footer className="footer" aria-label="Pied de page">
      <div className="footer__inner">
        <div className="footer__cols">

          <div className="footer__col">
            <div className="footer__col-head"><p className="footer__label">{f.horaires}</p></div>
            <p className="footer__text" dangerouslySetInnerHTML={{ __html: f.heures }} />
          </div>

          <div className="footer__col">
            <div className="footer__col-head"><p className="footer__label">{f.reserver}</p></div>
            <div className="footer__links">
              <a href={D.OPENTABLE_URL} className="footer__link" target="_blank" rel="noopener noreferrer">{f.reserverLink}</a>
            </div>
          </div>

          <div className="footer__col">
            <div className="footer__col-head"><p className="footer__label">{f.domicile}</p></div>
            <div className="footer__links">
              <a href="#livraison" className="footer__link"
                onClick={(e) => { e.preventDefault(); onScrollToLivraison && onScrollToLivraison(); }}>
                {f.commandeDirect}
              </a>
              <span className="footer__link footer__link--soon">{f.deliveroo} <em>— {f.soon}</em></span>
              <span className="footer__link footer__link--soon">{f.ubereats} <em>— {f.soon}</em></span>
            </div>
          </div>

          <div className="footer__col">
            <div className="footer__col-head"><p className="footer__label">{f.contacter}</p></div>
            <div className="footer__links">
              <a href={D.INSTAGRAM_URL} className="footer__link" target="_blank" rel="noopener noreferrer">{f.instagram}</a>
              <a href="mailto:clients@nektar-paris.com" className="footer__link">clients@nektar-paris.com</a>
            </div>
          </div>

        </div>
        <div className="footer__bottom">
          <p className="footer__address">{f.address}</p>
          <a href="mentions-legales.html" className="footer__mentions">{f.mentions}</a>
        </div>
      </div>
    </footer>
  );
}

/* ============================================================
   Expose to window for app.jsx
   ============================================================ */
Object.assign(window, {
  HeroSection, HistoireSection, SelectionSection,
  LivraisonSection, LieuSection, SuivreSection, FooterSection,
});
