// === Main app: navigation, stage, keyboard ===
// Presentación definitiva — "Un día entero. Una plataforma."

const SLIDES = [
  // APERTURA
  { title:'Portada',                  comp: ()=> Slide01,           dur:6 },
  { title:'Siete ventanas',           comp: ()=> SlideCaos,         dur:10 },
  { title:'Un solo motor',            comp: ()=> SlideMotor,        dur:11 },

  // EL DÍA — mañana operativa
  { title:'08:30 · Ponerse al día',   comp: ()=> SlideHome,         dur:13 },
  { title:'09:04 · Facturas',         comp: ()=> SlideFacturas,     dur:13 },
  { title:'09:36 · Banco',            comp: ()=> SlideBanco,        dur:14 },
  { title:'10:00 · Contabilidad',     comp: ()=> SlideContabilidad, dur:12 },

  // EL DÍA — venta y local
  { title:'11:30 · Ficha 360°',       comp: ()=> SlideFicha360,     dur:13 },
  { title:'12:15 · Pipeline',         comp: ()=> SlidePipeline,     dur:14 },
  { title:'13:05 · El local',         comp: ()=> SlideTpv,          dur:14 },

  // EL DÍA — inteligencia y plataforma
  { title:'16:20 · Yudo',             comp: ()=> SlideYudo,         dur:15 },
  { title:'16:40 · Tu agente',        comp: ()=> SlideAgente,       dur:17 },
  { title:'Por qué importa',          comp: ()=> SlideAgenteExplainer, dur:11 },
  { title:'17:00 · El equipo',        comp: ()=> SlideEquipo,       dur:13 },
  { title:'19:42 · El trimestre',     comp: ()=> SlideTrimestre,    dur:12 },

  // DINAUP FLEX — el antes y el después
  { title:'¿Y tu negocio?',           comp: ()=> SlideFlexPregunta, dur:8, stop:true },
  { title:'El Excel de siempre',      comp: ()=> SlideFlexExcel,    dur:14 },
  { title:'Flex · El lienzo',         comp: ()=> SlideFlexLienzo,   dur:18 },
  { title:'Caso · Minigolf',          comp: ()=> SlideFlexMinigolf, dur:15 },
  { title:'Caso · Autodesguaces',     comp: ()=> SlideFlexDesguace, dur:15 },
  { title:'Caso · Drivioon',          comp: ()=> SlideFlexDrivioon, dur:15 },
  { title:'El listado',               comp: ()=> SlideFlexListado,  dur:16 },
  { title:'Replicado en tiempo real', comp: ()=> SlideFlexReplica,  dur:12 },
  { title:'Tu IA lo entiende',        comp: ()=> SlideFlexIAGlobal, dur:13 },

  // PARA QUIEN CONSTRUYE — bloque técnico
  { title:'API · Para quien construye', comp: ()=> SlideApi,        dur:13 },
  { title:'Una historia real',        comp: ()=> SlideBackendHistoria, dur:11, stop:true },
  { title:'Caso · Backend + IA',      comp: ()=> SlideBackend,      dur:13 },

  // CIERRE
  { title:'Lo que acabas de ver',     comp: ()=> SlideResumen,      dur:9 },
  { title:'Te acompañamos',           comp: ()=> SlideSoporte,      dur:12 },
  { title:'Cierre',                   comp: ()=> SlideCierre,       dur:8 },
];

const STAGE_H = 1080;
const STAGE_W_FULL = 1920; // lienzo interno fijo

const ASPECT_PRESETS = {
  '16:9': 1920,
  '4:3':  1440,
  '1:1':  1080,
  '4:5':   864,
  '9:16':  608,
};

function getAspectW(ratio){
  return ASPECT_PRESETS[ratio] || 1920;
}

function useScale(stageW){
  const [scale, setScale] = React.useState(1);
  React.useEffect(()=>{
    const calc = () => {
      const sx = window.innerWidth / stageW;
      const sy = window.innerHeight / STAGE_H;
      setScale(Math.min(sx, sy));
    };
    calc();
    window.addEventListener('resize', calc);
    return ()=> window.removeEventListener('resize', calc);
  }, [stageW]);
  return scale;
}

function SlideHost({ slideIdx, onSlideEnd }){
  const slide = SLIDES[slideIdx];
  const SlideComp = slide.comp();
  const [resetKey, setResetKey] = React.useState(0);
  const [playing, setPlaying] = React.useState(true);
  const [progress, setProgress] = React.useState(0);
  const endedRef = React.useRef(false);

  React.useEffect(()=>{
    setResetKey(k => k+1);
    setProgress(0);
    endedRef.current = false;
  }, [slideIdx]);

  React.useEffect(()=>{
    window.__setPlaying = setPlaying;
    window.__progress = progress;
  });

  const handleProgress = React.useCallback((p)=>{
    setProgress(p);
    if (p >= 1 && endedRef.current === false) {
      endedRef.current = true;
      if (onSlideEnd) onSlideEnd();
    }
  }, [onSlideEnd]);

  return (
    // key={slideIdx}: remonta el Stage EN EL MISMO RENDER en que cambia el slide.
    // Sin él, el slide nuevo se pintaba 1-2 frames con el reloj del anterior
    // (t alto) antes de que el efecto reseteara — el "flash" entre diapositivas.
    <Stage key={slideIdx} duration={slide.dur} playing={playing} resetKey={resetKey} onProgress={handleProgress}>
      <InnerSlide SlideComp={SlideComp}/>
      <ProgressMirror progress={progress}/>
    </Stage>
  );
}

function InnerSlide({ SlideComp }){
  const t = useTime();
  return <SlideComp t={t}/>;
}

function ProgressMirror({ progress }){
  React.useEffect(()=>{
    const el = document.getElementById('progress-inner');
    if (el) el.style.width = `${Math.min(100, progress*100)}%`;
  }, [progress]);
  return null;
}

function App(){
  const [aspectRatio, setAspectRatio] = React.useState(()=> (window.__TWEAKS && window.__TWEAKS.aspectRatio) || '16:9');
  const stageW = getAspectW(aspectRatio);
  const scale = useScale(stageW);
  const cropOffset = (STAGE_W_FULL - stageW) / 2;

  const [slide, setSlide] = React.useState(()=>{
    const saved = parseInt(localStorage.getItem('definitiva-deck:slide') || '0', 10);
    return isNaN(saved) ? 0 : clamp(saved, 0, SLIDES.length-1);
  });
  const [showOverview, setShowOverview] = React.useState(false);
  const [navVisible, setNavVisible] = React.useState(true);
  const [playing, setPlaying] = React.useState(true);
  const [transitionKey, setTransitionKey] = React.useState(0);
  const [entering, setEntering] = React.useState(false);
  const [editMode, setEditMode] = React.useState(false);
  const hideTimer = React.useRef();

  // Protocolo edit mode — registrar listener antes de anunciar
  React.useEffect(()=>{
    const onMsg = (e) => {
      if (!e.data || typeof e.data !== 'object') return;
      if (e.data.type === '__activate_edit_mode') setEditMode(true);
      else if (e.data.type === '__deactivate_edit_mode') setEditMode(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({type:'__edit_mode_available'}, '*');
    return ()=> window.removeEventListener('message', onMsg);
  }, []);

  const updateTweak = React.useCallback((key, value)=>{
    if (key === 'aspectRatio') setAspectRatio(value);
    window.parent.postMessage({type:'__edit_mode_set_keys', edits:{[key]: value}}, '*');
  }, []);

  React.useEffect(()=>{
    localStorage.setItem('definitiva-deck:slide', String(slide));
    setTransitionKey(k=>k+1);
    setEntering(true);
    const id = setTimeout(()=>setEntering(false), 600);
    return ()=>clearTimeout(id);
  }, [slide]);

  const advanceTimer = React.useRef();

  const go = React.useCallback((n)=>{
    clearTimeout(advanceTimer.current);
    setPlaying(true); // salir de una pausa de reflexión reanuda la reproducción
    setSlide(clamp(n, 0, SLIDES.length-1));
  }, []);

  // Selector de ritmo: 0.5× (pausado) · 1× · 2× (rápido)
  const [speed, setSpeed] = React.useState(()=>{
    const saved = parseFloat(localStorage.getItem('definitiva-deck:speed') || '1');
    return [0.5, 1, 2].includes(saved) ? saved : 1;
  });
  React.useEffect(()=>{
    window.__deckSpeed = speed;
    localStorage.setItem('definitiva-deck:speed', String(speed));
  }, [speed]);

  // Autoplay: al agotar la duración del slide, avanza solo tras un pequeño hold.
  // Se desactiva con window.__TWEAKS.autoAdvance = false. No dispara en el último
  // slide ni cuando las tools de QA fuerzan el final con __deckSeekEnd.
  // Los slides con stop:true NO avanzan solos: pausan y esperan al presentador
  // (son las pausas de reflexión — se sale con → o Espacio).
  const handleSlideEnd = React.useCallback(()=>{
    const enabled = !(window.__TWEAKS && window.__TWEAKS.autoAdvance === false);
    if (!enabled) return;
    setSlide(s => {
      if (SLIDES[s] && SLIDES[s].stop) { setPlaying(false); return s; }
      clearTimeout(advanceTimer.current);
      advanceTimer.current = setTimeout(()=>{
        setSlide(x => (x < SLIDES.length-1 ? x+1 : x));
      }, 800);
      return s;
    });
  }, []);

  React.useEffect(()=>{
    if (playing === false) clearTimeout(advanceTimer.current);
  }, [playing]);

  React.useEffect(()=> ()=> clearTimeout(advanceTimer.current), []);

  React.useEffect(()=>{
    window.__deckGoTo = (n) => { clearTimeout(advanceTimer.current); setSlide(clamp(n, 0, SLIDES.length-1)); };
    window.__deckSlideCount = SLIDES.length;
    window.__deckTitles = SLIDES.map(s => s.title);
    window.__deckSeekEnd = () => {
      clearTimeout(advanceTimer.current);
      const ev = new CustomEvent('__deckSeekEnd');
      window.dispatchEvent(ev);
    };
  }, []);

  React.useEffect(()=>{
    const onKey = (e) => {
      if (e.key === 'ArrowRight' || e.key === 'PageDown') { go(slide+1); e.preventDefault(); }
      else if (e.key === 'ArrowLeft' || e.key === 'PageUp') { go(slide-1); e.preventDefault(); }
      else if (e.key === ' ') { setPlaying(p=>!p); e.preventDefault(); }
      else if (e.key === 'Escape') { setShowOverview(s=>!s); }
      else if (e.key === 'f' || e.key === 'F') {
        if (document.fullscreenElement) document.exitFullscreen();
        else document.documentElement.requestFullscreen();
      }
      else if (/^[1-9]$/.test(e.key)) { go(parseInt(e.key,10)-1); }
      else if (e.key === '0') { go(9); }
    };
    window.addEventListener('keydown', onKey);
    return ()=> window.removeEventListener('keydown', onKey);
  }, [slide, go]);

  React.useEffect(()=>{
    const onMove = () => {
      setNavVisible(true);
      clearTimeout(hideTimer.current);
      hideTimer.current = setTimeout(()=>setNavVisible(false), 2400);
    };
    window.addEventListener('mousemove', onMove);
    onMove();
    return ()=> { window.removeEventListener('mousemove', onMove); clearTimeout(hideTimer.current); };
  }, []);

  React.useEffect(()=>{
    window.__setPlaying && window.__setPlaying(playing);
  }, [playing]);

  const enterP = entering ? 0 : 1;

  return (
    <div>
      <div className="stage-wrap">
        <div style={{position:'relative',width:stageW,height:STAGE_H,flexShrink:0,transform:`scale(${scale})`,transformOrigin:'center center',overflow:'hidden',background:'#fff',boxShadow:'0 40px 120px rgba(0,133,255,0.18), 0 8px 30px rgba(15,23,42,0.06)', opacity: enterP, transition:'opacity 600ms cubic-bezier(0.22,1,0.36,1)'}}>
          <div className="stage" style={{position:'absolute',left:-cropOffset,top:0,width:STAGE_W_FULL,height:STAGE_H,background:'#fff',boxShadow:'none'}}>
            <div key={transitionKey} style={{position:'absolute',inset:0,transform: entering ? 'translateY(28px) scale(0.985)' : 'translateY(0) scale(1)', transition:'transform 600ms cubic-bezier(0.22,1,0.36,1)'}}>
              <SlideHost slideIdx={slide} onSlideEnd={handleSlideEnd}/>
            </div>
          </div>
        </div>
      </div>

      <div className="progress-outer"><div id="progress-inner" className="progress-inner" style={{width:0}}/></div>

      <div className="nav" style={{opacity:navVisible?1:0,pointerEvents:navVisible?'auto':'none'}}>
        <button onClick={()=>go(slide-1)} title="Anterior (←)">
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M9 3 L4 7 L9 11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
        </button>
        <button onClick={()=>setPlaying(p=>!p)} title="Play/Pausa (Espacio)">
          {playing ? (
            <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><rect x="2" y="2" width="3" height="8" fill="currentColor"/><rect x="7" y="2" width="3" height="8" fill="currentColor"/></svg>
          ) : (
            <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><polygon points="3,2 10,6 3,10" fill="currentColor"/></svg>
          )}
        </button>
        <button onClick={()=>go(slide+1)} title="Siguiente (→)">
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M5 3 L10 7 L5 11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
        </button>
        <div className="count">{String(slide+1).padStart(2,'0')} / {String(SLIDES.length).padStart(2,'0')}</div>
        {[0.5,1,2].map(v => (
          <button key={v} onClick={()=>setSpeed(v)} title={`Ritmo ${v}×`} style={{
            fontFamily:"'JetBrains Mono',monospace", fontSize:10, fontWeight:700, width:'auto', padding:'0 8px',
            color: speed===v ? '#fff' : undefined,
            background: speed===v ? 'rgba(0,133,255,0.85)' : undefined,
          }}>{String(v).replace('0.5','½')}×</button>
        ))}
        <button onClick={()=>setShowOverview(true)} title="Vista general (ESC)">
          <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><rect x="1" y="1" width="4" height="4" fill="currentColor"/><rect x="7" y="1" width="4" height="4" fill="currentColor"/><rect x="1" y="7" width="4" height="4" fill="currentColor"/><rect x="7" y="7" width="4" height="4" fill="currentColor"/></svg>
        </button>
      </div>

      <div className="slide-idx">{String(slide+1).padStart(2,'0')} · {SLIDES[slide].title.toUpperCase()}</div>
      <div className="hint">← → NAVEGAR · ESPACIO PAUSA · ESC VISTA · F PANTALLA COMPLETA</div>

      {showOverview && (
        <div className="overview" onClick={(e)=>{ if(e.target.classList.contains('overview')) setShowOverview(false); }}>
          {SLIDES.map((s,i)=>(
            <div key={i} className="ov-thumb" onClick={()=>{ go(i); setShowOverview(false); }}>
              <div className="ov-title">{s.title}</div>
              <div style={{position:'absolute',inset:0,background: i===slide ? 'rgba(0,133,255,0.08)' : 'linear-gradient(135deg,#F8FAFC,#F0F7FF)', display:'flex',alignItems:'center',justifyContent:'center',fontFamily:"'IBM Plex Sans',sans-serif",fontSize:48,fontWeight:800,color:'rgba(0,133,255,0.15)'}}>{String(i+1).padStart(2,'0')}</div>
              <div className="ov-label">{String(i+1).padStart(2,'0')} · {s.dur}s</div>
            </div>
          ))}
        </div>
      )}

      {editMode && (
        <TweaksPanel aspectRatio={aspectRatio} onChange={updateTweak}/>
      )}
    </div>
  );
}

function TweaksPanel({ aspectRatio, onChange }){
  const presets = [
    { id:'16:9', label:'16:9',  sub:'Desktop · YouTube', w:64, h:36 },
    { id:'4:3',  label:'4:3',   sub:'Clásico',           w:56, h:42 },
    { id:'1:1',  label:'1:1',   sub:'Instagram feed',    w:48, h:48 },
    { id:'4:5',  label:'4:5',   sub:'Instagram vert.',   w:40, h:50 },
    { id:'9:16', label:'9:16',  sub:'Stories · Reels',   w:28, h:50 },
  ];
  return (
    <div style={{
      position:'fixed', right:24, top:24, zIndex:100, width:260,
      background:'rgba(14,18,28,0.92)', backdropFilter:'blur(18px)',
      border:'1px solid rgba(255,255,255,0.08)', borderRadius:14,
      padding:'16px 16px 14px', boxShadow:'0 20px 60px rgba(0,0,0,0.5)',
      color:'#fff', fontFamily:"'IBM Plex Sans',sans-serif",
    }}>
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:12}}>
        <div style={{fontSize:13,fontWeight:700,letterSpacing:0.3}}>Tweaks</div>
        <div style={{fontSize:10,color:'rgba(255,255,255,0.4)',fontFamily:"'JetBrains Mono',monospace",letterSpacing:1}}>FORMATO</div>
      </div>
      <div style={{fontSize:11,color:'rgba(255,255,255,0.55)',marginBottom:10,lineHeight:1.35}}>
        Recorta el ancho para adaptarlo a formatos verticales. La altura se mantiene fija.
      </div>
      <div style={{display:'flex',flexDirection:'column',gap:6}}>
        {presets.map(p => {
          const active = p.id === aspectRatio;
          return (
            <button key={p.id} onClick={()=>onChange('aspectRatio', p.id)} style={{
              display:'flex',alignItems:'center',gap:12,padding:'8px 10px',
              background: active ? 'rgba(0,133,255,0.18)' : 'rgba(255,255,255,0.04)',
              border:`1px solid ${active ? 'rgba(0,133,255,0.5)' : 'rgba(255,255,255,0.08)'}`,
              borderRadius:10, color:'#fff', cursor:'pointer', fontFamily:'inherit', textAlign:'left',
              transition:'all 150ms',
            }}>
              <div style={{width:56,height:52,display:'flex',alignItems:'center',justifyContent:'center',flexShrink:0}}>
                <div style={{width:p.w,height:p.h,background: active ? 'linear-gradient(135deg,#0085FF,#56E16A)' : 'rgba(255,255,255,0.15)',borderRadius:3,transition:'all 150ms'}}/>
              </div>
              <div style={{flex:1,minWidth:0}}>
                <div style={{fontSize:13,fontWeight:700,letterSpacing:0.2}}>{p.label}</div>
                <div style={{fontSize:10,color:'rgba(255,255,255,0.5)',marginTop:1}}>{p.sub}</div>
              </div>
              {active && (
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" style={{flexShrink:0}}>
                  <path d="M4 12 L10 18 L20 6" stroke="#56E16A" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"/>
                </svg>
              )}
            </button>
          );
        })}
      </div>
      <div style={{marginTop:12,paddingTop:10,borderTop:'1px solid rgba(255,255,255,0.08)',fontSize:10,color:'rgba(255,255,255,0.45)',fontFamily:"'JetBrains Mono',monospace",letterSpacing:0.5}}>
        {getAspectW(aspectRatio)} × {STAGE_H} px
      </div>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
