// SIMULADOR LAUNCHER — carga HTML en iframe, gestiona límite de intentos y guarda resultados

window.SimuladorLauncher = function SimuladorLauncher({ navigate, store, pruebaId, modo }) {
  const PRUEBAS    = store.pruebas || window.SD_SEED.PRUEBAS;
  const prueba     = PRUEBAS.find(p => p.id === pruebaId);
  const isCompleto = modo === 'completo';

  // Completo siempre requiere sesión
  if (!store.session && isCompleto) { navigate('/login'); return null; }

  if (!prueba) {
    return (
      <div style={{ padding: 60, textAlign: 'center' }}>
        <h3>Prueba no encontrada</h3>
        <button className="btn btn-ghost" style={{ marginTop: 16 }} onClick={() => navigate('/')}>← Volver</button>
      </div>
    );
  }

  if (isCompleto && !store.hasPremium(pruebaId)) {
    return (
      <div>
        <window.DashHeader navigate={navigate} store={store} />
        <div className="container container-narrow" style={{ paddingTop: 60, paddingBottom: 80 }}>
          <div className="card card-pad-lg" style={{ textAlign: 'center' }}>
            <div style={{ fontSize: 48 }}>{prueba.icono || '🔒'}</div>
            <h2 style={{ marginTop: 16 }}>Simulador completo — acceso premium</h2>
            <p className="muted" style={{ marginTop: 12, fontSize: 15, lineHeight: 1.6 }}>
              Desbloquea <strong>{prueba.nombre}</strong> con un pago único de{' '}
              <strong>{window.formatPrice(prueba.precio || prueba.precio_mxn)}</strong>.
            </p>
            <div className="row gap-3" style={{ justifyContent: 'center', marginTop: 28 }}>
              <button className="btn btn-ghost btn-lg" onClick={() => navigate(`/simulador/${pruebaId}/muestra`)}>
                Probar muestra gratis
              </button>
              <button className="btn btn-amber btn-lg"
                onClick={() => { store.addToCart(pruebaId); navigate('/checkout'); }}>
                ★ Desbloquear · {window.formatPrice(prueba.precio || prueba.precio_mxn)}
              </button>
            </div>
          </div>
        </div>
      </div>
    );
  }

  // Sin sesión → modo diagnóstico anónimo (solo muestra)
  if (!store.session) {
    return <SimuladorAnonimoFrame prueba={prueba} navigate={navigate} />;
  }

  return <SimuladorFrame prueba={prueba} modo={modo} isCompleto={isCompleto} navigate={navigate} store={store} />;
};

// Script de detección de fin de examen para anónimos (inyectado en blob)
// Solo notifica al parent para guardar resultado en localStorage — sin overlay ni timer
function buildAnonDetectScript(pruebaId) {
  return `
<script>
(function(){
  var PID='${pruebaId}';
  function msg(t,ex){window.parent.postMessage(Object.assign({type:t},ex||{}),'*');}

  function notificar(){
    var t=document.body?document.body.innerText||'':'';
    var m=t.match(/(\\d+(?:\\.\\d+)?)\\s*%/);
    msg('sim_anonimo_fin',{pct:m?parseFloat(m[1]):null,pruebaId:PID});
  }
  var notificado=false;
  function unaVez(){
    if(notificado)return; notificado=true; setTimeout(notificar,350);
  }

  function hookMR(){
    if(typeof mostrarResultados==='function'&&!mostrarResultados._sdh){
      mostrarResultados._sdh=true;
      var _o=mostrarResultados;
      mostrarResultados=function(){_o.apply(this,arguments);unaVez();};
      return true;
    }
    return false;
  }
  if(!hookMR()){
    var chk=setInterval(function(){if(hookMR())clearInterval(chk);},500);
    setTimeout(function(){clearInterval(chk);},60000);
  }

  var _p=setInterval(function(){
    if(notificado){clearInterval(_p);return;}
    var t=document.body?document.body.textContent||'':'';
    if(/\\d+\\/\\d+/.test(t)&&/\\d+%/.test(t)){clearInterval(_p);unaVez();}
  },700);
  setTimeout(function(){clearInterval(_p);},300000);
})();
<\/script>`;
}

function injectScript(doc, code) {
  try {
    const s = doc.createElement('script');
    s.textContent = code;
    (doc.head || doc.body).appendChild(s);
  } catch(e) { console.warn('SD inject:', e); }
}

// ── Modo anónimo: carga HTML como blob con detección de fin ──────
function SimuladorAnonimoFrame({ prueba, navigate }) {
  const BASE = window.API_BASE || '/simuladordocente/api';

  const [iframeUrl, setIframeUrl] = React.useState(null);
  const [error,     setError]     = React.useState('');
  const [loading,   setLoading]   = React.useState(true);
  const startRef = React.useRef(Date.now());
  const blobRef  = React.useRef(null);

  React.useEffect(() => {
    fetch(`${BASE}/pruebas/${prueba.id}/url-muestra`)
      .then(r => r.json().then(d => ({ ok: r.ok, d })))
      .then(({ ok, d }) => {
        if (!ok) { setError(d.error || 'No disponible'); setLoading(false); return; }
        return fetch(d.url).then(r => {
          if (!r.ok) throw new Error('Archivo no disponible');
          return r.text().then(html => ({ html, htmlUrl: d.url }));
        });
      })
      .then(result => {
        if (!result) return;
        const { html, htmlUrl } = result;
        const base = htmlUrl.substring(0, htmlUrl.lastIndexOf('/') + 1);
        let modified = html.includes('<base')
          ? html
          : html.replace('<head>', `<head><base href="${base}">`);
        if (!modified.includes('<base')) modified = `<base href="${base}">` + modified;
        // Inyectar script de detección antes de </body>
        const detect = buildAnonDetectScript(prueba.id);
        modified = modified.includes('</body>')
          ? modified.replace('</body>', detect + '</body>')
          : modified + detect;
        const blob = new Blob([modified], { type: 'text/html; charset=utf-8' });
        blobRef.current = URL.createObjectURL(blob);
        startRef.current = Date.now();
        setIframeUrl(blobRef.current);
        setLoading(false);
      })
      .catch(e => { setError(e.message || 'Error de conexión'); setLoading(false); });

    return () => { if (blobRef.current) URL.revokeObjectURL(blobRef.current); };
  }, [prueba.id]);

  // Escuchar mensajes del iframe — guardar resultado en localStorage para recuperarlo al registrarse
  React.useEffect(() => {
    const handler = (e) => {
      if (e.data?.type === 'sim_anonimo_fin') {
        localStorage.setItem('sd_pending_result', JSON.stringify({
          prueba_id:    e.data.pruebaId || prueba.id,
          pct:          e.data.pct ?? null,
          duracion_seg: Math.round((Date.now() - startRef.current) / 1000),
        }));
      }
      if (e.data?.type === 'navigate') navigate(e.data.route);
    };
    window.addEventListener('message', handler);
    return () => window.removeEventListener('message', handler);
  }, []);

  return (
    <div className="simulador-launcher">
      <div className="sim-bar">
        <button className="btn btn-ghost btn-sm" onClick={() => navigate('/')}>← Salir</button>
        <div className="sim-bar-title">
          {prueba.icono} <strong>{prueba.nombre}</strong>
          <span className="pill pill-teal" style={{ marginLeft: 10 }}>Diagnóstico gratuito</span>
        </div>
      </div>

      <div className="sim-frame">
        {loading && (
          <div className="sim-center">
            <div style={{ fontSize: 36 }}>⏳</div>
            <p style={{ marginTop: 12, color: 'var(--muted)' }}>Cargando simulador…</p>
          </div>
        )}
        {!loading && error && (
          <div className="sim-center">
            <div style={{ fontSize: 48 }}>📭</div>
            <h3 style={{ marginTop: 16 }}>Simulador no disponible</h3>
            <p className="muted" style={{ marginTop: 10, fontSize: 14 }}>{error}</p>
            <p className="muted" style={{ fontSize: 13, marginTop: 6 }}>El administrador aún no ha subido el archivo HTML de muestra.</p>
            <button className="btn btn-ghost" style={{ marginTop: 20 }} onClick={() => navigate('/')}>
              ← Volver al inicio
            </button>
          </div>
        )}
        {!loading && !error && iframeUrl && (
          <iframe
            src={iframeUrl}
            title={prueba.nombre}
            className="sim-iframe"
            allow="fullscreen"
          />
        )}
      </div>
    </div>
  );
}

// ── Modo con sesión ───────────────────────────────────────────
function SimuladorFrame({ prueba, modo, isCompleto, navigate, store }) {
  const BASE = window.API_BASE || '/simuladordocente/api';

  const [iframeUrl,    setIframeUrl]    = React.useState(null);
  const [resultadoId,  setResultadoId]  = React.useState(null);
  const [intentosInfo, setIntentosInfo] = React.useState(null);
  const [limiteMsg,    setLimiteMsg]    = React.useState(null);
  const [error,        setError]        = React.useState('');
  const [loading,      setLoading]      = React.useState(true);

  const iframeRef  = React.useRef(null);
  const lsSnapshot = React.useRef({});
  const startTime  = React.useRef(Date.now());
  const savedRef   = React.useRef(null);

  const hasPremium = store.hasPremium(prueba.id);

  // ── 1. Solicitar URL al API ───────────────────────────────
  React.useEffect(() => {
    const tok = localStorage.getItem('sd_token');
    if (!tok) { setLoading(false); return; }

    fetch(`${BASE}/pruebas/${prueba.id}/abrir/${modo}`, {
      headers: { Authorization: `Bearer ${tok}` }
    })
      .then(r => r.json().then(d => ({ ok: r.ok, d })))
      .then(({ ok, d }) => {
        if (!ok) {
          if (d.error === 'limite_alcanzado') setLimiteMsg(d);
          else setError(d.error || 'No se pudo cargar');
        } else {
          setIframeUrl(d.url);
          setResultadoId(d.resultado_id);
          setIntentosInfo({ intentos_usados: d.intentos_usados, limite: d.limite });
          startTime.current = Date.now();
        }
        setLoading(false);
      })
      .catch(() => { setError('Error de conexión'); setLoading(false); });
  }, [prueba.id, modo]);

  // ── 2. Inyectar scripts cuando el iframe carga ────────────
  const onIframeLoad = () => {
    const snap = {};
    for (let i = 0; i < localStorage.length; i++) {
      const k = localStorage.key(i); snap[k] = localStorage.getItem(k);
    }
    lsSnapshot.current = snap;

    const doc = iframeRef.current?.contentDocument;
    if (!doc) return;

    // Script de captura de resultados (siempre)
    injectScript(doc, `(function(){
      function capturar(){
        var ls={};
        for(var i=0;i<localStorage.length;i++){var k=localStorage.key(i);ls[k]=localStorage.getItem(k);}
        var extras={};
        var sub=document.querySelector('.score-sub');
        if(sub){var m=sub.textContent.match(/(\\d+(?:\\.\\d+)?)%/);if(m)extras.pct=parseFloat(m[1]);}
        var big=document.querySelector('.score-big');
        if(big){
          var m2=big.textContent.match(/^(\\d+)/);if(m2)extras.total_aciertos=parseInt(m2[1]);
          var m3=big.textContent.match(/\\/(\\d+)/);if(m3)extras.max_aciertos=parseInt(m3[1]);
        }
        var niv=document.querySelector('.nivel-txt');
        if(niv)extras.nivel_texto=niv.textContent.trim();
        try{
          if(window._examenData&&Array.isArray(window._examenData)){
            extras._examenData=window._examenData.map(function(item){
              return{tipo:item.q&&item.q.d,chosen:item.r&&item.r.chosen,correct:item.r&&item.r.opt&&item.r.opt.l};
            });
          }
        }catch(e){}
        window.parent.postMessage({type:'sim_resultado',datos:ls,extras:extras},'*');
      }
      if(typeof mostrarResultados==='function'){
        var _orig=mostrarResultados;
        mostrarResultados=function(){_orig.apply(this,arguments);setTimeout(capturar,600);};
      }
      window.addEventListener('message',function(e){if(e.data&&e.data.type==='request_capture')capturar();});
      document.addEventListener('click',function(e){
        var txt=(e.target.textContent||e.target.innerText||'').toLowerCase();
        if(/finaliz|termina|resultado|calific|ver res|guardar|submit|finish/i.test(txt))setTimeout(capturar,900);
      },true);
      window.addEventListener('beforeunload',capturar);

      var _scored=false;
      var _poll=setInterval(function(){
        if(_scored){clearInterval(_poll);return;}
        var t=document.body?document.body.textContent||'':'';
        if(/\\d+\\/\\d+/.test(t)&&/\\d+%/.test(t)){
          _scored=true;clearInterval(_poll);setTimeout(capturar,600);
        }
      },800);
      setTimeout(function(){clearInterval(_poll);},600000);
    })();`);

    // Muestra sin premium: interceptar botón de compra del HTML
    if (!isCompleto && !hasPremium) {
      injectScript(doc, `(function(){
        function trap(){
          document.querySelectorAll('button,a,[role=button]').forEach(function(el){
            if(el._sc)return;
            var t=(el.textContent||el.innerText||'').toLowerCase();
            if(/quiero|compra|adquir|desbloquea|\\$15|pagar|completo/i.test(t)){
              el._sc=true;
              el.addEventListener('click',function(e){
                e.preventDefault();e.stopImmediatePropagation();
                window.parent.postMessage({type:'goto_checkout'},'*');
              },true);
            }
          });
        }
        trap();
        new MutationObserver(trap).observe(document.body,{childList:true,subtree:true});
      })();`);
    }
  };

  // ── 3. Listeners de mensajes del iframe ──────────────────
  React.useEffect(() => {
    if (!iframeUrl) return;
    const handler = () => {
      iframeRef.current?.contentWindow?.postMessage({ type: 'request_capture' }, '*');
    };
    window.addEventListener('storage', handler);
    return () => window.removeEventListener('storage', handler);
  }, [iframeUrl]);

  React.useEffect(() => {
    const handler = (e) => {
      if (e.data?.type === 'sim_resultado') {
        guardarResultado(e.data.datos, e.data.extras);
      }
      if (e.data?.type === 'goto_checkout' && !isCompleto && !hasPremium) {
        store.addToCart(prueba.id);
        navigate('/checkout');
      }
    };
    window.addEventListener('message', handler);
    return () => window.removeEventListener('message', handler);
  }, [resultadoId, isCompleto, hasPremium]);

  // ── 4. Guardar resultado ──────────────────────────────────
  const guardarResultado = React.useCallback((datosIframe, extras) => {
    if (!resultadoId) return;
    const hasScore = extras?.pct != null;
    if (savedRef.current === 'withScore') return;
    if (savedRef.current === 'noScore' && !hasScore) return;

    const tok = localStorage.getItem('sd_token');
    if (!tok) return;

    const changed = {};
    if (datosIframe) {
      Object.keys(datosIframe).forEach(k => {
        if (lsSnapshot.current[k] !== datosIframe[k]) changed[k] = datosIframe[k];
      });
    }
    if (extras && Object.keys(extras).length) changed._sim_extras = extras;

    const calificacion = hasScore ? parseFloat(extras.pct) : null;

    fetch(`${BASE}/resultados/${resultadoId}`, {
      method: 'PUT',
      headers: { Authorization: `Bearer ${tok}`, 'Content-Type': 'application/json' },
      body: JSON.stringify({
        calificacion,
        datos:        Object.keys(changed).length ? changed : null,
        duracion_seg: Math.round((Date.now() - startTime.current) / 1000),
      }),
    }).catch(() => {});

    savedRef.current = calificacion !== null ? 'withScore' : 'noScore';
  }, [resultadoId]);

  const salir = () => {
    if (savedRef.current !== 'withScore' && resultadoId) {
      const tok = localStorage.getItem('sd_token');
      if (tok) {
        fetch(`${BASE}/resultados/${resultadoId}`, {
          method: 'PUT',
          headers: { Authorization: `Bearer ${tok}`, 'Content-Type': 'application/json' },
          body: JSON.stringify({ duracion_seg: Math.round((Date.now() - startTime.current) / 1000) }),
          keepalive: true,
        }).catch(() => {});
      }
    }
    navigate('/dashboard');
  };

  if (limiteMsg) {
    return (
      <div>
        <window.DashHeader navigate={navigate} store={store} />
        <div className="container container-narrow" style={{ paddingTop: 60, paddingBottom: 80 }}>
          <div className="card card-pad-lg" style={{ textAlign: 'center' }}>
            <div style={{ fontSize: 48 }}>🔒</div>
            <h2 style={{ marginTop: 16 }}>Has usado todos tus intentos gratuitos</h2>
            <p className="muted" style={{ marginTop: 12, fontSize: 15, lineHeight: 1.6 }}>
              Usaste tus <strong>{limiteMsg.limite} intentos</strong> de muestra para{' '}
              <strong>{prueba.nombre}</strong>. Desbloquea el simulador completo para intentos ilimitados.
            </p>
            <div style={{ display:'flex', gap:6, justifyContent:'center', margin:'24px auto', maxWidth:200 }}>
              {Array.from({length: limiteMsg.limite}).map((_,i) => (
                <div key={i} style={{ flex:1, height:10, borderRadius:5, background:'var(--teal)' }}/>
              ))}
            </div>
            <div className="row gap-3" style={{ justifyContent: 'center', marginTop: 8 }}>
              <button className="btn btn-ghost btn-lg" onClick={() => navigate('/dashboard')}>
                ← Volver al panel
              </button>
              <button className="btn btn-amber btn-lg"
                onClick={() => { store.addToCart(prueba.id); navigate('/checkout'); }}>
                ★ Desbloquear · {window.formatPrice(prueba.precio || prueba.precio_mxn)}
              </button>
            </div>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="simulador-launcher">
      <div className="sim-bar">
        <button className="btn btn-ghost btn-sm" onClick={salir}>← Salir</button>
        <div className="sim-bar-title">
          {prueba.icono} <strong>{prueba.nombre}</strong>
          {isCompleto
            ? <span className="pill pill-amber" style={{ marginLeft: 10 }}>★ Completo</span>
            : <span className="pill pill-teal"  style={{ marginLeft: 10 }}>Muestra</span>}
        </div>
        <div style={{ fontSize: 12, color: 'rgba(255,255,255,0.6)' }}>
          {isCompleto
            ? 'Intentos ilimitados ★'
            : intentosInfo?.limite
              ? `${intentosInfo.intentos_usados}/${intentosInfo.limite} intentos muestra`
              : ''}
        </div>
      </div>

      <div className="sim-frame">
        {loading && (
          <div className="sim-center">
            <div style={{ fontSize: 36 }}>⏳</div>
            <p style={{ marginTop: 12, color: 'var(--muted)' }}>Cargando simulador…</p>
          </div>
        )}
        {!loading && error && (
          <div className="sim-center">
            <div style={{ fontSize: 48 }}>📭</div>
            <h3 style={{ marginTop: 16 }}>Simulador no disponible</h3>
            <p className="muted" style={{ marginTop: 10, fontSize: 14 }}>{error}</p>
            <p className="muted" style={{ fontSize: 13, marginTop: 6 }}>El administrador aún no ha subido el archivo HTML.</p>
            <button className="btn btn-ghost" style={{ marginTop: 20 }} onClick={() => navigate('/dashboard')}>
              ← Volver al panel
            </button>
          </div>
        )}
        {!loading && !error && iframeUrl && (
          <iframe
            ref={iframeRef}
            src={iframeUrl}
            title={prueba.nombre}
            className="sim-iframe"
            allow="fullscreen"
            onLoad={onIframeLoad}
          />
        )}
        {!loading && !error && !iframeUrl && (
          <div className="sim-center">
            <div className="sim-mock">
              <div style={{ fontSize: 48 }}>📝</div>
              <h3 style={{ marginTop: 12 }}>Modo demo</h3>
              <p className="muted" style={{ marginTop: 10, fontSize: 14 }}>
                Inicia sesión con una cuenta real para abrir el simulador.
              </p>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
