/* Secciones del portafolio */
const { useState: useStateS, useRef: useRefS, useEffect: useEffectS } = React;

/* Descarga el CV como PDF con nombre/extensión forzados.
   Se descarga vía blob para garantizar que el archivo llegue como .pdf válido
   sin importar el content-type que devuelva el servidor (evita que se guarde como .txt). */
const CV_FILENAME = "Jhostter-Valdez-CV.pdf";
async function downloadCV(e) {
  if (e) e.preventDefault();
  const url = window.CONTENT.contact.cv;
  try {
    const res = await fetch(url);
    if (!res.ok) throw new Error("fetch-" + res.status);
    const buf = await res.arrayBuffer();
    const blob = new Blob([buf], { type: "application/pdf" });
    const objUrl = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = objUrl;
    a.download = CV_FILENAME;
    document.body.appendChild(a);
    a.click();
    a.remove();
    setTimeout(() => URL.revokeObjectURL(objUrl), 4000);
  } catch (err) {
    // Fallback: abrir el PDF en una pestaña nueva si el fetch falla
    window.open(url, "_blank", "noopener");
  }
}

/* Hook: reveal on scroll */
function useReveal() {
  useEffectS(() => {
    const els = [...document.querySelectorAll(".reveal")];
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {if (e.isIntersecting) {e.target.classList.add("in");io.unobserve(e.target);}});
    }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
    els.forEach((el) => io.observe(el));

    // Fallback: in a non-scrolling context (e.g. auto-sized iframe embed) the
    // observer never fires for below-fold elements, leaving them invisible.
    // Detect that case and reveal everything so content is never lost.
    const t = setTimeout(() => {
      const before = window.scrollY;
      window.scrollTo({ top: before + 24, left: 0, behavior: "instant" });
      const moved = window.scrollY !== before;
      window.scrollTo({ top: before, left: 0, behavior: "instant" });
      const scrollable = document.documentElement.scrollHeight > window.innerHeight + 4;
      if (scrollable && !moved) els.forEach((el) => el.classList.add("in"));
    }, 500);
    return () => {io.disconnect();clearTimeout(t);};
  }, []);
}

/* Rotating role text */
function RoleRotator({ roles }) {
  const [i, setI] = useStateS(0);
  const [show, setShow] = useStateS(true);
  useEffectS(() => {
    const id = setInterval(() => {
      setShow(false);
      setTimeout(() => {setI((p) => (p + 1) % roles.length);setShow(true);}, 350);
    }, 2600);
    return () => clearInterval(id);
  }, [roles]);
  return (
    <span className="hero-role-rot" style={{ opacity: show ? 1 : 0, transform: show ? "translateY(0)" : "translateY(8px)", transition: "all .35s cubic-bezier(.22,1,.36,1)" }}>
      {roles[i]}
    </span>);

}

/* Animated counter */
function Counter({ value, suffix }) {
  const [n, setN] = useStateS(0);
  const ref = useRefS(null);
  const target = parseInt(value, 10) || 0;
  useEffectS(() => {
    let done = false;
    const io = new IntersectionObserver((entries) => {
      if (entries[0].isIntersecting && !done) {
        done = true;
        const dur = 1300;const start = performance.now();
        const tick = (now) => {
          const p = Math.min((now - start) / dur, 1);
          const eased = 1 - Math.pow(1 - p, 3);
          setN(Math.round(eased * target));
          if (p < 1) requestAnimationFrame(tick);
        };
        requestAnimationFrame(tick);
      }
    }, { threshold: 0.5 });
    if (ref.current) io.observe(ref.current);
    return () => io.disconnect();
  }, [target]);
  return <span className="num" ref={ref}>{n}{suffix}</span>;
}

/* Nav */
function Nav({ t, lang, setLang }) {
  const [scrolled, setScrolled] = useStateS(false);
  const [menuOpen, setMenuOpen] = useStateS(false);
  useEffectS(() => {
    const onScroll = () => setScrolled(window.scrollY > 30);
    window.addEventListener("scroll", onScroll);onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  // Lock body scroll while the mobile menu is open
  useEffectS(() => {
    document.body.style.overflow = menuOpen ? "hidden" : "";
    return () => { document.body.style.overflow = ""; };
  }, [menuOpen]);
  const N = t.nav;
  const links = [
    ["#about", N.about], ["#experience", N.experience], ["#skills", N.skills],
    ["#projects", N.projects], ["#education", N.education], ["#contact", N.contact]
  ];
  return (
    <nav className={`nav ${scrolled || menuOpen ? "scrolled" : ""}`}>
      <div className="nav-inner" data-comment-anchor="b4473f47c8-div-83-7">
        <a href="#top" className="brand" style={{ textDecoration: "none", color: "inherit" }} onClick={() => setMenuOpen(false)}>
          <span className="brand-mark">JV</span>
          <span>Jhostter Valdez<small>QA · SDET · DevOps</small></span>
        </a>
        <div className="nav-links">
          {links.map(([href, label]) => <a key={href} href={href}>{label}</a>)}
        </div>
        <div className="nav-tools">
          <div className="lang-toggle" onClick={() => setLang(lang === "es" ? "en" : "es")} role="button" aria-label="Toggle language">
            <span className={lang === "es" ? "on" : ""}>ES</span>
            <span className={lang === "en" ? "on" : ""}>EN</span>
          </div>
          <a className="btn btn-primary btn-sm nav-cv" href={window.CONTENT.contact.cv} download={CV_FILENAME} onClick={downloadCV}>
            <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
            {N.cv}
          </a>
          <button className={`nav-burger ${menuOpen ? "open" : ""}`} onClick={() => setMenuOpen(o => !o)} aria-label="Menú" aria-expanded={menuOpen}>
            <span></span><span></span><span></span>
          </button>
        </div>
      </div>
      <div className={`nav-mobile ${menuOpen ? "open" : ""}`}>
        <div className="nav-mobile-links">
          {links.map(([href, label]) => (
            <a key={href} href={href} onClick={() => setMenuOpen(false)}>{label}</a>
          ))}
        </div>
        <a className="btn btn-primary nav-mobile-cv" href={window.CONTENT.contact.cv} download={CV_FILENAME} onClick={(e) => { downloadCV(e); setMenuOpen(false); }}>
          <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
          {N.cv}
        </a>
      </div>
    </nav>);

}

/* Hero */
function Hero({ t, lang }) {
  const H = t.hero;
  return (
    <header className="hero wrap" id="top">
      <div className="hero-grid">
        <div className="hero-left">
          <div className="hero-greet reveal in">{H.greeting}</div>
          <h1 className="hero-name reveal in">{H.name}</h1>
          <div className="hero-roles reveal in"><RoleRotator roles={H.roles} /></div>
          <p className="hero-tagline reveal in">{H.tagline}</p>
          <div className="hero-meta reveal in">
            <span><i className="dot"></i>{H.location}</span>
            <span><i className="dot live"></i>{H.availability}</span>
          </div>
          <div className="hero-cta reveal in">
            <a href="#contact" className="btn btn-primary">{H.ctaChat}
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
            </a>
            <a href="#projects" className="btn btn-ghost">{H.ctaProjects}</a>
          </div>
        </div>
        <div className="hero-right reveal in" data-d="1">
          <div className="avatar-stack">
            <AIChat lang={lang} t={t} />
          </div>
        </div>
      </div>
    </header>);

}

/* Stats */
function Stats({ t }) {
  return (
    <section className="wrap" style={{ paddingTop: 0 }}>
      <div className="stats">
        {t.stats.map((s, i) =>
        <div key={i} className="stat glass reveal" data-d={String(i % 4)}>
            <Counter value={s.value} suffix={s.suffix} />
            <div className="lbl">{s.label}</div>
          </div>
        )}
      </div>
    </section>);

}

/* About */
function About({ t }) {
  const A = t.about;
  return (
    <section id="about" className="wrap">
      <div className="about-grid">
        <div className="reveal">
          <div className="kicker">{A.kicker}</div>
          <h2 className="sec-title">{A.title}</h2>
          <p className="about-body">{A.body}</p>
          <div className="about-pills">
            {A.pills.map((p, i) => <span key={i} className="pill">{p}</span>)}
          </div>
        </div>
        <div className="about-visual glass reveal" data-d="1" data-comment-anchor="8c1f814e0d-div-161-9">
          <img src={window.CONTENT.contact.photo} alt="Jhostter Valdez" />
        </div>
      </div>
    </section>);

}

/* Experience */
function Experience({ t, lang }) {
  const E = t.experience;
  return (
    <section id="experience" className="wrap">
      <div className="sec-head reveal">
        <div className="kicker">{E.kicker}</div>
        <h2 className="sec-title">{E.title}</h2>
      </div>
      <div className="timeline">
        {window.CONTENT.experience.map((x, i) =>
        <div key={i} className={`tl-item ${x.current ? "cur" : ""} reveal`}>
            <div className="tl-node"><i></i></div>
            <div className="tl-card glass">
              <div className="tl-top">
                <div>
                  <div className="tl-role">{x.role[lang]}
                    {x.current && <span className="tl-badge">{E.current}</span>}
                  </div>
                  <div className="tl-co">{x.company} <span>· {x.place[lang]} · {x.type[lang]}</span></div>
                </div>
                <div className="tl-period">{x.period[lang]}</div>
              </div>
              <ul className="tl-points">
                {x.points[lang].map((p, j) => <li key={j}>{p}</li>)}
              </ul>
            </div>
          </div>
        )}
      </div>
    </section>);

}

/* Skills */
function Skills({ t, lang }) {
  const S = t.skills;
  return (
    <section id="skills" className="wrap">
      <div className="sec-head reveal">
        <div className="kicker">{S.kicker}</div>
        <h2 className="sec-title">{S.title}</h2>
      </div>
      <div className="skills-grid">
        {window.CONTENT.skills.map((g, i) =>
        <div key={i} className="skill-card glass reveal" data-d={String(i % 3)}>
            <h4>{g.group[lang]}</h4>
            <div className="chips">
              {g.items.map((it, j) => <span key={j} className="chip">{it}</span>)}
            </div>
          </div>
        )}
        <div className="skill-card glass reveal" data-d="2">
          <h4>{S.langTitle}</h4>
          <div className="lang-row">
            {window.CONTENT.languages.map((l, i) =>
            <Lang key={i} l={l} lang={lang} />
            )}
          </div>
        </div>
      </div>
    </section>);

}
function Lang({ l, lang }) {
  const ref = useRefS(null);
  useEffectS(() => {
    const io = new IntersectionObserver((e) => {
      if (e[0].isIntersecting && ref.current) {ref.current.style.width = l.pct + "%";io.disconnect();}
    }, { threshold: 0.4 });
    if (ref.current) io.observe(ref.current.parentElement);
    return () => io.disconnect();
  }, []);
  return (
    <div className="lang-item">
      <div className="lang-top"><b>{l.name[lang]}</b><span>{l.level[lang]}</span></div>
      <div className="lang-bar"><div className="lang-fill" ref={ref}></div></div>
    </div>);

}

/* Projects */
function Projects({ t, lang }) {
  const P = t.projects;
  return (
    <section id="projects" className="wrap">
      <div className="sec-head reveal">
        <div className="kicker">{P.kicker}</div>
        <h2 className="sec-title">{P.title}</h2>
      </div>
      <div className="proj-list">
        {window.CONTENT.projects.map((p, i) =>
        <article key={i} className="proj-card glass reveal" data-d={String(i % 2)}>
            <div className="proj-main">
              <div className="proj-tag">{p.tag[lang]}</div>
              <h3 className="proj-name">{p.name}</h3>
              <p className="proj-summary">{p.summary[lang]}</p>
              <div className="proj-meta-lbl">{P.highlights}</div>
              <ul className="proj-highlights">
                {p.highlights[lang].map((h, j) => <li key={j}>{h}</li>)}
              </ul>
            </div>
            <div className="proj-side">
              <div>
                <div className="proj-meta-lbl">{P.role}</div>
                <div className="proj-role-v">{p.role[lang]}</div>
              </div>
              <div>
                <div className="proj-meta-lbl">Flow</div>
                <div className="proj-flow">{p.flow[lang]}</div>
              </div>
              <div>
                <div className="proj-meta-lbl">{P.stack}</div>
                <div className="proj-stack">
                  {p.stack.map((s, j) => <span key={j} className="chip">{s}</span>)}
                </div>
              </div>
            </div>
          </article>
        )}
      </div>
    </section>);

}

/* Education */
function Education({ t, lang }) {
  const E = t.education;
  return (
    <section id="education" className="wrap">
      <div className="sec-head reveal">
        <div className="kicker">{E.kicker}</div>
        <h2 className="sec-title">{E.title}</h2>
      </div>
      <div className="edu-grid">
        <div className="edu-list">
          {window.CONTENT.education.map((e, i) =>
          <div key={i} className="edu-card glass reveal" data-d={String(i % 3)}>
              <div className="edu-year">{e.period}</div>
              <div>
                <h4>{e.degree[lang]}</h4>
                <div className="edu-deg">{e.school}</div>
                <div className="edu-full">{e.full[lang]}</div>
                {e.note[lang] && <span className="edu-note">{e.note[lang]}</span>}
              </div>
            </div>
          )}
        </div>
        <div className="certs-card glass reveal" data-d="1">
          <h4>{E.certs}</h4>
          {window.CONTENT.certs.map((c, i) =>
          <div key={i} className="cert-item">
              <span className="y">{c.year}</span>
              <span className="n">{c.name[lang]}</span>
            </div>
          )}
        </div>
      </div>
    </section>);

}

/* Contact */
function Contact({ t }) {
  const C = t.contact;
  const ct = window.CONTENT.contact;
  return (
    <section id="contact" className="wrap">
      <div className="contact-card glass reveal" data-comment-anchor="2876c5443b-div-338-7">
        <div className="contact-inner">
          <div className="kicker" style={{ justifyContent: "center" }}>{C.kicker}</div>
          <h2 className="contact-title">{C.title}</h2>
          <p className="contact-body">{C.body}</p>
          <div className="contact-btns">
            <a className="btn btn-primary" href={ct.whatsappLink} target="_blank" rel="noopener">
              <svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><path d="M12.04 2c-5.46 0-9.91 4.45-9.91 9.91 0 1.75.46 3.45 1.32 4.95L2.05 22l5.25-1.38c1.45.79 3.08 1.21 4.74 1.21 5.46 0 9.91-4.45 9.91-9.91S17.5 2 12.04 2zm5.8 14.04c-.24.68-1.42 1.3-1.95 1.34-.5.04-1.13.21-3.66-.77-3.07-1.21-5.04-4.34-5.2-4.54-.15-.2-1.25-1.66-1.25-3.17s.79-2.25 1.07-2.56c.28-.31.61-.39.81-.39.2 0 .41 0 .58.01.19.01.44-.07.69.53.24.6.83 2.07.9 2.22.07.15.12.33.02.53-.1.2-.15.33-.3.5-.15.18-.31.39-.45.53-.15.15-.3.31-.13.6.17.3.76 1.25 1.63 2.02 1.12 1 2.07 1.31 2.36 1.46.3.15.47.13.64-.08.17-.2.74-.86.94-1.16.2-.3.39-.25.66-.15.27.1 1.71.81 2 .96.3.15.5.22.57.34.07.13.07.7-.17 1.39z"></path></svg>
              {C.whatsapp}
            </a>
            <a className="btn btn-ghost" href={ct.phoneLink}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92z"></path></svg>
              {C.phone} · {ct.phone}
            </a>
            <a className="btn btn-ghost" href={ct.linkedin} target="_blank" rel="noopener">
              <svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14zM8.34 9.85H5.67V18h2.67V9.85zM7 6.5a1.55 1.55 0 1 0 0 3.1 1.55 1.55 0 0 0 0-3.1zM18.34 18v-4.47c0-2.39-.51-4.22-3.3-4.22-1.34 0-2.24.74-2.61 1.43h-.04V9.85h-2.56V18h2.67v-4.03c0-1.06.2-2.09 1.52-2.09 1.3 0 1.32 1.21 1.32 2.16V18h2.6z"></path></svg>
              {C.linkedin}
            </a>
            <a className="btn btn-ghost" href={ct.cv} download={CV_FILENAME} onClick={downloadCV}>
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
              {C.cv}
            </a>
          </div>
        </div>
      </div>
    </section>);

}

/* Footer */
function Footer({ t }) {
  return (
    <footer className="footer">
      <div className="wrap footer-inner">
        <span>© {new Date().getFullYear()} Jhostter Antonio Valdez Ortiz</span>
        <span>{t.footer}</span>
      </div>
    </footer>);

}

Object.assign(window, {
  useReveal, RoleRotator, Counter, Nav, Hero, Stats, About,
  Experience, Skills, Projects, Education, Contact, Footer
});