/* global React */
const { useEffect, useState, useRef } = React;

/* ============================================================
   Shared atoms
   ============================================================ */

/* tel:/wa.me href helpers — strip spaces, drop the "+" for wa.me */
const telHref = (phone) => 'tel:' + String(phone).replace(/\s+/g, '');
const waHref = (phone, msg) => {
  const num = String(phone).replace(/[\s+]/g, '');
  const params = msg ? '?text=' + encodeURIComponent(msg) : '';
  return 'https://wa.me/' + num + params;
};
const WEBCRAFTDEV_URL = 'https://webcraftdev.com';

const Logo = () => (
  <a className="wcd-logo" href={WEBCRAFTDEV_URL} target="_blank" rel="noopener noreferrer" aria-label="WebCraftDev">
    <img className="wcd-mark-img" src="img/webcraft-logo-gold.webp" alt="" />
    <div className="wcd-text">WebCraftDev</div>
  </a>
);

const PageTop = ({ left, right, tone }) => (
  <div className="page-chrome-top">
    <div style={{ color: 'var(--gold)' }}>{left}</div>
    <div className="muted">{right}</div>
  </div>
);

/* PageBottom — `left` is always cover.web ("webcraftdev.com"); make it
   a real link to the WebCraftDev site. `right` stays a static page-num. */
const PageBottom = ({ left, right }) => (
  <div className="page-chrome-bottom">
    <a className="muted chrome-link" href={WEBCRAFTDEV_URL} target="_blank" rel="noopener noreferrer">{left}</a>
    <div className="page-num">{right}</div>
  </div>
);

const Placeholder = ({ label, sub, style, className = "" }) => (
  <div className={`placeholder ${className}`} style={style}>
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 14 }}>
      <div className="ph-label">{label}</div>
      {sub ? <div style={{ fontSize: 10, opacity: 0.7, letterSpacing: '0.18em' }}>{sub}</div> : null}
    </div>
  </div>
);

/* Animated count-up for stats */
const CountUp = ({ value, suffix = "", duration = 1400, format = (v) => v }) => {
  const [display, setDisplay] = useState(0);
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let raf, start;
    const observer = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting && !start) {
          start = performance.now();
          const tick = (now) => {
            const t = Math.min(1, (now - start) / duration);
            const eased = 1 - Math.pow(1 - t, 3);
            setDisplay(Math.round(value * eased));
            if (t < 1) raf = requestAnimationFrame(tick);
          };
          raf = requestAnimationFrame(tick);
        }
      });
    }, { threshold: 0.4 });
    observer.observe(el);
    return () => { observer.disconnect(); if (raf) cancelAnimationFrame(raf); };
  }, [value]);
  return <span ref={ref}>{format(display)}{suffix}</span>;
};

/* ============================================================
   Slide 01 — Hero (cover + who, merged)
   ============================================================ */
const SlideCover = ({ c, who }) => (
  <section className="tone-dark" data-screen-label="01 Cover">
    <div className="cover-grid"></div>
    <div className="cover-glow" style={{ top: '-300px', right: '-300px' }}></div>
    <div className="cover-glow" style={{ bottom: '-500px', left: '-200px', width: '900px', height: '900px', opacity: 0.5 }}></div>

    <div className="page-chrome-top">
      <Logo />
      <div className="muted reveal reveal-1">{c.kicker}</div>
    </div>

    <div className="frame" style={{ paddingTop: 132, paddingBottom: 132, height: '100%', display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 80, alignItems: 'center' }}>
      <div>
        <div className="kicker reveal reveal-1" style={{ marginBottom: 22 }}>{c.role.toUpperCase()}</div>
        <h1 className="display-black reveal reveal-2" style={{ fontSize: 140, margin: 0, lineHeight: 0.92, color: 'var(--fg-on-dark)' }}>
          MOHAMED <span style={{ color: 'var(--gold)' }}>SAHBI.</span>
        </h1>
        <div className="reveal reveal-3" style={{ marginTop: 28, maxWidth: 760, fontFamily: 'var(--display)', fontSize: 26, lineHeight: 1.3, fontWeight: 400, letterSpacing: '-0.01em', color: 'var(--gold)' }}>
          {c.tagline}
        </div>
        {who ? (
          <p className="reveal reveal-3" style={{ marginTop: 26, maxWidth: 760, fontSize: 17, lineHeight: 1.55, color: 'var(--fg-on-dark)', opacity: 0.92, margin: '26px 0 0' }}>{who.body}</p>
        ) : null}
        {who && who.stats ? (
          <div className="stats-row reveal reveal-4" style={{ marginTop: 36 }}>
            {who.stats.map((s, i) => (
              <div className="stat" key={i}>
                <div className="stat-num">{s.num}</div>
                <div className="stat-label">{s.label}</div>
              </div>
            ))}
          </div>
        ) : null}
      </div>
      <div className="reveal reveal-2" style={{ height: '100%' }}>
        {who && who.photo ? (
          <div className="portrait-frame" style={{ height: '100%', maxHeight: 760, width: '100%' }}>
            <img src={who.photo} alt="Mohamed Sahbi" />
            <div className="portrait-cap">{who.photoLabel}</div>
          </div>
        ) : null}
      </div>
    </div>

    <div className="page-chrome-bottom">
      <div style={{ display: 'flex', gap: 36, fontFamily: 'var(--mono)', fontSize: 12 }}>
        <a className="chrome-link" href={WEBCRAFTDEV_URL} target="_blank" rel="noopener noreferrer">
          <span style={{ color: 'var(--gold)' }}>↳</span> {c.web}
        </a>
        <a className="chrome-link" href={`mailto:${c.mail}`}>
          <span style={{ color: 'var(--gold)' }}>↳</span> {c.mail}
        </a>
        <a className="chrome-link" href={telHref(c.phone)}>
          <span style={{ color: 'var(--gold)' }}>↳</span> {c.phone}
        </a>
      </div>
      <div className="page-num">{c.city}</div>
    </div>
  </section>
);

/* ============================================================
   Slide 02 — Who I Am (DEPRECATED: merged into SlideCover; not rendered)
   ============================================================ */
const SlideWho = ({ c, cover }) => (
  <section className="tone-dark" data-screen-label="02 Who">
    <PageTop left={c.kicker} right="MOHAMED SAHBI · 02 / 21" />
    <div className="frame" style={{ paddingTop: 140 }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 96, height: 'calc(100% - 140px)', alignItems: 'start' }}>
        <div>
          <h2 className="display-black reveal reveal-1" style={{ fontSize: 96, margin: 0, whiteSpace: 'pre-line' }}>{c.title}</h2>
          <div className="gold-rule draw-line" style={{ marginTop: 40, width: 120, height: 2 }}></div>
          <p className="body-lg reveal reveal-2" style={{ marginTop: 40, maxWidth: 760, color: 'var(--fg-on-dark)' }}>{c.body}</p>
          <div className="stats-row reveal reveal-3" style={{ marginTop: 64 }}>
            {c.stats.map((s, i) => (
              <div className="stat" key={i}>
                <div className="stat-num">{s.num}</div>
                <div className="stat-label">{s.label}</div>
              </div>
            ))}
          </div>
        </div>
        <div className="reveal reveal-2" style={{ height: '100%' }}>
          {c.photo ? (
            <div className="portrait-frame" style={{ height: 720, width: '100%' }}>
              <img src={c.photo} alt="Mohamed Sahbi" />
              <div className="portrait-cap">{c.photoLabel}</div>
            </div>
          ) : (
            <Placeholder label={c.photoLabel} sub="JPG · 2400×3000 · drop here" style={{ height: 720, width: '100%' }} />
          )}
        </div>
      </div>
    </div>
    <PageBottom left={cover.web} right="P. 02 / 21" />
  </section>
);

/* ============================================================
   Slide 03 — What I Do
   ============================================================ */
const SlideWhat = ({ c, cover }) => (
  <section className="tone-dark-2" data-screen-label="03 What">
    <PageTop left={c.kicker} right="MOHAMED SAHBI · 02 / 21" />
    <div className="frame" style={{ paddingTop: 140 }}>
      <h2 className="display-black reveal reveal-1" style={{ fontSize: 88, margin: 0, whiteSpace: 'pre-line', maxWidth: 1100 }}>{c.title}</h2>
      <div className="reveal reveal-2" style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 24, marginTop: 64 }}>
        {c.pillars.map((p, i) => (
          <div className="pillar" key={i} style={{ animationDelay: `${0.2 + i * 0.08}s` }}>
            <div className="pillar-corner"></div>
            <div className="pillar-num">{p.n}</div>
            <div className="pillar-title">{p.title}</div>
            <div className="pillar-body">{p.body}</div>
            <div style={{ flex: 1 }}></div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
              {p.tags.map((t, j) => <span className="tag-mono" key={j}>{t}</span>)}
            </div>
          </div>
        ))}
      </div>
    </div>
    <PageBottom left={cover.web} right="P. 02 / 21" />
  </section>
);

/* ============================================================
   Slide 04 — How I Work
   ============================================================ */
const SlideHow = ({ c, cover }) => (
  <section className="tone-dark" data-screen-label="04 How">
    <PageTop left={c.kicker} right="MOHAMED SAHBI · 18 / 21" />
    <div className="frame" style={{ paddingTop: 140 }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.4fr', gap: 96, alignItems: 'start' }}>
        <div className="reveal reveal-1">
          <h2 className="display-black" style={{ fontSize: 80, margin: 0, whiteSpace: 'pre-line' }}>{c.title}</h2>
          <div className="gold-rule draw-line" style={{ marginTop: 32, width: 120, height: 2 }}></div>
          <p className="body-lg" style={{ marginTop: 32, color: 'var(--muted-on-dark)' }}>{c.sub}</p>
        </div>
        <div className="reveal reveal-2">
          {c.steps.map((s, i) => (
            <div className="step" key={i}>
              <div className="step-num">{s.n}</div>
              <div>
                <div className="step-title">{s.title}</div>
                <div className="step-body">{s.body}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
    <PageBottom left={cover.web} right="P. 18 / 21" />
  </section>
);

/* ============================================================
   Slide 05 — Section Divider · Results
   ============================================================ */
const SlideDivider = ({ c, cover }) => (
  <section className="tone-dark" data-screen-label="03 Divider">
    <div className="cover-grid"></div>
    <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 12, background: 'var(--gold)' }}></div>
    <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 12, background: 'var(--gold)' }}></div>
    <PageTop left={c.kicker} right="MOHAMED SAHBI · 03 / 21" />
    <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: '200px 120px 160px' }}>
      <h2 className="display-black reveal reveal-1" style={{ fontSize: 160, margin: 0, lineHeight: 0.94, whiteSpace: 'pre-line', color: 'var(--gold)' }}>{c.title}</h2>
      <p className="reveal reveal-2" style={{ marginTop: 88, fontSize: 28, fontFamily: 'var(--display)', fontWeight: 400, color: 'var(--fg-on-dark)', maxWidth: 1100 }}>{c.sub}</p>
    </div>
    <PageBottom left={cover.web} right="P. 03 / 21" />
  </section>
);

/* ============================================================
   Case Hero — generic
   ============================================================ */
const CaseHero = ({ caseData, idx, cover, label }) => {
  const pageNum = String(4 + idx * 2).padStart(2, '0');
  return (
    <section className="tone-dark" data-screen-label={label}>
      <PageTop left={caseData.kicker} right={`MOHAMED SAHBI · ${pageNum} / 21`} />
      <div className="frame" style={{ paddingTop: 120, paddingBottom: 120 }}>
        <div className="case-hero-grid">
          <div>
            <div className="reveal reveal-1" style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
              {caseData.category.map((t, i) => <span className="tag" key={i}>{t}</span>)}
            </div>
            <h2 className="display-black reveal reveal-2" style={{ fontSize: 96, margin: '28px 0 0', whiteSpace: 'pre-line', wordBreak: 'keep-all', lineHeight: 0.92 }}>{caseData.name}</h2>
            <div className="gold-rule draw-line" style={{ marginTop: 28, width: 120, height: 2 }}></div>
            <p className="reveal reveal-3" style={{ marginTop: 28, fontSize: 24, fontFamily: 'var(--display)', fontWeight: 400, lineHeight: 1.3, maxWidth: 560, color: 'var(--fg-on-dark)' }}>{caseData.sub}</p>
            <div className="reveal reveal-4" style={{ marginTop: 40, display: 'flex', alignItems: 'baseline', gap: 24 }}>
              <div className="kicker">{caseData.metricLabel}</div>
              <div className={`metric-inline ${caseData.metricBig.length > 4 ? 'metric-inline-sm' : ''}`}>
                {caseData.metricBig}
              </div>
            </div>
          </div>
          <div className="reveal reveal-3 case-hero-shot">
            {caseData.image ? (
              <img
                src={caseData.image}
                alt={caseData.name.replace(/\n/g, ' ')}
                onClick={() => window.openLightbox && window.openLightbox(caseData.image)}
                style={{ cursor: 'zoom-in' }}
              />
            ) : (
              <Placeholder label={`${caseData.name.replace(/\n/g, ' ')} · screenshot`} sub="hero shot" style={{ height: '100%', width: '100%' }} />
            )}
          </div>
        </div>
      </div>
      <PageBottom left={cover.web} right={`P. ${pageNum} / 21 · ${caseData.id.toUpperCase()}`} />
    </section>
  );
};

/* ============================================================
   Case Detail — generic
   ============================================================ */
const CaseDetail = ({ caseData, idx, cover, label, labels: labelOverride }) => {
  const pageNum = String(5 + idx * 2).padStart(2, '0');
  const labels = labelOverride || caseData.labels || { defi: "Le défi", solution: "Ma solution", results: "Résultats", detail: "DÉTAIL" };
  const galleryClass = caseData.gallery && caseData.gallery.length === 2 ? 'case-gallery case-gallery--two' : 'case-gallery';
  return (
    <section className="tone-dark-2" data-screen-label={label}>
      <PageTop left={`${caseData.kicker} · ${labels.detail}`} right={`MOHAMED SAHBI · ${pageNum} / 21`} />
      <div className="frame" style={{ paddingTop: 120, paddingBottom: 120, height: '100%', display: 'flex', flexDirection: 'column' }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 24, flexWrap: 'wrap' }}>
          <h3 className="display-black reveal reveal-1" style={{ fontSize: 60, margin: 0, whiteSpace: 'pre-line', lineHeight: 1 }}>{caseData.name}</h3>
          <div className="reveal reveal-1" style={{ fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--gold)', letterSpacing: '0.16em', whiteSpace: 'nowrap' }}>
            {caseData.metricBig} · {caseData.metricLabel}
          </div>
        </div>

        <div className="case-detail-layout reveal reveal-2">
          <div className="case-cols-wrap">
            <div className="case-cols">
              <div className="case-col">
                <h4>{labels.defi}</h4>
                <p>{caseData.defi}</p>
              </div>
              <div className="case-col">
                <h4>{labels.solution}</h4>
                <p>{caseData.solution}</p>
              </div>
              <div className="case-col">
                <h4>{labels.results}</h4>
                <ul>
                  {caseData.results.map((r, i) => <li key={i}>{r}</li>)}
                </ul>
              </div>
            </div>

            <div className="stack-row reveal reveal-4">
              <span className="kicker" style={{ marginRight: 16 }}>STACK</span>
              {caseData.stack.map((s, i) => <span className="tag-mono" key={i}>{s}</span>)}
            </div>
          </div>

          {caseData.gallery && caseData.gallery.length ? (
            <div className={`${galleryClass} reveal reveal-3`}>
              {caseData.gallery.map((g, i) => (
                <figure key={i}>
                  <div className="shot-frame">
                    <img
                      src={g.src}
                      alt={g.caption}
                      onClick={() => window.openLightbox && window.openLightbox(g.src)}
                      style={{ cursor: 'zoom-in' }}
                    />
                  </div>
                  <figcaption>{g.caption}</figcaption>
                </figure>
              ))}
            </div>
          ) : null}
        </div>
      </div>
      <PageBottom left={cover.web} right={`P. ${pageNum} / 21 · ${caseData.id.toUpperCase()}`} />
    </section>
  );
};

/* ============================================================
   Slide — More projects
   ============================================================ */
const SlideMore = ({ c, cover }) => (
  <section className="tone-dark" data-screen-label="More">
    <PageTop left={c.kicker} right="MOHAMED SAHBI · 14 / 21" />
    <div className="frame" style={{ paddingTop: 120 }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 36 }}>
        <h2 className="display-black reveal reveal-1" style={{ fontSize: 80, margin: 0 }}>{c.title}</h2>
        <p className="reveal reveal-2" style={{ fontSize: 16, color: 'var(--muted-on-dark)', maxWidth: 320, margin: 0, fontFamily: 'var(--mono)' }}>{c.sub}</p>
      </div>
      <div className="more-grid reveal reveal-3">
        {c.items.map((it, i) => (
          <div className="more-card" key={i}>
            <div className="mc-shot">
              {it.image ? <img src={it.image} alt={it.name} /> : <div className="mc-shot-ph">{it.name}</div>}
            </div>
            <div className="mc-num">{String(i + 1).padStart(2, '0')}</div>
            <div className="mc-text">
              <div className="mc-name">{it.name}</div>
              <div className="mc-desc">{it.desc}</div>
            </div>
            <div className="mc-stack">{it.stack}</div>
          </div>
        ))}
      </div>
    </div>
    <PageBottom left={cover.web} right="P. 14 / 21" />
  </section>
);

/* ============================================================
   Slide — Stack
   ============================================================ */
const SlideStack = ({ c, cover }) => (
  <section className="tone-dark-2" data-screen-label="Stack">
    <PageTop left={c.kicker} right="MOHAMED SAHBI · 15 / 21" />
    <div className="frame" style={{ paddingTop: 140 }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between' }}>
        <h2 className="display-black reveal reveal-1" style={{ fontSize: 96, margin: 0, whiteSpace: 'pre-line' }}>{c.title}</h2>
        <p className="reveal reveal-2" style={{ fontSize: 18, color: 'var(--muted-on-dark)', maxWidth: 360, margin: 0, fontFamily: 'var(--mono)' }}>{c.sub}</p>
      </div>
      <div className="stack-grid reveal reveal-3">
        {c.groups.map((g, i) => (
          <div className="stack-col" key={i}>
            <h4>{g.name}</h4>
            <ul>
              {g.items.map((it, j) => <li key={j}>{it}</li>)}
            </ul>
          </div>
        ))}
      </div>
    </div>
    <PageBottom left={cover.web} right="P. 15 / 21" />
  </section>
);

/* ============================================================
   Lightbox — fullscreen image viewer with click-to-zoom
   ============================================================ */
const Lightbox = ({ src, onClose }) => {
  const [zoomed, setZoomed] = useState(false);
  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.body.classList.add('lb-open');
    window.addEventListener('keydown', onKey);
    return () => {
      document.body.classList.remove('lb-open');
      window.removeEventListener('keydown', onKey);
    };
  }, [onClose]);
  return (
    <div className="lb-overlay" onClick={onClose} role="dialog" aria-modal="true">
      <button className="lb-close" onClick={onClose} aria-label="Close">×</button>
      <img
        className={`lb-img ${zoomed ? 'zoomed' : ''}`}
        src={src}
        alt=""
        onClick={(e) => { e.stopPropagation(); setZoomed((z) => !z); }}
      />
      <div className="lb-hint">Click image to zoom · ESC or click outside to close</div>
    </div>
  );
};

/* Export */
Object.assign(window, {
  Logo, PageTop, PageBottom, Placeholder, CountUp, Lightbox,
  SlideCover, SlideWho, SlideWhat, SlideHow, SlideDivider,
  CaseHero, CaseDetail, SlideMore, SlideStack,
});
