/* eslint-disable */
/* global React, window, PAIN_LANDINGS */
const { useEffect, useMemo, useRef, useState } = React;

const PAIN_KEYS = Object.keys(PAIN_LANDINGS);
const GATEWAY_ROUTE_VERSION = '20260519-gateway-stagevideos';
const TRANSITION_MS = 520;
const ACTIVATION_TAIL_MS = 1000;
const BASE_IMAGE = '01_inicial_meditacion_fondo_negro';
const DIAGNOSTIC_VIDEOS = ['activation-01', 'activation-02', 'activation-03'];
const STAGE_ACTIVATION_VIDEOS = ['activation-01', 'activation-02', 'activation-03'];

const VISUAL_STATES = {
  neutral: {
    label: 'Calibración inicial',
    short: 'Sistema Cortex',
    video: 'activation-01',
    poster: BASE_IMAGE,
  },
  sueno: {
    label: 'Ruido nocturno',
    short: 'Sueño',
    video: 'activation-02',
    poster: 'activation-02-poster',
  },
  ruido: {
    label: 'Interferencia mental',
    short: 'Ruido mental',
    video: 'activation-02',
    poster: 'activation-02-poster',
  },
  decisiones: {
    label: 'Opciones abiertas',
    short: 'Decisión',
    video: 'activation-02',
    poster: 'activation-02-poster',
  },
  burnout: {
    label: 'Energía drenada',
    short: 'Energía',
    video: 'activation-01',
    poster: 'activation-01-poster',
  },
  foco: {
    label: 'Atención dispersa',
    short: 'Foco',
    video: 'activation-03',
    poster: 'activation-03-poster',
  },
};

const PRELOAD_ASSETS = [
  { id: BASE_IMAGE, type: 'image', url: 'assets/diagnostico/01_inicial_meditacion_fondo_negro.webp' },
  { id: 'activation-01-poster', type: 'image', url: 'assets/diagnostico/activation-01-poster.jpg' },
  { id: 'activation-02-poster', type: 'image', url: 'assets/diagnostico/activation-02-poster.jpg' },
  { id: 'activation-03-poster', type: 'image', url: 'assets/diagnostico/activation-03-poster.jpg' },
  ...DIAGNOSTIC_VIDEOS.map((id) => ({ id, type: 'video', url: `assets/diagnostico/${id}.mp4` })),
];

const QUESTIONS = [
  {
    label: '01 / Lo que más pesa',
    title: <>¿Qué te está afectando <em>más</em> hoy?</>,
    help: 'Elige la frase que más se parece a tu día real.',
    options: [
      { text: 'No puedo dormir o me despierto de madrugada', score: { sueno: 5 } },
      { text: 'Mi cabeza no para y no logro cortar', score: { ruido: 5 } },
      { text: 'Tengo información, pero sigo sin decidir', score: { decisiones: 5 } },
      { text: 'Estoy agotado aunque sigo funcionando', score: { burnout: 5 } },
      { text: 'Me disperso y no termino lo que empiezo', score: { foco: 5 } },
    ],
  },
  {
    label: '02 / Cuándo aparece',
    title: <>¿En qué momento se vuelve <em>más evidente</em>?</>,
    help: 'Esto afina la ruta sin hacerte contestar un formulario largo.',
    options: [
      { text: 'De noche, cuando debería apagar', score: { sueno: 3, ruido: 2 } },
      { text: 'Al despertar, cuando ya arranco sin energía', score: { burnout: 3, sueno: 1 } },
      { text: 'Frente a una decisión importante', score: { decisiones: 4, ruido: 1 } },
      { text: 'Cuando trabajo con pantalla, pestañas o redes', score: { foco: 4, burnout: 1 } },
      { text: 'Después de conversaciones o estrés', score: { ruido: 3, burnout: 2 } },
    ],
  },
  {
    label: '03 / Primer cambio',
    title: <>Si esto mejora, <em>¿qué notarías primero?</em></>,
    help: 'La landing siguiente va a hablarte desde esa prioridad.',
    options: [
      { text: 'Dormir de corrido y levantarme más liviano', score: { sueno: 4 } },
      { text: 'Tener silencio mental aunque el día esté intenso', score: { ruido: 4 } },
      { text: 'Decidir sin postergar tres meses', score: { decisiones: 4 } },
      { text: 'Recuperar energía sin apilar más hábitos', score: { burnout: 4 } },
      { text: 'Sostener foco real durante la mañana', score: { foco: 4 } },
    ],
  },
];

function gwAsset(path) {
  const prefix = window.CORTEX_ASSET_PREFIX || '../';
  return `${prefix}${path}`;
}

function scoreToPain(scores) {
  const ranked = [...PAIN_KEYS].sort((a, b) => scores[b] - scores[a]);
  return ranked[0] || 'ruido';
}

function visualPainFromScores(scores) {
  const hasScore = Object.values(scores).some((score) => score > 0);
  return hasScore ? scoreToPain(scores) : 'neutral';
}

function optionTarget(option) {
  return Object.entries(option.score)
    .sort((a, b) => b[1] - a[1])[0]?.[0] || 'neutral';
}

function emptyScores() {
  return PAIN_KEYS.reduce((acc, key) => ({ ...acc, [key]: 0 }), {});
}

function scoresFromSelections(selections) {
  const nextScores = emptyScores();
  Object.values(selections).forEach((option) => {
    Object.entries(option.score).forEach(([key, value]) => {
      nextScores[key] += value;
    });
  });
  return nextScores;
}

function answersFromSelections(selections) {
  return Object.keys(selections)
    .map(Number)
    .sort((a, b) => a - b)
    .map((index) => selections[index].text);
}

function safeStoreResult(pain, answers) {
  try {
    window.sessionStorage.setItem('cortex-gateway-result', JSON.stringify({
      pain: pain.slug,
      answers,
      createdAt: new Date().toISOString(),
    }));
  } catch (_) {
    // Some embedded browsers block storage. The click must still navigate.
  }
}

function GatewayChrome() {
  return (
    <header className="gw-chrome">
      <img src={gwAsset('assets/logo-cortex-white.png')} alt="Academia Cortex" />
    </header>
  );
}

function GatewaySlideIndicator({ activeStep, onSelect }) {
  return (
    <nav className="gw-slide-indicator" aria-label="Progreso del diagnóstico">
      {QUESTIONS.map((_, index) => (
        <button
          key={index}
          type="button"
          className={`gw-slide-dot ${index === activeStep ? 'is-active' : ''} ${index < activeStep ? 'is-complete' : ''}`}
          onClick={() => onSelect(index)}
          aria-label={`Ir a pregunta ${index + 1}`}
          aria-current={index === activeStep ? 'step' : undefined}
        ></button>
      ))}
    </nav>
  );
}

function GatewayLoading({ progress }) {
  return (
    <div className="gw-loading" role="status" aria-live="polite">
      <div className="gw-loading-core">
        <span>Academia Cortex</span>
        <strong>{progress}%</strong>
        <div aria-hidden="true">
          <i style={{ transform: `scaleX(${progress / 100})` }}></i>
        </div>
        <p>Cargando diagnóstico</p>
      </div>
    </div>
  );
}

function GatewayMedia({ visualPain, activeVideoId, isHolding, videoSources, videoRefs }) {
  const visual = VISUAL_STATES[visualPain] || VISUAL_STATES.neutral;

  return (
    <div className="gw-media" aria-hidden="true">
      <picture className="gw-base-media">
        <source srcSet={gwAsset('assets/diagnostico/01_inicial_meditacion_fondo_negro.avif')} type="image/avif" />
        <source srcSet={gwAsset('assets/diagnostico/01_inicial_meditacion_fondo_negro.webp')} type="image/webp" />
        <img src={gwAsset('assets/diagnostico/01_inicial_meditacion_fondo_negro.png')} alt="" draggable="false" />
      </picture>

      <div className={`gw-activation-media ${isHolding ? 'is-active' : ''}`}>
        {DIAGNOSTIC_VIDEOS.map((id) => (
          <video
            key={id}
            ref={(node) => {
              if (node) videoRefs.current[id] = node;
            }}
            className={activeVideoId === id ? 'is-visible' : ''}
            src={videoSources[id] || gwAsset(`assets/diagnostico/${id}.mp4`)}
            muted
            loop
            playsInline
            preload="auto"
            draggable={false}
            disablePictureInPicture
            controlsList="nodownload nofullscreen noremoteplayback"
            onContextMenu={(event) => event.preventDefault()}
          ></video>
        ))}
      </div>

      <div className="gw-media-status">
        <span>{visual.label}</span>
        <strong>{visual.short}</strong>
      </div>
      <div className="gw-media-grain"></div>
    </div>
  );
}

function HoldCue({ isHolding, hasHeld }) {
  return (
    <div className={`gw-hold-cue ${isHolding ? 'is-active' : ''} ${hasHeld ? 'is-muted' : ''}`} aria-hidden="true">
      <span></span>
      <strong>{isHolding ? 'Soltá para volver' : 'Mantené presionado para activar'}</strong>
    </div>
  );
}

function GatewayQuestion({ question, questionIndex, onPick, getHref, disabled, selectedText }) {
  return (
    <section className="gw-panel">
      <div className="gw-eyebrow">{question.label}</div>
      <h1>{question.title}</h1>
      <p>{question.help}</p>
      <div className="gw-options">
        {question.options.map((option, index) => {
          const target = optionTarget(option);
          const content = (
            <>
              <span>{String(index + 1).padStart(2, '0')}</span>
              <strong>{option.text}</strong>
            </>
          );
          const href = getHref ? getHref(option) : null;
          const isSelected = selectedText === option.text;

          if (href) {
            return (
              <a
                key={option.text}
                className={`gw-option gw-option-${target} ${isSelected ? 'is-selected' : ''}`}
                href={href}
                onClick={(event) => onPick(option, questionIndex, event)}
                aria-disabled={disabled ? 'true' : undefined}
              >
                {content}
              </a>
            );
          }

          return (
            <button
              key={option.text}
              className={`gw-option gw-option-${target} ${isSelected ? 'is-selected' : ''}`}
              onClick={(event) => onPick(option, questionIndex, event)}
              disabled={disabled}
            >
              {content}
            </button>
          );
        })}
      </div>
    </section>
  );
}

function Gateway() {
  const videoRefs = useRef({});
  const holdTimerRef = useRef(null);
  const stageRef = useRef(null);
  const slideRefs = useRef([]);
  const [activeStep, setActiveStep] = useState(0);
  const [selectedOptions, setSelectedOptions] = useState({});
  const [activePulse, setActivePulse] = useState(null);
  const [hasHeld, setHasHeld] = useState(false);
  const [isHolding, setIsHolding] = useState(false);
  const [isTransitioning, setIsTransitioning] = useState(false);
  const [isExiting, setIsExiting] = useState(false);
  const [loadProgress, setLoadProgress] = useState(0);
  const [isReady, setIsReady] = useState(false);
  const [videoSources, setVideoSources] = useState({});
  const transitionRef = useRef(null);
  const scores = useMemo(() => scoresFromSelections(selectedOptions), [selectedOptions]);
  const visualPain = activePulse || visualPainFromScores(scores);
  const visual = VISUAL_STATES[visualPain] || VISUAL_STATES.neutral;
  const activeVideoId = STAGE_ACTIVATION_VIDEOS[activeStep] || visual.video;

  useEffect(() => {
    let cancelled = false;
    const objectUrls = [];

    async function preload() {
      const sources = {};
      let completed = 0;

      await Promise.all(PRELOAD_ASSETS.map(async (asset) => {
        try {
          const response = await fetch(gwAsset(asset.url), { cache: 'force-cache' });
          if (!response.ok) throw new Error(`Could not load ${asset.url}`);
          const blob = await response.blob();
          if (asset.type === 'video') {
            const objectUrl = URL.createObjectURL(blob);
            objectUrls.push(objectUrl);
            sources[asset.id] = objectUrl;
          }
        } catch (_) {
          if (asset.type === 'video') sources[asset.id] = gwAsset(asset.url);
        } finally {
          completed += 1;
          if (!cancelled) {
            setLoadProgress(Math.round((completed / PRELOAD_ASSETS.length) * 100));
          }
        }
      }));

      if (!cancelled) {
        setVideoSources(sources);
        setLoadProgress(100);
        window.setTimeout(() => {
          if (!cancelled) setIsReady(true);
        }, 160);
      }
    }

    preload();

    return () => {
      cancelled = true;
      objectUrls.forEach((url) => URL.revokeObjectURL(url));
    };
  }, []);

  useEffect(() => {
    if (!isReady) return;

    Object.values(videoRefs.current).forEach((video) => {
      video.muted = true;
      video.playsInline = true;
      video.loop = true;
      video.currentTime = 0.01;
      const promise = video.play();
      if (promise?.catch) promise.catch(() => {});
    });
  }, [isReady, videoSources]);

  useEffect(() => {
    if (!isReady) return undefined;

    const stop = () => stopHold();
    window.addEventListener('pointerup', stop);
    window.addEventListener('pointercancel', stop);
    window.addEventListener('touchend', stop, { passive: true });
    window.addEventListener('touchcancel', stop, { passive: true });
    window.addEventListener('mouseup', stop);
    window.addEventListener('blur', stop);

    return () => {
      window.removeEventListener('pointerup', stop);
      window.removeEventListener('pointercancel', stop);
      window.removeEventListener('touchend', stop);
      window.removeEventListener('touchcancel', stop);
      window.removeEventListener('mouseup', stop);
      window.removeEventListener('blur', stop);
      window.clearTimeout(holdTimerRef.current);
    };
  }, [isReady, visualPain]);

  useEffect(() => {
    if (!isReady) return undefined;
    const stage = stageRef.current;
    if (!stage) return undefined;
    let frame = 0;

    const updateActiveStep = () => {
      frame = 0;
      const slideHeight = stage.clientHeight || window.innerHeight || 1;
      const nextStep = Math.max(0, Math.min(QUESTIONS.length - 1, Math.round(stage.scrollTop / slideHeight)));
      setActiveStep(nextStep);
    };

    const handleScroll = () => {
      if (frame) return;
      frame = window.requestAnimationFrame(updateActiveStep);
    };

    updateActiveStep();
    stage.addEventListener('scroll', handleScroll, { passive: true });

    return () => {
      stage.removeEventListener('scroll', handleScroll);
      if (frame) window.cancelAnimationFrame(frame);
    };
  }, [isReady]);

  function clearTransition() {
    if (transitionRef.current) window.clearTimeout(transitionRef.current);
  }

  function scrollToStep(index, behavior = 'smooth') {
    const safeIndex = Math.max(0, Math.min(QUESTIONS.length - 1, index));
    const stage = stageRef.current;
    const slide = slideRefs.current[safeIndex];
    setActiveStep(safeIndex);
    if (stage && slide) {
      stage.scrollTo({ top: slide.offsetTop, behavior });
    }
  }

  function startHold(event) {
    if (!isReady) return;
    if (event?.pointerType === 'mouse' && event.button !== 0) return;
    window.clearTimeout(holdTimerRef.current);
    setHasHeld(true);
    setIsHolding(true);
    const activeVideo = videoRefs.current[activeVideoId];
    if (activeVideo) {
      const promise = activeVideo.play();
      if (promise?.catch) promise.catch(() => {});
    }
  }

  function stopHold() {
    window.clearTimeout(holdTimerRef.current);
    holdTimerRef.current = window.setTimeout(() => {
      setIsHolding(false);
    }, ACTIVATION_TAIL_MS);
  }

  function pick(option, questionIndex, event) {
    if (isTransitioning) {
      event?.preventDefault?.();
      return;
    }

    const nextSelections = { ...selectedOptions, [questionIndex]: option };
    const nextScores = scoresFromSelections(nextSelections);
    const nextAnswers = answersFromSelections(nextSelections);
    const isFinalStep = questionIndex + 1 >= QUESTIONS.length;
    const painKey = isFinalStep ? optionTarget(option) : scoreToPain(nextScores);
    const pain = PAIN_LANDINGS[painKey];
    event?.currentTarget?.blur?.();
    setSelectedOptions(nextSelections);
    setActivePulse(painKey);
    setIsTransitioning(true);
    stopHold();

    if (isFinalStep) {
      event?.preventDefault?.();
      safeStoreResult(pain, nextAnswers);
      setIsExiting(true);
      clearTransition();
      transitionRef.current = window.setTimeout(() => {
        window.location.href = `${pain.slug}/?v=${GATEWAY_ROUTE_VERSION}`;
      }, TRANSITION_MS + 180);
      return;
    }

    clearTransition();
    window.setTimeout(() => scrollToStep(questionIndex + 1), 40);
    transitionRef.current = window.setTimeout(() => {
      setActivePulse(null);
      setIsTransitioning(false);
      setIsHolding(false);
    }, TRANSITION_MS);
  }

  const routePreview = useMemo(() => {
    const pain = PAIN_LANDINGS[visualPain];
    return pain?.short || visual.short;
  }, [visualPain, visual.short]);

  return (
    <main
      className={`gw gw-pain-${visualPain} gw-step-${activeStep + 1} ${isHolding ? 'is-holding' : ''} ${isTransitioning ? 'is-transitioning' : ''} ${isExiting ? 'is-exiting' : ''} ${isReady ? 'is-ready' : 'is-loading'}`}
      onPointerDownCapture={startHold}
      onPointerUpCapture={stopHold}
      onPointerCancelCapture={stopHold}
      onMouseUpCapture={stopHold}
      onTouchStart={startHold}
      onTouchEnd={stopHold}
      onTouchCancel={stopHold}
      onContextMenu={(event) => event.preventDefault()}
    >
      {!isReady && <GatewayLoading progress={loadProgress} />}
      <GatewayMedia
        visualPain={visualPain}
        activeVideoId={activeVideoId}
        isHolding={isHolding}
        videoSources={videoSources}
        videoRefs={videoRefs}
      />
      <GatewayChrome />
      <HoldCue isHolding={isHolding} hasHeld={hasHeld} />
      <GatewaySlideIndicator activeStep={activeStep} onSelect={scrollToStep} />
      <div className="gw-stage" ref={stageRef}>
        {QUESTIONS.map((question, index) => (
          <article
            key={question.label}
            className="gw-slide"
            ref={(node) => {
              if (node) slideRefs.current[index] = node;
            }}
          >
            <div className="gw-context" aria-hidden="true">
              <span>{VISUAL_STATES[index === 0 ? 'neutral' : visualPain].label}</span>
              <strong>{routePreview}</strong>
            </div>
            <GatewayQuestion
              question={question}
              questionIndex={index}
              onPick={pick}
              disabled={isTransitioning}
              selectedText={selectedOptions[index]?.text}
              getHref={index + 1 >= QUESTIONS.length
                ? (option) => `${PAIN_LANDINGS[optionTarget(option)].slug}/?v=${GATEWAY_ROUTE_VERSION}`
                : null}
            />
          </article>
        ))}
      </div>
      {isExiting && (
        <div className="gw-exit" role="status" aria-live="polite">
          <span></span>
          <p>Abriendo tu VSL personalizada</p>
        </div>
      )}
    </main>
  );
}

window.Gateway = Gateway;
