// Home sections: hero, KPI strip, ticker, value tiles and closing CTA.

(function (NUON) {
  const { useState, useEffect, useRef } = React;
  const { IsoHero, TypoHero } = NUON;

  // ============================================================
  // HERO
  // ============================================================
  function Hero({ copy, variant, lang }) {
    const isType = variant === "typo";
    const targetLang = lang === "en" ? "en" : "es";

    const buildTarget = (page, hash = "") => {
      const url = new URL(`${page}${hash ? `#${hash}` : ""}`, window.location.href);
      url.searchParams.set("lang", targetLang);
      return url.toString();
    };

    const goContact = () => {
      window.location.assign(buildTarget("contacto.html"));
    };
    const goConsole = () => {
      window.location.assign(buildTarget("producto.html", "consola"));
    };

    return (
      <section className={`hero ${isType ? "hero--type" : ""}`} id="contenido" tabIndex="-1">
        <div className="container">
          <div className="hero__head">
            <div>
              <div className="hero__overline mono-label">
                <span className="dot"></span>
                <span>{copy.overline}</span>
              </div>
              <h1 className="hero__title">{copy.title}</h1>
              <p className="hero__subtitle">{copy.subtitle}</p>
            </div>
            <div>
              <p className="hero__lede">{copy.lede}</p>
              <div className="hero__cta">
                <button className="btn btn--primary btn--lg" onClick={goContact}>
                  <span>{copy.cta_primary}</span>
                  <span className="arr"></span>
                </button>
                <button className="btn btn--ghost btn--lg" onClick={goConsole}>
                  <span>{copy.cta_secondary}</span>
                </button>
              </div>
            </div>
          </div>

          {isType ? <TypoHero copy={copy} /> : <IsoHero copy={copy} />}
        </div>
      </section>
    );
  }

  // ============================================================
  // KPI STRIP
  // ============================================================
  function KpiStrip({ data }) {
    return (
      <section className="kpi-strip">
        <div className="container kpi-strip__inner">
          {data.map(([label, value, foot], i) => (
            <div className="kpi" key={i}>
              <div className="kpi__label">{label}</div>
              <div className="kpi__num">
                <KpiValue value={value} />
              </div>
              <div className="kpi__sub">{foot}</div>
            </div>
          ))}
        </div>
      </section>
    );
  }

  // El valor llega completo desde el diccionario («23%», «Hasta 37%», «36% a
  // 58%»). Se parte en números —que animan— y texto literal —que va en cuerpo
  // menor—, de modo que el contador no obligue a fragmentar la cifra publicada.
  const KPI_NUMBER = /\d[\d.,]*/g;

  function KpiValue({ value }) {
    const parts = [];
    let cut = 0;
    for (const m of String(value).matchAll(KPI_NUMBER)) {
      if (m.index > cut) parts.push({ text: value.slice(cut, m.index) });
      parts.push({ num: m[0] });
      cut = m.index + m[0].length;
    }
    if (cut < value.length) parts.push({ text: value.slice(cut) });
    return parts.map((p, i) =>
      p.num ? (
        <CountUp key={i} value={p.num} />
      ) : (
        <span className="unit" key={i}>
          {p.text}
        </span>
      )
    );
  }

  // Count-up animation when in view
  function CountUp({ value }) {
    const ref = useRef(null);
    const [shown, setShown] = useState("0");
    const startedRef = useRef(false);
    useEffect(() => {
      if (!ref.current) return;
      const target = parseFloat(String(value).replace(/,/g, ""));
      const isDecimal = String(value).includes(".");
      let raf;
      const obs = new IntersectionObserver(
        (entries) => {
          entries.forEach((e) => {
            if (e.isIntersecting && !startedRef.current) {
              startedRef.current = true;
              const final = isDecimal
                ? target.toFixed(1)
                : Math.round(target).toLocaleString("es-CO");
              // Con movimiento reducido la cifra aparece ya puesta, sin contar.
              if (NUON.prefersReducedMotion && NUON.prefersReducedMotion()) {
                setShown(final);
                return;
              }
              const dur = 1200;
              const t0 = performance.now();
              const tick = (t) => {
                const k = Math.min(1, (t - t0) / dur);
                const eased = 1 - Math.pow(1 - k, 3);
                const v = target * eased;
                const out = isDecimal ? v.toFixed(1) : Math.round(v).toLocaleString("es-CO");
                setShown(out);
                if (k < 1) raf = requestAnimationFrame(tick);
              };
              raf = requestAnimationFrame(tick);
            }
          });
        },
        { threshold: 0.4 }
      );
      obs.observe(ref.current);
      return () => {
        cancelAnimationFrame(raf);
        obs.disconnect();
      };
    }, [value]);
    return <span ref={ref}>{shown}</span>;
  }

  // ============================================================
  // TICKER
  // ============================================================
  function Ticker({ items }) {
    // The track scrolls half its width per loop: an even number of copies
    // loops without a jump, and eight outrun a wide screen with three items.
    const list = Array.from({ length: 8 }, () => items).flat();
    return (
      <div className="ticker">
        <div className="ticker__track">
          {list.map(([label, val, delta, cls], i) => (
            <div className="ticker__item" key={i}>
              <span className="sym">▮</span>
              <span style={{ color: "rgba(255,255,255,.65)" }}>{label}</span>
              <span style={{ color: "#fff", fontWeight: 600 }}>{val}</span>
              {delta && (
                <span className={cls === "pos" ? "pos" : cls === "neg" ? "neg" : ""}>{delta}</span>
              )}
            </div>
          ))}
        </div>
      </div>
    );
  }

  // ============================================================
  // HOME TILES (short home version)
  // ============================================================
  function HomeTiles({ copy }) {
    return (
      <section className="section">
        <div className="container">
          <div className="home-tiles">
            {copy.tiles.map((t, i) => (
              <div key={i} className="tile" style={{ "--accent": t.color }}>
                {/* El ordinal es parte del título, no un rótulo aparte: se lee
                  "01 Qué está haciendo la energía…" en una sola línea de voz. */}
                <h3 className="tile__title">
                  <span className="tile__title-num">{t.num}</span>
                  {t.title}
                </h3>
                <p className="tile__body">{t.body}</p>
              </div>
            ))}
          </div>
        </div>
      </section>
    );
  }

  // ============================================================
  // HOME CLOSING CTA
  // ============================================================
  function HomeClosingCta({ copy }) {
    return (
      <section className="home-cta" id="cierre">
        <div className="container">
          <div className="home-cta__inner">
            <div>
              <h2 className="home-cta__title">{copy.cierre_title}</h2>
              <p className="home-cta__lede">
                <span className="grad">{copy.cierre_lede}</span>
              </p>
            </div>
            <div>
              <a className="btn btn--ondark btn--lg" href="contacto.html">
                <span>{copy.cierre_btn}</span>
                <span className="arr"></span>
              </a>
            </div>
          </div>
        </div>
      </section>
    );
  }

  Object.assign(NUON, { Hero, KpiStrip, Ticker, HomeTiles, HomeClosingCta });
})((window.NUON ??= {}));
