// Main app sections
const { useState, useEffect, useRef } = React;

// Real project photography — the three projects with delivered photos
const PROJECT_PHOTOS = {
  "tour-stanley": "photos/project-tower.jpg",
  "chum-pavillon-d": "photos/project-mixeduse.jpg",
  "verdun-quartier": "photos/project-homes.jpg",
};

// Flat construction mark — ascending slabs, top one gold
function LogoMark({ size = 40, color = "currentColor", accent = "#c9a23b", className, style }) {
  return (
    <svg viewBox="0 0 48 48" width={size} height={size} className={className} style={style} aria-hidden="true">
      <rect x="4" y="36" width="26" height="7" fill={color}></rect>
      <rect x="11" y="25" width="26" height="7" fill={color}></rect>
      <rect x="18" y="14" width="26" height="7" fill={accent}></rect>
    </svg>
  );
}

function Nav({ lang, setLang, t }) {
  const [scrolled, setScrolled] = useState(false);
  const [open, setOpen] = useState(false);
  const close = () => setOpen(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 8);
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  useEffect(() => {
    document.body.style.overflow = open ? "hidden" : "";
    return () => { document.body.style.overflow = ""; };
  }, [open]);
  return (
    <nav className={"nav" + (scrolled ? " scrolled" : "")}>
      <div className="container nav-inner">
        <a href="#top" className="logo">
          <LogoMark size={34} color="var(--ink)" />
          <span className="logo-word">Rosedale</span>
        </a>
        <div className="nav-links">
          <a href="#projects">{t.nav.projects}</a>
          <a href="#services">{t.nav.services}</a>
          <a href="#approach">{t.nav.approach}</a>
          <a href="#about">{t.nav.about}</a>
          <a href="#contact">{t.nav.contact}</a>
        </div>
        <div className="nav-right">
          <div className="lang-toggle" role="group" aria-label="Language">
            <button className={lang === "fr" ? "on" : ""} onClick={() => setLang("fr")}>FR</button>
            <button className={lang === "en" ? "on" : ""} onClick={() => setLang("en")}>EN</button>
          </div>
          <a href="#contact" className="btn nav-cta" style={{padding: "10px 16px", fontSize: 13}}>
            {t.nav.rfq}
            <span className="arrow">→</span>
          </a>
          <button className={"menu-btn" + (open ? " open" : "")} aria-label="Menu" aria-expanded={open} onClick={() => setOpen(o => !o)}>
            <span></span><span></span>
          </button>
        </div>
      </div>
      <div className={"nav-menu" + (open ? " open" : "")}>
        <a href="#projects" onClick={close}>{t.nav.projects}</a>
        <a href="#services" onClick={close}>{t.nav.services}</a>
        <a href="#approach" onClick={close}>{t.nav.approach}</a>
        <a href="#about" onClick={close}>{t.nav.about}</a>
        <a href="#contact" onClick={close}>{t.nav.contact}</a>
        <a href="#contact" className="btn menu-cta" onClick={close}>
          {t.nav.rfq}
          <span className="arrow">→</span>
        </a>
      </div>
    </nav>
  );
}

function Hero({ t }) {
  return (
    <section id="top" className="hero">
      <LogoMark className="hero-cubes" color="var(--ink)" accent="var(--gold)" />
      <div className="container">
        <div className="hero-grid">
          <div>
            <span className="eyebrow">{t.hero.eyebrow}</span>
            <h1>
              {t.hero.title_1}<br/>
              <span className="it gold">{t.hero.title_2}</span>
            </h1>
            <p className="hero-body">{t.hero.body}</p>
            <div className="hero-ctas">
              <a href="#projects" className="btn">
                {t.hero.cta_primary}
                <span className="arrow">→</span>
              </a>
              <a href="#contact" className="btn ghost">
                {t.hero.cta_secondary}
              </a>
            </div>
          </div>
          <div>
            <div className="hero-visual">
              <span className="ph-label">[ FIG. 01 · TOUR STANLEY ]</span>
              <img src="photos/project-tower.jpg" alt="Tour Stanley — Montréal" />
              <div className="ph-caption">
                <span>TOUR STANLEY</span>
                <span>42F · MONTRÉAL</span>
              </div>
            </div>
            <div className="hero-meta" style={{marginTop: 16, paddingBottom: 0, borderBottom: 0}}>
              <span className="loc">45.5017°N 73.5673°W</span>
              <span className="loc">MTL · QC · CA</span>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function CountUp({ value }) {
  const m = /^([^0-9]*)(\d+)(.*)$/.exec(value);
  const ref = useRef(null);
  const [display, setDisplay] = useState(m ? m[1] + "0" + m[3] : value);

  useEffect(() => {
    if (!m) { setDisplay(value); return; }
    const target = parseInt(m[2], 10);
    const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced) { setDisplay(value); return; }
    const el = ref.current;
    let raf, timer, started = false;
    const start = () => {
      if (started) return;
      started = true;
      io.disconnect();
      window.removeEventListener("scroll", check);
      clearTimeout(fallback);
      const t0 = performance.now();
      const dur = 1200;
      // Safety: snap to final value if rAF stalls
      timer = setTimeout(() => setDisplay(value), dur + 400);
      const tick = (now) => {
        const p = Math.min(1, (now - t0) / dur);
        const eased = 1 - Math.pow(1 - p, 3);
        setDisplay(p >= 1 ? value : m[1] + Math.round(target * eased) + m[3]);
        if (p < 1) raf = requestAnimationFrame(tick);
      };
      raf = requestAnimationFrame(tick);
    };
    const io = new IntersectionObserver(([e]) => { if (e.isIntersecting) start(); }, { threshold: 0 });
    // Fallbacks: IO can starve — check on scroll, and snap after 3.5s regardless
    const check = () => {
      const r = el.getBoundingClientRect();
      if (r.top < window.innerHeight && r.bottom > 0) start();
    };
    const fallback = setTimeout(() => { if (!started) { started = true; io.disconnect(); window.removeEventListener("scroll", check); setDisplay(value); } }, 3500);
    io.observe(el);
    window.addEventListener("scroll", check, { passive: true });
    check();
    return () => {
      io.disconnect();
      cancelAnimationFrame(raf);
      clearTimeout(timer);
      clearTimeout(fallback);
      window.removeEventListener("scroll", check);
    };
  }, [value]);

  return <span ref={ref}>{display}</span>;
}

function Stats({ t }) {
  return (
    <section className="stats-wrap">
      <div className="stats">
        {t.stats.map((s, i) => (
          <div key={i} className="stat">
            <div className="n serif"><CountUp value={s.n} /></div>
            <div className="label">{s.label}</div>
          </div>
        ))}
      </div>
    </section>
  );
}

function Projects({ t, lang, onOpen }) {
  const filters = t.projects_section.filters;
  const [active, setActive] = useState(0);
  const enFilters = ["All", "Commercial", "Institutional", "Residential", "Retail"];

  const filtered = PROJECTS.filter(p => active === 0 || p.category === enFilters[active]);

  return (
    <section id="projects" className="projects">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <span className="eyebrow">{t.projects_section.eyebrow}</span>
            <h2>{t.projects_section.title}</h2>
          </div>
          <div className="sh-body">{t.projects_section.body}</div>
        </div>

        <div className="proj-filters">
          {filters.map((f, i) => (
            <button key={i} className={`chip ${active === i ? "on" : ""}`} onClick={() => setActive(i)}>
              {f}
            </button>
          ))}
        </div>

        <div className="proj-grid">
          {filtered.map((p, i) => {
            const catIdx = enFilters.indexOf(p.category);
            const localCat = filters[catIdx] || p.category;
            const photo = PROJECT_PHOTOS[p.id];
            return (
              <article key={p.id} className="proj-card">
                <div className="proj-media">
                  <span className="tag">{localCat} · {p.year}</span>
                  {photo
                    ? <img src={photo} alt={p.name[lang]} />
                    : <div className="photo-pending"><span>{t.projects_section.photo_pending}</span></div>}
                </div>
                <div className="proj-meta" onClick={() => onOpen(p)}>
                  <h3>{p.name[lang]}</h3>
                  <span className="sub">{p.year} · {p.location.split(",")[0]}</span>
                </div>
              </article>
            );
          })}
        </div>
      </div>
    </section>
  );
}

function Services({ t }) {
  return (
    <section id="services" className="services">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <span className="eyebrow">{t.services_section.eyebrow}</span>
            <h2>{t.services_section.title}</h2>
          </div>
          <div className="sh-body">{t.services_section.body}</div>
        </div>
        <div className="svc-grid reveal">
          {t.services_section.items.map((s, i) => (
            <div key={i} className="svc">
              <span className="num">{s.num}</span>
              <div>
                <h3>{s.title}</h3>
                <p>{s.body}</p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function Approach({ t }) {
  return (
    <section id="approach" className="approach">
      <div className="container">
        <div className="approach-grid reveal">
          <div>
            <span className="eyebrow">{t.approach_section.eyebrow}</span>
            <h2>{t.approach_section.title}</h2>
          </div>
          <div className="body">{t.approach_section.body}</div>

          <div className="pillars">
            {t.approach_section.pillars.map((p, i) => (
              <div key={i} className="pillar">
                <span className="num">0{i + 1}</span>
                <h4>{p.title}</h4>
                <p>{p.body}</p>
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

function About({ t }) {
  return (
    <section id="about" className="about">
      <div className="container">
        <div className="about-grid reveal">
          <div>
            <span className="eyebrow">{t.about_section.eyebrow}</span>
            <h2>{t.about_section.title}</h2>
            <div className="body">{t.about_section.body}</div>
            <div className="certs">
              {t.about_section.certifications.map((c, i) => (
                <span key={i} className="cert">{c}</span>
              ))}
            </div>
          </div>
          <div>
            <div className="leadership">
              {t.about_section.leadership.map((l, i) => (
                <div key={i} className="lead">
                  <span className="mono">0{i + 1}</span>
                  <span className="nm">{l.name}</span>
                  <span className="rl">{l.role}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function RFQ({ t }) {
  const f = t.rfq_section.fields;
  const [state, setState] = useState({
    name: "", company: "", email: "", phone: "",
    type: "", budget: "", timeline: "", message: "",
  });
  const [errors, setErrors] = useState({});
  const [status, setStatus] = useState("idle"); // idle | submitting | sent | failed

  const set = (k, v) => setState(s => ({ ...s, [k]: v }));

  const submit = async (e) => {
    e.preventDefault();
    const errs = {};
    if (!state.name.trim()) errs.name = t.rfq_section.error_required;
    if (!state.email.trim()) errs.email = t.rfq_section.error_required;
    else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(state.email)) errs.email = t.rfq_section.error_email;
    if (!state.type) errs.type = t.rfq_section.error_required;
    if (!state.message.trim()) errs.message = t.rfq_section.error_required;
    setErrors(errs);
    if (Object.keys(errs).length) return;
    setStatus("submitting");
    try {
      const res = await fetch("https://api.web3forms.com/submit", {
        method: "POST",
        headers: { "Content-Type": "application/json", Accept: "application/json" },
        body: JSON.stringify({
          access_key: "c02b7a98-9b9d-41d4-8291-c34e81dcddb6",
          subject: t.rfq_section.mail_subject,
          from_name: "Site web Rosedale",
          replyto: state.email,
          botcheck: "",
          name: state.name,
          company: state.company,
          email: state.email,
          phone: state.phone,
          project_type: state.type,
          budget: state.budget,
          timeline: state.timeline,
          message: state.message,
        }),
      });
      const data = await res.json();
      setStatus(data.success ? "sent" : "failed");
    } catch (err) {
      setStatus("failed");
    }
  };

  if (status === "sent") {
    return (
      <section id="contact" className="rfq">
        <div className="container">
          <div className="rfq-grid">
            <div>
              <span className="eyebrow">{t.rfq_section.eyebrow}</span>
              <h2>{t.rfq_section.title}</h2>
              <div className="body">{t.rfq_section.body}</div>
            </div>
            <div className="form-success">
              <span className="mono">✓ {t.rfq_section.eyebrow}</span>
              {t.rfq_section.success}
            </div>
          </div>
        </div>
      </section>
    );
  }

  return (
    <section id="contact" className="rfq">
      <div className="container">
        <div className="rfq-grid reveal">
          <div>
            <span className="eyebrow">{t.rfq_section.eyebrow}</span>
            <h2>{t.rfq_section.title}</h2>
            <div className="body">{t.rfq_section.body}</div>
          </div>

          <form className="form" onSubmit={submit} noValidate>
            <div className={`field ${errors.name ? "error" : ""}`}>
              <label>{f.name}</label>
              <input type="text" value={state.name} onChange={e => set("name", e.target.value)} placeholder="—" />
              {errors.name && <span className="err">{errors.name}</span>}
            </div>
            <div className="field left-pad">
              <label>{f.company}</label>
              <input type="text" value={state.company} onChange={e => set("company", e.target.value)} placeholder="—" />
            </div>

            <div className={`field ${errors.email ? "error" : ""}`}>
              <label>{f.email}</label>
              <input type="email" value={state.email} onChange={e => set("email", e.target.value)} placeholder="—" />
              {errors.email && <span className="err">{errors.email}</span>}
            </div>
            <div className="field left-pad">
              <label>{f.phone}</label>
              <input type="tel" value={state.phone} onChange={e => set("phone", e.target.value)} placeholder="—" />
            </div>

            <div className={`field ${errors.type ? "error" : ""}`}>
              <label>{f.type}</label>
              <select value={state.type} onChange={e => set("type", e.target.value)}>
                <option value="">—</option>
                {t.rfq_section.type_options.map((o, i) => <option key={i} value={o}>{o}</option>)}
              </select>
              {errors.type && <span className="err">{errors.type}</span>}
            </div>
            <div className="field left-pad">
              <label>{f.budget}</label>
              <select value={state.budget} onChange={e => set("budget", e.target.value)}>
                <option value="">—</option>
                {t.rfq_section.budget_options.map((o, i) => <option key={i} value={o}>{o}</option>)}
              </select>
            </div>

            <div className="field full">
              <label>{f.timeline}</label>
              <select value={state.timeline} onChange={e => set("timeline", e.target.value)}>
                <option value="">—</option>
                {t.rfq_section.timeline_options.map((o, i) => <option key={i} value={o}>{o}</option>)}
              </select>
            </div>

            <div className={`field full ${errors.message ? "error" : ""}`}>
              <label>{f.message}</label>
              <textarea value={state.message} onChange={e => set("message", e.target.value)} placeholder="—" />
              {errors.message && <span className="err">{errors.message}</span>}
            </div>

            <div className="form-actions">
              {status === "failed" && <span className="err">{t.rfq_section.error_send}</span>}
              <span className="form-note">↳ {t.rfq_section.note}</span>
              <button type="submit" className="btn accent" disabled={status === "submitting"}>
                {status === "submitting" ? t.rfq_section.submitting : t.rfq_section.submit}
                <span className="arrow">→</span>
              </button>
            </div>
          </form>
        </div>
      </div>
    </section>
  );
}

function Footer({ t }) {
  return (
    <footer className="footer">
      <div className="container">
        <div className="footer-grid">
          <div>
            <div className="footer-logo">
              <LogoMark size={44} color="#eeeae1" />
              <span className="footer-word">Rosedale</span>
            </div>
            <h3 className="serif">
              {t.footer.tagline_1} <span className="it">Montréal</span><br/>
              {t.footer.tagline_2}
            </h3>
          </div>
          <div>
            <div className="col-label">Studio</div>
            <div className="addr">
              {t.footer.address_1}<br/>
              {t.footer.address_2}{t.footer.address_3 ? <br/> : null}{t.footer.address_3}
            </div>
          </div>
          <div>
            <div className="col-label">Contact</div>
            <div className="flinks">
              <a href={`tel:${t.footer.phone}`}>{t.footer.phone}</a>
              <a href={`mailto:${t.footer.email}`}>{t.footer.email}</a>
            </div>
          </div>
          <div>
            <div className="col-label">Navigate</div>
            <div className="flinks">
              <a href="#projects">{t.nav.projects}</a>
              <a href="#services">{t.nav.services}</a>
              <a href="#about">{t.nav.about}</a>
              <a href="#contact">{t.nav.contact}</a>
            </div>
          </div>
        </div>
        <div className="footer-bottom">
          <span>{t.footer.rights}</span>
          <span>{t.footer.rbq}</span>
          <a className="bug-link" href="report-a-bug.html">{t.footer.bug}</a>
        </div>
      </div>
    </footer>
  );
}

function CaseStudyModal({ project, lang, t, onClose }) {
  useEffect(() => {
    const onKey = e => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [onClose]);

  if (!project) return null;
  const ef = ["All", "Commercial", "Institutional", "Residential", "Retail"];
  const idx = ef.indexOf(project.category);
  const catLocal = t.projects_section.filters[idx];
  const photo = PROJECT_PHOTOS[project.id];

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose} aria-label="Close">×</button>
        <div className="modal-hero">
          {photo
            ? <img src={photo} alt={project.name[lang]} />
            : <div className="photo-pending"><span>{t.projects_section.photo_pending}</span></div>}
        </div>
        <div className="modal-body">
          <span className="eyebrow">{catLocal} · {project.year}</span>
          <h2>{project.name[lang]}</h2>
          <p>{project.blurb[lang]}</p>
          <div className="modal-facts">
            <div className="f">
              <div className="k">{lang === "fr" ? "Client" : "Client"}</div>
              <div className="v">{project.client}</div>
            </div>
            <div className="f">
              <div className="k">{lang === "fr" ? "Emplacement" : "Location"}</div>
              <div className="v">{project.location}</div>
            </div>
            <div className="f">
              <div className="k">{lang === "fr" ? "Superficie" : "Scope"}</div>
              <div className="v">{project.size}</div>
            </div>
            <div className="f">
              <div className="k">{lang === "fr" ? "Livré" : "Delivered"}</div>
              <div className="v">{project.year}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// Scroll reveals — adds .in to .reveal elements as they enter the viewport
function initReveal() {
  const all = () => document.querySelectorAll(".reveal:not(.in)");
  if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
    all().forEach(el => el.classList.add("in"));
    return () => {};
  }
  const io = new IntersectionObserver((entries) => {
    entries.forEach(e => {
      if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); }
    });
  }, { threshold: 0 });
  all().forEach(el => io.observe(el));

  // Fallbacks: IO callbacks can starve after anchor jumps — reveal anything
  // already in view on scroll/resize, and force-reveal everything after 4s.
  const sweep = () => {
    all().forEach(el => {
      const r = el.getBoundingClientRect();
      if (r.top < window.innerHeight && r.bottom > 0) el.classList.add("in");
    });
  };
  window.addEventListener("scroll", sweep, { passive: true });
  window.addEventListener("resize", sweep);
  const timer = setTimeout(() => all().forEach(el => el.classList.add("in")), 4000);
  sweep();
  return () => {
    io.disconnect();
    clearTimeout(timer);
    window.removeEventListener("scroll", sweep);
    window.removeEventListener("resize", sweep);
  };
}

Object.assign(window, {
  Nav, Hero, Stats, Projects, Services, Approach, About, RFQ, Footer, CaseStudyModal, initReveal, LogoMark,
});
