/* global React, ReactDOM, Problem, PromiseSection, Pillars, Performance, Trust, Story, Quiz, Calculator, Privacy, FAQ */
const { useState, useEffect, useRef, useMemo } = React;

// ============================================================
// i18n
// ============================================================
const COPY = {
  fr: {
    nav: { features: "Fonctionnalités", story: "Histoire", quiz: "Ton rêve", faq: "FAQ", contact: "Contact" },
    hero: {
      badge: "Disponible sur iOS · iPhone · Apple Watch",
      title1: "Pour ceux qui ont",
      title2: "un rêve à financer.",
      sub: "L'app iOS qui te montre, jour après jour, à quelle distance tu es de ce que tu veux vraiment.\nPas de pub. Pas de connexion bancaire. Pas de revente de données.",
      cta: "Télécharger sur l'App Store",
      cta2: "Voir comment ça marche",
      metric1: "7 jours gratuits",
      metric2: "Aucun engagement · Annulation en 1 tap",
    },
    screens: {
      eyebrow: "Dans l'app",
      title: "Chaque écran résout un vrai problème.",
      sub: "Des outils pensés pour transformer ton rapport à l'argent, un geste à la fois.",
      features: [
        {
          tag: "Vue d'ensemble",
          title: "Toute ta finance, en un coup d'œil.",
          desc: "Score de santé, budget quotidien restant, et répartition de tes revenus — tout est là dès l'ouverture de l'app. Aucun menu à explorer, aucune donnée à chercher.",
          bullets: ["Score /100 en temps réel", "Budget jour par jour", "Répartition automatique"],
          img: "dashboard",
        },
        {
          tag: "Projections intelligentes",
          title: "Vois ton futur financier.",
          desc: "Trajectoire 3, 6 et 12 mois calculée sur tes données réelles. L'app détecte tes crédits qui se terminent et intègre automatiquement les libérations à ton épargne.",
          bullets: ["Projection basée sur l'historique réel", "Détection auto des libérations", "Gain de +2 713€ sur 12 mois"],
          img: "trajectory",
        },
        {
          tag: "Répartition des revenus",
          title: "Où va vraiment ton argent ?",
          desc: "Un donut clair sépare engagements, épargne, vie courante et disponible. L'app alerte quand tes engagements dépassent 50% et suggère comment reprendre la main.",
          bullets: ["4 catégories claires", "Alertes automatiques à 50%", "Conseils contextuels"],
          img: "repartition",
        },
      ],
    },
    contact: {
      eyebrow: "Contact",
      title: "Une question ? Un retour ?",
      sub: "Nous lisons chaque message. Réponse sous 48 heures.",
      email: "Email",
      form: { name: "Ton nom", email: "Ton email", message: "Ton message", send: "Envoyer", sent: "Message envoyé. Merci !" },
    },
    footer: { rights: "Tous droits réservés.", legal: "Mentions légales", privacy: "Confidentialité", support: "Support", tagline: "Finance les rêves qui comptent." },
  },
  en: {
    nav: { features: "Features", story: "Story", quiz: "Your dream", faq: "FAQ", contact: "Contact" },
    hero: {
      badge: "Available on iOS · iPhone · Apple Watch",
      title1: "For those who have",
      title2: "a dream to fund.",
      sub: "The iOS app that shows you, day after day, how close you are to what you actually want.\nNo ads. No bank connection. No data reselling.",
      cta: "Download on the App Store",
      cta2: "See how it works",
      metric1: "7 days free",
      metric2: "No commitment · 1-tap cancel",
    },
    screens: {
      eyebrow: "Inside the app",
      title: "Every screen solves a real problem.",
      sub: "Tools designed to transform your relationship with money, one tap at a time.",
      features: [
        {
          tag: "Overview",
          title: "Your whole finances at a glance.",
          desc: "Health score, daily budget left, and income breakdown — all there the moment you open the app. No menus to dig through, no data to hunt.",
          bullets: ["Real-time /100 score", "Day-by-day budget", "Automatic breakdown"],
          img: "dashboard",
        },
        {
          tag: "Smart projections",
          title: "See your financial future.",
          desc: "3, 6 and 12 month trajectory computed from your real data. The app detects credits ending and automatically rolls those releases into your savings.",
          bullets: ["Based on real history", "Auto-detects releases", "+€2,713 gain over 12 months"],
          img: "trajectory",
        },
        {
          tag: "Income breakdown",
          title: "Where does your money actually go?",
          desc: "A clear donut splits commitments, savings, daily life and available. The app warns when commitments exceed 50% and suggests how to take back control.",
          bullets: ["4 clear categories", "Auto alerts at 50%", "Contextual advice"],
          img: "repartition",
        },
      ],
    },
    contact: {
      eyebrow: "Contact",
      title: "A question? Feedback?",
      sub: "We read every message. Reply within 48 hours.",
      email: "Email",
      form: { name: "Your name", email: "Your email", message: "Your message", send: "Send", sent: "Message sent. Thanks!" },
    },
    footer: { rights: "All rights reserved.", legal: "Legal", privacy: "Privacy", support: "Support", tagline: "Fund the dreams that matter." },
  },
};

// ============================================================
// Hooks
// ============================================================
function useInView(options = {}) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const io = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) setInView(true); },
      { threshold: 0.15, ...options }
    );
    io.observe(ref.current);
    return () => io.disconnect();
  }, []);
  return [ref, inView];
}

function useScrollY() {
  const [y, setY] = useState(0);
  useEffect(() => {
    const onScroll = () => setY(window.scrollY);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return y;
}

// ============================================================
// Reveal wrapper
// ============================================================
function Reveal({ children, delay = 0, as = "div", className = "", ...rest }) {
  const [ref, inView] = useInView();
  const Comp = as;
  return (
    <Comp
      ref={ref}
      className={`reveal ${inView ? "in" : ""} ${className}`}
      style={{ transitionDelay: `${delay}ms` }}
      {...rest}
    >
      {children}
    </Comp>
  );
}

// Expose Reveal for sections.jsx
window.Reveal = Reveal;

// ============================================================
// Nav
// ============================================================
function Nav({ lang, setLang, theme, setTheme, scrolled }) {
  const t = COPY[lang];
  return (
    <nav className={`nav ${scrolled ? "scrolled" : ""}`}>
      <div className="nav-inner">
        <a href="#top" className="logo">
          <span className="logo-mark">
            <svg viewBox="0 0 24 24" width="22" height="22">
              <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" strokeWidth="1.5" />
              <circle cx="12" cy="12" r="6" fill="none" stroke="currentColor" strokeWidth="1.5" />
              <circle cx="12" cy="12" r="2" fill="currentColor" />
            </svg>
          </span>
          <span className="logo-wd">TargetSaver</span>
        </a>
        <div className="nav-links">
          <a href="#screens">{t.nav.features}</a>
          <a href="#story">{t.nav.story}</a>
          <a href="#quiz">{t.nav.quiz}</a>
          <a href="#faq">{t.nav.faq}</a>
        </div>
        <div className="nav-tools">
          <button className="toggle-pair" onClick={() => setLang(lang === "fr" ? "en" : "fr")} aria-label="Language">
            <span className={lang === "fr" ? "on" : ""}>FR</span>
            <span className={lang === "en" ? "on" : ""}>EN</span>
          </button>
          <button className="theme-btn" onClick={() => setTheme(theme === "dark" ? "light" : "dark")} aria-label="Theme">
            {theme === "dark" ? (
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8Z"/></svg>
            ) : (
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>
            )}
          </button>
          <a href="#contact" className="nav-cta">{lang === "fr" ? "Télécharger" : "Download"}</a>
        </div>
      </div>
    </nav>
  );
}

// ============================================================
// Hero
// ============================================================
function Hero({ lang, tick, theme }) {
  const t = COPY[lang].hero;
  const scrollY = useScrollY();
  return (
    <section className="hero" id="top">
      <div className="grid-bg" aria-hidden="true" />
      <div className="glow glow-a" aria-hidden="true" />
      <div className="hero-inner">
        <div className="hero-copy">
          <Reveal className="hero-badge">
            <span className="dot" />{t.badge}
          </Reveal>
          <Reveal as="h1" delay={80} className="hero-title">
            <span className="l1">{t.title1}</span>
            <span className="l2">{t.title2}</span>
          </Reveal>
          <Reveal as="p" delay={180} className="hero-sub">
            {t.sub.split("\n").map((line, i) => (
              <React.Fragment key={i}>
                {i > 0 && <br />}
                {line}
              </React.Fragment>
            ))}
          </Reveal>
          <Reveal delay={260} className="hero-ctas">
            <a href="#contact" className="btn btn-primary" data-magnetic>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M17.6 13.6c0-2.3 1.9-3.4 2-3.5-1.1-1.6-2.8-1.8-3.4-1.8-1.5-.1-2.8.9-3.6.9-.7 0-1.9-.8-3.1-.8-1.6 0-3.1.9-3.9 2.4-1.7 2.9-.4 7.2 1.2 9.5.8 1.1 1.7 2.4 2.9 2.4 1.2 0 1.6-.7 3.1-.7 1.4 0 1.9.7 3.1.7 1.3 0 2.1-1.1 2.9-2.3.9-1.3 1.3-2.6 1.3-2.7-.1 0-2.5-1-2.5-3.8ZM15.4 6.1c.7-.8 1.1-2 1-3.1-1 .1-2.2.7-2.9 1.5-.6.7-1.2 1.9-1 3 1.1 0 2.3-.6 2.9-1.4Z"/></svg>
              {t.cta}
            </a>
            <a href="#screens" className="btn btn-ghost" data-magnetic>
              {t.cta2}
              <svg className="cta-arrow" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="13 6 19 12 13 18"/></svg>
            </a>
          </Reveal>
          <Reveal delay={360} className="hero-metric">
            <div className="metric-num">{t.metric1}</div>
            <div className="metric-sub">{t.metric2}</div>
          </Reveal>
        </div>

        <div className="hero-phone" style={{ transform: `translateY(${-scrollY * 0.04}px)` }}>
          <div className="phone-wrap">
            <div className="hero-phone-bezel">
              <img src={`screens/dashboard-${theme}.png`} alt="TargetSaver dashboard" className="hero-phone-img" />
            </div>
          </div>
          <div className="phone-halo" aria-hidden="true" />
          <div className="float-chip chip-a">
            <div className="chip-dot" />
            <div>
              <div className="chip-t">{lang === "fr" ? "20 jours en or" : "20 golden days"}</div>
              <div className="chip-s">{lang === "fr" ? "ce mois-ci" : "this month"}</div>
            </div>
          </div>
          <div className="float-chip chip-b">
            <div className="chip-spark" style={{ color: "#f5b447" }}>✦</div>
            <div>
              <div className="chip-t">+2 713 €</div>
              <div className="chip-s">{lang === "fr" ? "gain projeté 12 mois" : "12-mo projected gain"}</div>
            </div>
          </div>
        </div>
      </div>
      <div className="hero-ticker">
        <div className="ticker-track">
          {Array(3).fill(0).map((_, i) => (
            <div key={i} className="ticker-row">
              <span>● PRIVACY-FIRST</span>
              <span>● ZÉRO PUB · ZÉRO TRACKER</span>
              <span>● PAS DE BANQUE CONNECTÉE</span>
              <span>● iOS 18+ · APPLE WATCH</span>
              <span>● SIRI · 14 COMMANDES</span>
              <span>● CHIFFREMENT AES-256</span>
              <span>● RGPD · SERVEUR UE</span>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ============================================================
// Screenshots — feature rows with real app screenshots
// ============================================================
function Screens({ lang, theme }) {
  const t = COPY[lang].screens;
  return (
    <section className="screens" id="screens">
      <div className="section-head">
        <Reveal as="div" className="eyebrow">{t.eyebrow}</Reveal>
        <Reveal as="h2" delay={80} className="section-title">{t.title}</Reveal>
        <Reveal as="p" delay={160} className="section-sub">{t.sub}</Reveal>
      </div>
      <div className="features-stack">
        {t.features.map((f, i) => (
          <Reveal key={i} delay={i * 60} className={`feature-row ${i % 2 ? "reverse" : ""}`}>
            <div className="feature-copy">
              <div className="feature-tag">{f.tag}</div>
              <h3 className="feature-title">{f.title}</h3>
              <p className="feature-desc">{f.desc}</p>
              <ul className="feature-bullets">
                {f.bullets.map((b, j) => (
                  <li key={j}><span className="bullet-dot" />{b}</li>
                ))}
              </ul>
            </div>
            <div className="feature-visual">
              <div className="feature-phone">
                <img
                  src={`screens/${f.img}-${theme}.png`}
                  alt={f.title}
                  className="feature-img"
                />
              </div>
              <div className="feature-halo" aria-hidden="true" />
            </div>
          </Reveal>
        ))}
      </div>
    </section>
  );
}

// ============================================================
// Contact
// ============================================================
function Contact({ lang }) {
  const t = COPY[lang].contact;
  const [sent, setSent] = useState(false);
  const [form, setForm] = useState({ name: "", email: "", message: "" });

  const submit = (e) => {
    e.preventDefault();
    const data = new URLSearchParams();
    data.append("form-name", "contact");
    data.append("name", form.name);
    data.append("email", form.email);
    data.append("message", form.message);
    fetch("/", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: data.toString(),
    }).catch(() => { /* graceful: still show "sent" UI */ });
    setSent(true);
    setTimeout(() => { setSent(false); setForm({ name: "", email: "", message: "" }); }, 3200);
  };

  return (
    <section className="contact" id="contact">
      <div className="contact-inner">
        <div className="contact-left">
          <Reveal className="eyebrow eyebrow--accent">{t.eyebrow}</Reveal>
          <Reveal as="h2" delay={80} className="section-title">{t.title}</Reveal>
          <Reveal as="p" delay={160} className="section-sub">{t.sub}</Reveal>
          <Reveal delay={240} className="contact-email">
            <div className="ce-label">{t.email}</div>
            <a href="mailto:hello@targetsaver.app" className="ce-value">hello@targetsaver.app</a>
          </Reveal>
          <Reveal delay={320} className="contact-social">
            <a href="#" className="soc">Twitter</a>
            <a href="#" className="soc">Mastodon</a>
            <a href="#" className="soc">LinkedIn</a>
          </Reveal>
        </div>
        <Reveal delay={120} className="contact-right">
          <form
            name="contact"
            method="POST"
            data-netlify="true"
            netlify-honeypot="bot-field"
            onSubmit={submit}
            className={`contact-form ${sent ? "sent" : ""}`}
          >
            <input type="hidden" name="form-name" value="contact" />
            <p className="hp-field" style={{ display: "none" }}>
              <label>Don't fill: <input name="bot-field" /></label>
            </p>
            <label>
              <span>{t.form.name}</span>
              <input required name="name" value={form.name} onChange={e => setForm({ ...form, name: e.target.value })} />
            </label>
            <label>
              <span>{t.form.email}</span>
              <input required type="email" name="email" value={form.email} onChange={e => setForm({ ...form, email: e.target.value })} />
            </label>
            <label>
              <span>{t.form.message}</span>
              <textarea required name="message" rows="4" value={form.message} onChange={e => setForm({ ...form, message: e.target.value })} />
            </label>
            <button type="submit" className="btn btn-primary form-send" data-magnetic>
              {sent ? t.form.sent : t.form.send}
              {!sent && <span className="arrow">→</span>}
            </button>
          </form>
        </Reveal>
      </div>
    </section>
  );
}

// ============================================================
// Footer
// ============================================================
function Footer({ lang }) {
  const t = COPY[lang].footer;
  return (
    <footer className="footer">
      <div className="footer-inner">
        <div className="footer-brand">
          <div className="footer-brand-top">
            <span className="logo-mark">
              <svg viewBox="0 0 24 24" width="20" height="20">
                <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" strokeWidth="1.5" />
                <circle cx="12" cy="12" r="6" fill="none" stroke="currentColor" strokeWidth="1.5" />
                <circle cx="12" cy="12" r="2" fill="currentColor" />
              </svg>
            </span>
            <span>TargetSaver</span>
          </div>
          <div className="footer-tagline">{t.tagline}</div>
        </div>
        <div className="footer-copy">© 2026 TargetSaver. {t.rights}</div>
        <div className="footer-links">
          <a href="legal.html">{t.legal}</a>
          <a href="privacy.html">{t.privacy}</a>
          <a href="support.html">{t.support}</a>
        </div>
      </div>
    </footer>
  );
}

// ============================================================
// Root
// ============================================================
function App() {
  const [lang, setLang] = useState("fr");
  const [theme, setTheme] = useState("dark");
  const [tick, setTick] = useState(0);
  const scrollY = useScrollY();
  const scrolled = scrollY > 12;

  useEffect(() => {
    document.documentElement.setAttribute("data-theme", theme);
  }, [theme]);

  useEffect(() => {
    let raf;
    const loop = () => { setTick(t => t + 1); raf = requestAnimationFrame(loop); };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, []);

  return (
    <div className="site">
      <LoadingCinematic />
      <Nav lang={lang} setLang={setLang} theme={theme} setTheme={setTheme} scrolled={scrolled} />
      <Hero lang={lang} tick={tick} theme={theme} />
      <Problem lang={lang} />
      <PromiseSection lang={lang} />
      <Screens lang={lang} theme={theme} />
      <Pillars lang={lang} />
      <Performance lang={lang} />
      <Story lang={lang} />
      <Quiz lang={lang} />
      <Calculator lang={lang} />
      <Privacy lang={lang} />
      <Trust lang={lang} />
      <FAQ lang={lang} />
      <Contact lang={lang} />
      <Footer lang={lang} />
    </div>
  );
}

window.App = App;
