/* ════════════════════════════════════════════════════════════════
   GRUPO CISPE — HERO acordeón cinemático (React + Tailwind)
   Monta en #hero-root. Edita el array UNITS para texto / color / video.
   #hero-root[data-chrome="full"]  → muestra logo + reloj propios (standalone)
   #hero-root.hx-embedded en CSS   → deja espacio para el nav del sitio
   ════════════════════════════════════════════════════════════════ */
const { useState, useEffect, useRef, useCallback } = React;

const UNITS = [
  { id:'seguridad',        eyebrow:'CISPE', title:'SEGURIDAD',        op:'OPERATIVO U-01', tags:['Protección','Control','Respuesta'],          ac:'#D9C229', cta:'ACCEDER AL SITIO', href:'https://cispe-seguridad.com',        video:'videos/seguridad.mp4' },
  { id:'capacitacion',     eyebrow:'CISPE', title:'CAPACITACIÓN',     op:'OPERATIVO U-02', tags:['Entrenamiento','Protocolos','Simulacros'],    ac:'#4F6F46', cta:'ACCEDER AL SITIO', href:'https://cispe-capacitacion.com',     video:'videos/capacitacion.mp4' },
  { id:'legal',            eyebrow:'CISPE', title:'LEGAL',            op:'OPERATIVO U-03', tags:['Respaldo','Cumplimiento','Defensa'],          ac:'#B68A3C', cta:'ACCEDER AL SITIO', href:'https://cispe-legal.com',            video:'videos/legal.mp4' },
  { id:'monitoreo',        eyebrow:'CISPE', title:'MONITOREO',        op:'OPERATIVO U-04', tags:['Vigilancia','Análisis','Control'],            ac:'#35B7F2', cta:'ACCEDER AL SITIO', href:'https://cispe-monitoreo.com',        video:'videos/monitoreo.mp4' },
  { id:'comercializadora', eyebrow:'CISPE', title:'COMERCIALIZADORA', op:'OPERATIVO U-05', tags:['Equipamiento','Tecnología','Suministro'],     ac:'#C96A18', cta:'ACCEDER AL SITIO', href:'https://cispe-comercializadora.com', video:'videos/comercializadora.mp4' },
  { id:'investigacion',    eyebrow:'CISPE', title:'INVESTIGACIÓN',    op:'OPERATIVO U-06', tags:['Inteligencia','Evidencia','Verificación'],    ac:'#7C6AA8', cta:'ACCEDER AL SITIO', href:'https://cispeinvestigacion.com',     video:'videos/investigacion.mp4' },
  { id:'grupo',            eyebrow:'GRUPO', title:'CISPE',            op:'MATRIZ OPERATIVA', tags:['Seis unidades','Una misión'],               ac:'#1D8FE1', cta:'CONOCER MÁS',      href:'#',                                  video:'videos/grupo-cispe.mp4', matrix:true },
];

const FALLBACK_DWELL = 6500;   // ms — si un video no carga o no tiene duración
const HARD_CAP       = 14000;  // ms — tope por panel para mantener la rotación viva

function Arrow({ s = 13 }) {
  return (
    <svg viewBox="0 0 24 24" width={s} height={s} fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M5 12h14M13 6l6 6-6 6" />
    </svg>
  );
}

function Panel({ u, idx, active, vertical, onActivate, setRef, onFail, failed }) {
  const isActive = active;
  return (
    <article
      className={"hx-panel hx-scan group" + (isActive ? " is-on" : "")}
      style={{ "--ac": u.ac, "--g": isActive ? 12 : 1 }}
      onClick={() => onActivate(idx)}
      onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onActivate(idx); } }}
      tabIndex={0}
      role="button"
      aria-pressed={isActive}
      aria-label={u.eyebrow + " " + u.title}
    >
      {!failed ? (
        <video
          ref={(el) => setRef(idx, el)}
          muted loop={false} playsInline
          preload={isActive ? "auto" : "metadata"}
          onError={() => onFail(idx)}
        >
          <source src={u.video} type="video/mp4" />
        </video>
      ) : (
        <div className="hx-fallback" style={{ background: `radial-gradient(120% 90% at 30% 0%, ${u.ac}22, #0B0D0E 60%)` }} />
      )}

      <div className="hx-tint" />
      <div className="hx-veil" />
      <span className="hx-edge" />

      <span className="hx-node" style={{ top: 10, right: 10 }} />
      <span className="hx-node" style={{ bottom: 10, left: 10 }} />

      <span className="hx-bk tl" /><span className="hx-bk tr" /><span className="hx-bk bl" /><span className="hx-bk br" />

      {/* index chip */}
      <div className="hx-mono absolute top-0 left-0 px-2.5 py-1.5 text-[10px] tracking-[0.18em] flex items-center gap-1.5 z-10"
           style={{ color: isActive ? u.ac : "rgba(242,244,242,.55)" }}>
        <span className="inline-block w-1.5 h-1.5 rounded-full"
              style={{ background: u.ac, boxShadow: isActive ? `0 0 8px ${u.ac}` : "none", opacity: isActive ? 1 : .5 }} />
        {String(idx + 1).padStart(2, "0")}
      </div>

      {/* compressed label */}
      <div className="hx-vlabel absolute inset-0 flex items-center justify-center pointer-events-none">
        <span className={(vertical ? "" : "hx-vtext ") + "font-cond uppercase leading-none text-thumo/82 group-hover:text-thumo transition-colors"}
              style={{ fontSize: vertical ? "clamp(.95rem,3.6vw,1.3rem)" : "clamp(1rem,1.5vw,1.4rem)", fontWeight: 500, letterSpacing: ".07em" }}>
          {u.matrix ? "GRUPO CISPE" : u.title}
        </span>
      </div>

      {/* active content */}
      <div className="hx-content absolute inset-0 flex flex-col justify-end p-6 sm:p-8 lg:p-10 z-10">
        <div className="hx-mono text-[11px] tracking-[0.34em] mb-3 flex items-center gap-2.5" style={{ color: u.ac }}>
          <span className="inline-block w-4 h-px" style={{ background: u.ac }} />
          {u.op}
        </div>

        <h2 className="font-cond uppercase text-thumo leading-[0.92]" style={{ fontWeight: 600, letterSpacing: "0.01em" }}>
          <span className="hx-mono block text-ttec tracking-[0.42em] mb-1.5"
                style={{ fontSize: "clamp(.7rem,1vw,.95rem)", fontWeight: 400 }}>{u.eyebrow}</span>
          <span className="block" style={{ fontSize: "clamp(2.3rem,6vw,5.6rem)" }}>{u.title}</span>
        </h2>

        <div className="mt-4 flex flex-wrap items-center gap-x-3 gap-y-1.5">
          {u.tags.map((t, i) => (
            <React.Fragment key={t}>
              {i > 0 && <span className="text-ttec/50 text-xs">/</span>}
              <span className="font-cond uppercase tracking-[0.14em] text-thumo/78"
                    style={{ fontSize: "clamp(.82rem,1.1vw,1.05rem)" }}>{t}</span>
            </React.Fragment>
          ))}
        </div>

        <a href={u.href} target={u.href !== "#" ? "_blank" : undefined} rel="noopener"
           onClick={(e) => e.stopPropagation()}
           className="hx-mono mt-7 inline-flex items-center gap-2.5 self-start px-4 py-2.5 text-[11px] tracking-[0.2em] text-thumo border transition-colors duration-300"
           style={{ borderColor: `color-mix(in srgb, ${u.ac} 55%, transparent)`, background: "rgba(5,6,7,.34)" }}
           onMouseEnter={(e) => { e.currentTarget.style.background = `color-mix(in srgb, ${u.ac} 16%, rgba(5,6,7,.34))`; }}
           onMouseLeave={(e) => { e.currentTarget.style.background = "rgba(5,6,7,.34)"; }}>
          {u.cta} <span style={{ color: u.ac }}><Arrow /></span>
        </a>
      </div>

      <span className="hx-pbar" />
    </article>
  );
}

function Hero({ full }) {
  const [active, setActive] = useState(0);
  const [progress, setProgress] = useState(0);
  const [failed, setFailed] = useState({});
  const [vertical, setVertical] = useState(false);
  const [clock, setClock] = useState("--:--:--");
  const [muted, setMuted] = useState(false);   // música ON por defecto
  const [needTap, setNeedTap] = useState(false); // navegador bloqueó el autoplay
  const [inView, setInView] = useState(true);  // hero visible en el viewport

  const audioRef = useRef(null);
  const sectionRef = useRef(null);
  const musicStartedRef = useRef(false);
  const mutedRef = useRef(false);

  /* ── AUDIO SINGLETON: garantiza que NUNCA exista más de un <audio> sonando.
        Si un montaje previo dejó audio huérfano, lo elimina antes de reusar. ── */
  useEffect(() => {
    // mata cualquier audio del hero que ande suelto
    document.querySelectorAll("audio[data-hero-music]").forEach((el) => {
      if (el !== window.__cispeHeroAudio) { try { el.pause(); } catch (e) {} el.remove(); }
    });
    let a = window.__cispeHeroAudio;
    if (!a || !document.body.contains(a)) {
      a = document.createElement("audio");
      a.setAttribute("data-hero-music", "");
      a.src = "videos/musica-hero.mp3?v=6";
      a.loop = true;
      a.preload = "auto";
      a.volume = 0.55;
      document.body.appendChild(a);
      window.__cispeHeroAudio = a;
    }
    audioRef.current = a;
    a.muted = mutedRef.current;
    musicStartedRef.current = !a.paused;   // refleja estado real si ya venía sonando

    const stop = () => { try { a.pause(); } catch (e) {} };
    window.addEventListener("pagehide", stop);
    return () => {
      // al desmontar (recarga en caliente / navegación SPA) detén el audio
      // para que no quede sonando en paralelo con el nuevo montaje
      stop();
      window.removeEventListener("pagehide", stop);
    };
  }, []);

  const videoRefs = useRef([]);
  const rafRef = useRef(0);
  const timerRef = useRef(0);
  const setRef = useCallback((i, el) => { videoRefs.current[i] = el; }, []);
  const onFail = useCallback((i) => setFailed((f) => ({ ...f, [i]: true })), []);
  const goTo = useCallback((i) => setActive(((i % UNITS.length) + UNITS.length) % UNITS.length), []);

  useEffect(() => {
    const mq = window.matchMedia("(max-width: 860px)");
    const apply = () => setVertical(mq.matches);
    apply();
    mq.addEventListener("change", apply);
    return () => mq.removeEventListener("change", apply);
  }, []);

  useEffect(() => {
    const t = setInterval(() => setClock(new Date().toUTCString().slice(17, 25)), 1000);
    return () => clearInterval(t);
  }, []);

  /* ── el hero solo "vive" mientras está en pantalla: al hacer scroll fuera,
        se pausan video y música; al volver, se reanudan ── */
  useEffect(() => {
    const el = sectionRef.current;
    if (!el || !("IntersectionObserver" in window)) return;
    const io = new IntersectionObserver(
      ([entry]) => setInView(entry.isIntersecting && entry.intersectionRatio > 0.12),
      { threshold: [0, 0.12, 0.5] }
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);

  /* música sigue la visibilidad del hero (sin reiniciarla) */
  useEffect(() => {
    const a = audioRef.current;
    if (!a) return;
    if (!inView) { try { a.pause(); } catch (e) {} }
    else if (musicStartedRef.current && !mutedRef.current) {
      const pr = a.play(); if (pr && pr.catch) pr.catch(() => {});
    }
  }, [inView]);

  /* ── audio de fondo: NO suena en el montaje; arranca coordinado con el
        primer video (ver motor de reproducción). Si el navegador bloquea el
        autoplay, el primer gesto del usuario lo dispara. ── */
  useEffect(() => {
    const a = audioRef.current;
    if (!a) return;
    a.volume = 0.55;

    const onGesture = () => {
      if (!mutedRef.current && !musicStartedRef.current) {
        // re-sincroniza: reinicia el ciclo desde el panel 1 + música a la vez
        setActive(0);
        try { a.currentTime = 0; } catch (e) {}
        const pr = a.play();
        if (pr && pr.then) pr.then(() => { musicStartedRef.current = true; setNeedTap(false); }).catch(() => {});
      }
      setNeedTap(false);
      window.removeEventListener("pointerdown", onGesture);
      window.removeEventListener("keydown", onGesture);
      window.removeEventListener("scroll", onGesture);
      window.removeEventListener("touchstart", onGesture);
    };
    window.addEventListener("pointerdown", onGesture, { once: true });
    window.addEventListener("keydown", onGesture, { once: true });
    window.addEventListener("scroll", onGesture, { once: true, passive: true });
    window.addEventListener("touchstart", onGesture, { once: true, passive: true });

    return () => {
      window.removeEventListener("pointerdown", onGesture);
      window.removeEventListener("keydown", onGesture);
      window.removeEventListener("scroll", onGesture);
      window.removeEventListener("touchstart", onGesture);
    };
  }, []);

  /* sincroniza el estado mute con el elemento <audio> */
  useEffect(() => {
    const a = audioRef.current;
    if (!a) return;
    mutedRef.current = muted;
    a.muted = muted;
    if (!muted && musicStartedRef.current) { const pr = a.play(); if (pr && pr.catch) pr.catch(() => {}); }
  }, [muted]);

  /* playback + progress engine */
  useEffect(() => {
    setProgress(0);
    cancelAnimationFrame(rafRef.current);
    clearTimeout(timerRef.current);

    videoRefs.current.forEach((v, i) => {
      if (v && i !== active) { try { v.pause(); v.currentTime = 0; } catch (e) {} }
    });

    const next = () => setActive((a) => (a + 1) % UNITS.length);
    const v = videoRefs.current[active];
    const start = performance.now();

    // hero fuera de pantalla: pausa todo y espera a volver
    if (!inView) {
      videoRefs.current.forEach((vid) => { if (vid) { try { vid.pause(); } catch (e) {} } });
      return () => {};
    }

    if (!v || failed[active]) {
      const tick = (t) => {
        const p = Math.min(1, (t - start) / FALLBACK_DWELL);
        setProgress(p);
        if (p < 1) rafRef.current = requestAnimationFrame(tick);
        else next();
      };
      rafRef.current = requestAnimationFrame(tick);
      return () => { cancelAnimationFrame(rafRef.current); clearTimeout(timerRef.current); };
    }

    try { v.currentTime = 0; } catch (e) {}
    const pr = v.play();
    if (pr && pr.catch) pr.catch(() => {});

    /* ── arranca la música EXACTAMENTE con el primer video (panel 1) ── */
    if (active === 0 && !musicStartedRef.current && !mutedRef.current) {
      const a = audioRef.current;
      if (a) {
        try { a.currentTime = 0; } catch (e) {}
        a.muted = false;
        const ap = a.play();
        if (ap && ap.then) ap.then(() => { musicStartedRef.current = true; setNeedTap(false); })
                            .catch(() => setNeedTap(true));
      }
    }

    const onEnded = () => next();
    v.addEventListener("ended", onEnded);

    const tick = () => {
      const d = v.duration;
      let p;
      if (d && isFinite(d) && d > 0) p = v.currentTime / d;
      else p = Math.min(1, (performance.now() - start) / FALLBACK_DWELL);
      setProgress(Math.max(0, Math.min(1, p)));
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    timerRef.current = setTimeout(next, HARD_CAP);

    return () => {
      v.removeEventListener("ended", onEnded);
      cancelAnimationFrame(rafRef.current);
      clearTimeout(timerRef.current);
    };
  }, [active, failed, inView]);

  useEffect(() => {
    const onKey = (e) => {
      if (e.key === "ArrowRight") goTo(active + 1);
      else if (e.key === "ArrowLeft") goTo(active - 1);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [active, goTo]);

  useEffect(() => {
    const el = document.querySelectorAll(".hx-panel")[active];
    if (el) el.style.setProperty("--p", (progress * 100).toFixed(2) + "%");
  }, [progress, active]);

  const cur = UNITS[active];
  const topAccordion = "calc(var(--hx-navpad) + clamp(40px, 5.5vh, 58px))";
  const topMarquee   = "calc(var(--hx-navpad) + clamp(10px, 1.6vh, 16px))";

  return (
    <section ref={sectionRef} className={"hx-hero relative w-full bg-tnegro text-thumo overflow-hidden" + (full ? "" : " hx-embedded")}
             style={{ height: "100svh", minHeight: 600 }}>
      <div className="hx-gridov" />
      <span className="hx-fb tl" /><span className="hx-fb tr" /><span className="hx-fb bl" /><span className="hx-fb br" />


      {/* control de sonido (HUD) */}
      <button onClick={() => setMuted((m) => !m)}
              aria-label={muted ? "Activar sonido" : "Silenciar"}
              className="group absolute z-40 flex items-center gap-2 px-3 py-2 font-mono text-[10px] tracking-[0.2em] text-thumo border border-[#7A838A]/30 bg-tnegro/55 backdrop-blur-[1px] hover:border-[#7A838A]/60 transition-colors"
              style={{ right: "clamp(16px, 2.4vw, 34px)", bottom: "clamp(58px, 8vh, 84px)" }}>
        <span className={"hx-eq" + (muted ? " is-off" : "")} aria-hidden="true">
          <i></i><i></i><i></i><i></i>
        </span>
        <span className="hidden sm:inline">{needTap && !muted ? "ACTIVAR AUDIO" : muted ? "SONIDO OFF" : "SONIDO ON"}</span>
      </button>

      {full && (
        <header className="absolute top-0 inset-x-0 z-30 flex items-center justify-between px-5 sm:px-8 pt-5 sm:pt-6">
          <img src="assets/logo-header-2.webp" alt="Grupo CISPE" className="h-7 sm:h-9 w-auto"
               onError={(e)=>{e.currentTarget.style.display='none';}} />
          <div className="hidden md:flex items-center gap-6 font-mono text-[10.5px] tracking-[0.2em] text-ttec">
            <span className="flex items-center gap-2">
              <span className="inline-block w-1.5 h-1.5 rounded-full bg-[#B6E22E]" style={{ boxShadow: "0 0 8px #B6E22E" }} />
              OPERATIVO · 24/7
            </span>
            <span className="text-thumo/80">UTC {clock}</span>
          </div>
        </header>
      )}

      {/* marquee */}
      <div className="absolute inset-x-0 z-20 border-y border-[#7A838A]/14 bg-tnegro/55 backdrop-blur-[1px] overflow-hidden"
           style={{ top: topMarquee }}>
        <div className="font-mono text-[9.5px] tracking-[0.26em] text-ttec/70 py-1.5">
          <div className="hx-marq">
            {[0,1].map((k)=>(
              <span className="inline-flex gap-9" key={k} aria-hidden={k===1}>
                <span>// SECURITY · INTELLIGENCE · OPS</span>
                <span>// 06_UNIDADES_ACTIVAS</span>
                <span>// PERIM_OK · TX_OK · NODE_OK</span>
                <span>// SEÑAL ESTABLE · CANAL CISPE-MX</span>
                <span>// OPERATION CONTINUITY</span>
                <span>// N 19°25′10″  W 99°08′44″</span>
              </span>
            ))}
          </div>
        </div>
      </div>

      {/* accordion */}
      <div className="absolute inset-x-0 z-10 px-3 sm:px-5"
           style={{ top: topAccordion, bottom: "clamp(64px, 9vh, 86px)" }}>
        <div className="flex h-full w-full gap-[3px]" style={{ flexDirection: vertical ? "column" : "row" }}>
          {UNITS.map((u, i) => (
            <Panel key={u.id} u={u} idx={i} active={i === active} vertical={vertical}
                   onActivate={goTo} setRef={setRef} onFail={onFail} failed={!!failed[i]} />
          ))}
        </div>
      </div>

      {/* bottom bar */}
      <footer className="absolute bottom-0 inset-x-0 z-30 px-5 sm:px-8 pb-4 sm:pb-5">
        <div className="flex items-center gap-4 sm:gap-6">
          <span className="font-mono text-[10px] tracking-[0.2em] hidden sm:inline" style={{ color: cur.ac }}>
            FASE_{String(active + 1).padStart(3, "0")}
          </span>

          <div className="flex-1 flex items-center gap-1.5">
            {UNITS.map((u, i) => (
              <button key={u.id} onClick={() => goTo(i)} aria-label={"Ir a " + u.title}
                      className="group relative h-[3px] flex-1 bg-[#7A838A]/22 overflow-hidden transition-all"
                      style={{ flexGrow: i === active ? 2.4 : 1 }}>
                <span className="absolute inset-y-0 left-0"
                      style={{
                        background: u.ac,
                        width: i < active ? "100%" : i === active ? (progress * 100).toFixed(2) + "%" : "0%",
                        boxShadow: i === active ? `0 0 10px ${u.ac}` : "none",
                        transition: i === active ? "width 120ms linear" : "width 500ms ease",
                      }} />
              </button>
            ))}
          </div>

          <div className="font-mono text-[10px] tracking-[0.2em] text-ttec flex items-center gap-1">
            <span style={{ color: cur.ac }}>{String(active + 1).padStart(2, "0")}</span>
            <span className="text-ttec/45">/ {String(UNITS.length).padStart(2, "0")}</span>
          </div>

          <div className="hidden sm:flex items-center gap-1.5">
            <button onClick={() => goTo(active - 1)} aria-label="Anterior"
                    className="w-7 h-7 grid place-items-center border border-[#7A838A]/30 text-ttec hover:text-thumo hover:border-[#7A838A]/60 transition-colors">
              <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2"><path d="M15 5l-7 7 7 7"/></svg>
            </button>
            <button onClick={() => goTo(active + 1)} aria-label="Siguiente"
                    className="w-7 h-7 grid place-items-center border border-[#7A838A]/30 text-ttec hover:text-thumo hover:border-[#7A838A]/60 transition-colors">
              <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2"><path d="M9 5l7 7-7 7"/></svg>
            </button>
          </div>
        </div>
      </footer>
    </section>
  );
}

(function mount() {
  const rootEl = document.getElementById("hero-root");
  if (!rootEl) return;
  const full = rootEl.dataset.chrome === "full";
  ReactDOM.createRoot(rootEl).render(<Hero full={full} />);
})();
