/* global React, DATA, Icon, ExtraIcons, Card, Badge, Button, Avatar, StatePill, PageHeader, Tabs, Modal, ProgressBar, useOnScreen */
const { useState, useRef } = React;

// ============================================================================
// 04 · WORKFLOWS (catálogo + detalle)
// ============================================================================
const WF_LIST = [
  {id:'WF-ALT', n:'Alta de paciente',           cat:'Onboarding',  est:'Activo',  ejec:'248', tasa:'98%', tiempo:'6 min',  desc:'Crea el caso, solicita datos mínimos y llama a HIS para traer historia clínica si existe.'},
  {id:'WF-REC', n:'Validación de receta',       cat:'Clínico',     est:'Activo',  ejec:'312', tasa:'96%', tiempo:'2 min',  desc:'Valida receta contra vademécum, firma profesional, vigencia y compatibilidad con financiador.'},
  {id:'WF-ADH', n:'Seguimiento de adherencia',  cat:'Adherencia',  est:'Activo',  ejec:'86',  tasa:'78%', tiempo:'3 días', desc:'Detecta gaps > 7d, inicia recontacto omnicanal y escala a humano si requiere intervención clínica.'},
  {id:'WF-DIS', n:'Dispensa + remito',          cat:'Operación',   est:'Activo',  ejec:'218', tasa:'99%', tiempo:'90 seg', desc:'Registra dispensa, genera remito, actualiza stock y notifica al paciente por WhatsApp.'},
  {id:'WF-DOC', n:'Consolidación documental',   cat:'Documental',  est:'Activo',  ejec:'164', tasa:'92%', tiempo:'4 min',  desc:'Reúne receta + autorización + remito, los valida vs padrón y arma el legajo digital.'},
  {id:'WF-FIN', n:'Validación económica',       cat:'Económico',   est:'Activo',  ejec:'156', tasa:'88%', tiempo:'3 min',  desc:'Compara precio y bonificación contra reglas del financiador; marca diferencias para revisión.'},
  {id:'WF-FAC', n:'Armado de legajo facturable',cat:'Facturación', est:'Activo',  ejec:'134', tasa:'95%', tiempo:'5 min',  desc:'Cierra el legajo cuando toda la documentación está completa y lo envía al pipeline de facturación.'},
  {id:'WF-ESC', n:'Escalamiento a humano',      cat:'Interno',     est:'Activo',  ejec:'54',  tasa:'—',   tiempo:'inst.',  desc:'Detecta ambigüedad o reglas incumplidas y asigna el caso al responsable correcto.'},
  {id:'WF-REN', n:'Renovación de autorización', cat:'Económico',   est:'Activo',  ejec:'42',  tasa:'90%', tiempo:'1 día',  desc:'Detecta autorizaciones por vencer y dispara proceso de renovación con el financiador.'},
  {id:'WF-LAB', n:'Ingesta de laboratorios',    cat:'Clínico',     est:'Activo',  ejec:'198', tasa:'97%', tiempo:'30 seg', desc:'Incorpora resultados de lab al HIS, compara con objetivos terapéuticos y marca outliers.'},
];
const CAT_COLORS = {
  'Onboarding':'helios','Clínico':'teal2','Adherencia':'danger','Operación':'sun','Documental':'helios',
  'Económico':'slate','Facturación':'ok','Interno':'warn'
};

function WorkflowsPage({go}) {
  const [cat, setCat] = useState('Todos');
  const [q, setQ] = useState('');
  const cats = ['Todos','Onboarding','Clínico','Adherencia','Operación','Documental','Económico','Facturación','Interno'];
  const list = WF_LIST.filter(w => (cat==='Todos'||w.cat===cat) && (!q || (w.n+w.id+w.desc).toLowerCase().includes(q.toLowerCase())));

  return <div className="px-7 py-6 max-w-[1480px]">
    <PageHeader titulo="Workflows automatizados"
      subtitulo="10 workflows activos · 1.612 ejecuciones hoy · 94,5% sin escalamiento"
      action={<Button variant="primary" size="sm" icon={<Icon.plus c="w-3.5 h-3.5"/>}>Nuevo workflow</Button>}/>

    <div className="grid grid-cols-4 gap-3 mb-5">
      <Kpi l="Ejecuciones hoy" v="1.612" sub="↑ 4% vs ayer"/>
      <Kpi l="Resolución automática" v="94,5%" sub="sin escalamiento" tone="ok"/>
      <Kpi l="Tiempo medio" v="3m 42s" sub="de inicio a cierre"/>
      <Kpi l="Escaladas a humano" v="89" sub="5,5% del total" tone="warn"/>
    </div>

    <div className="flex items-center gap-2 mb-4 flex-wrap">
      <div className="relative">
        <Icon.search c="w-3.5 h-3.5 absolute left-2.5 top-1/2 -translate-y-1/2 text-ink-400"/>
        <input value={q} onChange={e=>setQ(e.target.value)} placeholder="Buscar workflow…"
          className="pl-8 pr-3 py-1.5 text-[12px] bg-white border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-helios-400/50 w-64"/>
      </div>
      <div className="flex gap-1 flex-wrap">
        {cats.map(c => <button key={c} onClick={()=>setCat(c)}
          className={'px-2.5 py-1 rounded-lg text-[11.5px] font-medium '+(cat===c?'bg-helios-50 text-helios-700 ring-1 ring-helios-200':'bg-white text-ink-500 hover:bg-slate-50 ring-1 ring-slate-200')}>{c}</button>)}
      </div>
    </div>

    <div className="grid grid-cols-2 gap-3">
      {list.map(w => <button key={w.id} onClick={()=>go('workflow',w.id)}
        className="text-left bg-white rounded-2xl border border-slate-100 p-4 hover:-translate-y-0.5 hover:shadow-md transition-all group"
        style={{boxShadow:'0 1px 2px rgba(15,23,42,0.04)'}}>
        <div className="flex items-start gap-3">
          <div className="w-11 h-11 rounded-xl bg-helios-50 text-helios-700 flex items-center justify-center shrink-0"><ExtraIcons.zap c="w-5 h-5"/></div>
          <div className="flex-1 min-w-0">
            <div className="flex items-center gap-2">
              <span className="font-mono text-[10.5px] text-ink-400 font-semibold">{w.id}</span>
              <Badge tone={CAT_COLORS[w.cat]||'slate'} size="sm">{w.cat}</Badge>
              <Badge tone="ok" size="sm" dot>{w.est}</Badge>
            </div>
            <h3 className="font-display font-semibold text-ink-800 text-[15px] mt-1 group-hover:text-helios-700">{w.n}</h3>
            <p className="text-[11.5px] text-ink-500 mt-1 leading-snug">{w.desc}</p>
          </div>
        </div>
        <div className="grid grid-cols-3 gap-2 mt-3 pt-3 border-t border-slate-100">
          <Mini l="Ejec. hoy" v={w.ejec}/>
          <Mini l="Éxito" v={w.tasa}/>
          <Mini l="Tiempo medio" v={w.tiempo}/>
        </div>
      </button>)}
    </div>
  </div>;
}

function WorkflowDetailPage({id='WF-ADH', go}) {
  const w = WF_LIST.find(x=>x.id===id) || WF_LIST[2];
  const [tab, setTab] = useState('diagrama');

  return <div className="px-7 py-6 max-w-[1480px]">
    <button onClick={()=>go('workflows')} className="flex items-center gap-1 text-[12px] text-ink-400 hover:text-ink-700 mb-3">
      <Icon.chevR c="w-3.5 h-3.5 rotate-180"/> Workflows
    </button>

    <div className="bg-white rounded-2xl border border-slate-100 p-5 mb-4" style={{boxShadow:'0 1px 2px rgba(15,23,42,0.04)'}}>
      <div className="flex items-start gap-4">
        <div className="w-14 h-14 rounded-2xl bg-helios-50 text-helios-700 flex items-center justify-center shrink-0"><ExtraIcons.zap c="w-7 h-7"/></div>
        <div className="flex-1">
          <div className="flex items-center gap-2 flex-wrap">
            <span className="font-mono text-[11px] text-ink-400 font-semibold">{w.id}</span>
            <Badge tone={CAT_COLORS[w.cat]} size="sm">{w.cat}</Badge>
            <Badge tone="ok" size="sm" dot>{w.est} · versión 3.2</Badge>
          </div>
          <h1 className="text-[22px] font-display font-extrabold text-ink-800 mt-1">{w.n}</h1>
          <p className="text-[12.5px] text-ink-500 mt-1 max-w-3xl">{w.desc}</p>
        </div>
        <div className="flex gap-2">
          <Button variant="outline" size="sm">Pausar</Button>
          <Button variant="outline" size="sm">Duplicar</Button>
          <Button variant="primary" size="sm">Editar</Button>
        </div>
      </div>
      <div className="grid grid-cols-5 gap-3 mt-4">
        <Kpi l="Ejecuciones hoy" v={w.ejec}/>
        <Kpi l="Resolución auto" v={w.tasa} tone="ok"/>
        <Kpi l="Tiempo medio" v={w.tiempo}/>
        <Kpi l="Escaladas" v="14" sub="16% del total" tone="warn"/>
        <Kpi l="Casos en curso" v="23"/>
      </div>
    </div>

    <div className="bg-white rounded-t-2xl border border-slate-100 border-b-0">
      <Tabs tabs={[{key:'diagrama',label:'Diagrama'},{key:'reglas',label:'Reglas y condiciones'},{key:'exec',label:'Ejecuciones recientes'},{key:'metricas',label:'Métricas'}]} active={tab} onChange={setTab}/>
    </div>
    <div className="bg-white rounded-b-2xl border border-slate-100 p-5" style={{boxShadow:'0 1px 2px rgba(15,23,42,0.04)'}}>
      {tab==='diagrama' && <WFDiagram/>}
      {tab==='reglas'   && <WFReglas/>}
      {tab==='exec'     && <WFExec go={go}/>}
      {tab==='metricas' && <WFMetricas/>}
    </div>
  </div>;
}

// Design-system-coherent node palette
const NODE_TYPES = {
  trigger:  {label:'TRIGGER',   fg:'#B93535', bg:'#FBE8E8', dot:'#E04B4B', icon:'⚡'},
  accion:   {label:'ACCIÓN',    fg:'#1B7690', bg:'#E6F1F5', dot:'#1B7690', icon:'▸'},
  ia:       {label:'IA',        fg:'#7B3FA0', bg:'#F0E6F5', dot:'#7B3FA0', icon:'✶'},
  decision: {label:'DECISIÓN',  fg:'#A06A12', bg:'#FDF0D9', dot:'#D28513', icon:'◆'},
  humano:   {label:'HUMANO',    fg:'#D65A1D', bg:'#FBE4D4', dot:'#D65A1D', icon:'●'},
  resuelto: {label:'RESUELTO',  fg:'#1E8057', bg:'#DDF1E4', dot:'#2EA571', icon:'✓'},
  escalar:  {label:'ESCALAR',   fg:'#B93535', bg:'#FBE8E8', dot:'#E04B4B', icon:'↗'},
};

function WFDiagram() {
  const wrapRef = useRef(null);
  const visible = useOnScreen(wrapRef);
  const [hoverNode, setHoverNode] = useState(null);

  // Zoom + pan state
  const [zoom, setZoom] = useState(1);
  const [pan, setPan] = useState({x:0, y:0});
  const dragRef = useRef({active:false, startX:0, startY:0, origX:0, origY:0});
  const frameRef = useRef(null);

  const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
  const setZoomClamped = (z) => setZoom(clamp(z, 0.4, 2));
  const zoomIn  = () => setZoomClamped(Math.round((zoom + 0.1)*10)/10);
  const zoomOut = () => setZoomClamped(Math.round((zoom - 0.1)*10)/10);
  const resetView = () => { setZoom(1); setPan({x:0, y:0}); };
  const fit = () => {
    const fw = frameRef.current?.clientWidth || 1100;
    const fh = frameRef.current?.clientHeight || 360;
    const VB_W = 1444, VB_H = 246;
    const scaleX = fw / VB_W;
    const scaleY = fh / VB_H;
    const z = clamp(Math.min(scaleX, scaleY) * 0.95, 0.4, 2);
    setZoom(z);
    setPan({x:0, y:0});
  };

  // Wheel → zoom
  React.useEffect(() => {
    const el = frameRef.current;
    if (!el) return;
    const onWheel = (e) => {
      e.preventDefault();
      const delta = e.deltaY < 0 ? 0.08 : -0.08;
      setZoom(z => clamp(Math.round((z + delta)*100)/100, 0.4, 2));
    };
    el.addEventListener('wheel', onWheel, {passive:false});
    return () => el.removeEventListener('wheel', onWheel);
  }, []);

  const onMouseDown = (e) => {
    if (e.button !== 0) return;
    // Don't pan when clicking on a node (a <g> with data-node attr)
    if (e.target.closest && e.target.closest('[data-wf-node]')) return;
    dragRef.current = {active:true, startX:e.clientX, startY:e.clientY, origX:pan.x, origY:pan.y};
    e.currentTarget.style.cursor = 'grabbing';
  };
  const onMouseMove = (e) => {
    if (!dragRef.current.active) return;
    const dx = e.clientX - dragRef.current.startX;
    const dy = e.clientY - dragRef.current.startY;
    setPan({x: dragRef.current.origX + dx, y: dragRef.current.origY + dy});
  };
  const endDrag = (e) => {
    if (!dragRef.current.active) return;
    dragRef.current.active = false;
    if (e.currentTarget && e.currentTarget.style) e.currentTarget.style.cursor = 'grab';
  };

  const NW = 172, NH = 76;
  const nodes = [
    {x:30,   y:60,  kind:'trigger',  l:'Gap > 7 días',         sub:'Disparador'},
    {x:232,  y:60,  kind:'accion',   l:'Consulta HIS + CRM',   sub:'Enriquecer caso'},
    {x:434,  y:60,  kind:'ia',       l:'Score de riesgo',      sub:'Modelo v2.4'},
    {x:636,  y:60,  kind:'decision', l:'Canal óptimo',         sub:'3 ramas'},
    {x:838,  y:0,   kind:'accion',   l:'Enviar WhatsApp',      sub:'ADH-GLP1-01'},
    {x:838,  y:80,  kind:'accion',   l:'Fallback SMS',         sub:'ADH-GLP1-SMS'},
    {x:838,  y:160, kind:'humano',   l:'Llamada humana',       sub:'Operador'},
    {x:1040, y:80,  kind:'ia',       l:'Clasificar motivo',    sub:'NLU'},
    {x:1242, y:0,   kind:'resuelto', l:'Dispensa reagend.',    sub:'Cierre auto'},
    {x:1242, y:80,  kind:'escalar',  l:'Equipo clínico',       sub:'Dra. Alemán'},
    {x:1242, y:160, kind:'escalar',  l:'Farmacia',             sub:'Supply chain'},
  ];
  const edges = [[0,1],[1,2],[2,3],[3,4],[3,5],[3,6],[4,7],[5,7],[6,7],[7,8],[7,9],[7,10]];

  const VB_W = 1444, VB_H = 246;

  return <div ref={wrapRef}>
    <div className="flex items-center justify-between flex-wrap gap-2 mb-3">
      <div className="flex items-center gap-2 flex-wrap">
        {Object.entries(NODE_TYPES).map(([k,t]) =>
          <span key={k} className="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-white border border-slate-100 text-[9.5px] font-bold uppercase" style={{color:t.fg, letterSpacing:'0.14em'}}>
            <span className="w-1.5 h-1.5 rounded-full" style={{background:t.dot}}/>
            {t.label}
          </span>)}
      </div>
      <div className="flex items-center gap-3 text-[11px] text-ink-400">
        <span className="flex items-center gap-1.5 font-mono">
          <span className="w-1.5 h-1.5 rounded-full bg-[#2EA571] pulse-dot"/>
          En ejecución · 23 casos
        </span>
        <span className="font-mono">11 nodos · 12 conexiones</span>
      </div>
    </div>

    <div className="relative rounded-xl border border-slate-100 overflow-hidden"
      ref={frameRef}
      onMouseDown={onMouseDown}
      onMouseMove={onMouseMove}
      onMouseUp={endDrag}
      onMouseLeave={endDrag}
      style={{
        background:'#FAFBFC',
        backgroundImage:'radial-gradient(circle at 1px 1px, rgba(148,163,184,0.25) 1px, transparent 0)',
        backgroundSize:'18px 18px',
        height: 360,
        cursor: 'grab',
        userSelect: 'none',
      }}>
      <div style={{
        position:'absolute', top:0, left:0,
        transform:`translate(${pan.x}px, ${pan.y}px) scale(${zoom})`,
        transformOrigin:'top left',
        transition: dragRef.current.active ? 'none' : 'transform 150ms ease',
        padding:20,
        width:'100%',
      }}>
        <svg viewBox={`0 0 ${VB_W} ${VB_H}`} style={{width:1444, display:'block'}}>
          <defs>
            <marker id="arr-soft" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto">
              <path d="M0,0 L10,5 L0,10 z" fill="#94A3B8"/>
            </marker>
            <marker id="arr-active" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto">
              <path d="M0,0 L10,5 L0,10 z" fill="#1B7690"/>
            </marker>
            <filter id="node-shadow" x="-10%" y="-10%" width="120%" height="140%">
              <feDropShadow dx="0" dy="1" stdDeviation="1.2" floodColor="#0F172A" floodOpacity="0.08"/>
            </filter>
          </defs>

          {/* Edges */}
          {edges.map(([a,b],i) => {
            const n1 = nodes[a], n2 = nodes[b];
            const x1 = n1.x + NW, y1 = n1.y + NH/2;
            const x2 = n2.x,       y2 = n2.y + NH/2;
            const mx = (x1 + x2) / 2;
            const d = `M${x1},${y1} C${mx},${y1} ${mx},${y2} ${x2},${y2}`;
            const isHover = hoverNode!=null && (hoverNode===a || hoverNode===b);
            const dim = hoverNode!=null && !isHover ? 0.3 : 1;
            return <path key={i} d={d}
              fill="none"
              stroke={isHover ? '#1B7690' : '#CBD5E1'}
              strokeWidth={isHover ? 2 : 1.5}
              markerEnd={isHover ? 'url(#arr-active)' : 'url(#arr-soft)'}
              opacity={dim}
              strokeDasharray={visible ? 'none' : '600'}
              style={{
                strokeDashoffset: visible ? 0 : 600,
                transition: `stroke-dashoffset .8s ease-out ${0.4 + i*0.05}s, opacity .15s, stroke .15s, stroke-width .15s`,
              }}/>;
          })}

          {/* Nodes */}
          {nodes.map((n,i) => {
            const t = NODE_TYPES[n.kind];
            const isHover = hoverNode===i;
            const dim = hoverNode!=null && !isHover ? 0.5 : 1;
            const delay = 0.05 + i*0.04;
            return <g key={i}
              data-wf-node={i}
              onMouseEnter={()=>setHoverNode(i)}
              onMouseLeave={()=>setHoverNode(null)}
              style={{
                cursor:'pointer',
                opacity: visible ? dim : 0,
                transform: visible ? 'translateY(0)' : 'translateY(4px)',
                transformBox:'fill-box',
                transition:`opacity .3s ease-out ${delay}s, transform .3s ease-out ${delay}s`,
              }}>
              {/* Pulse ring on trigger node when active */}
              {n.kind==='trigger' && visible && <rect
                x={n.x-2} y={n.y-2} width={NW+4} height={NH+4} rx="10"
                fill="none" stroke={t.dot} strokeWidth="2"
                opacity="0"
                style={{animation:'trgPulse 2.4s ease-out infinite 1.2s'}}/>}

              {/* Card */}
              <rect x={n.x} y={n.y} width={NW} height={NH} rx="10"
                fill="white"
                stroke={isHover ? t.fg : '#E2E8F0'}
                strokeWidth={isHover ? 1.5 : 1}
                filter="url(#node-shadow)"/>

              {/* Left accent bar */}
              <rect x={n.x} y={n.y} width="3" height={NH} fill={t.dot} rx="1.5"/>

              {/* Type chip — matches design-system Badge tokens · generous padding so labels never clip */}
              <rect x={n.x+14} y={n.y+12} width={t.label.length*7.4+24} height="20" rx="10" fill={t.bg}/>
              <text x={n.x+26} y={n.y+25.5} fontSize="10" fontFamily="Inter" fill={t.fg} fontWeight="700" letterSpacing="1.2">
                {t.label}
              </text>

              {/* Main label — Inter 12 · 600 · ink-900 · y = chip bottom + 14 */}
              <text x={n.x+14} y={n.y+50} fontSize="12" fontFamily="Inter" fill="#0F172A" fontWeight="600">{n.l}</text>
              {/* Sub label — Inter 10.5 · ink-400 · y = main + 14 */}
              <text x={n.x+14} y={n.y+64} fontSize="10.5" fontFamily="Inter" fill="#7E8798" fontWeight="400">{n.sub}</text>
            </g>;
          })}
        </svg>
      </div>

      {/* Zoom controls */}
      <div className="absolute bottom-3 right-3 flex items-center gap-1 bg-white border border-slate-200 rounded-lg shadow-sm p-1"
        onMouseDown={(e)=>e.stopPropagation()}>
        <button onClick={zoomOut} disabled={zoom<=0.4}
          className="w-7 h-7 flex items-center justify-center rounded hover:bg-slate-100 text-ink-700 disabled:text-ink-300 disabled:cursor-not-allowed"
          title="Alejar">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="w-3.5 h-3.5"><line x1="5" y1="12" x2="19" y2="12"/></svg>
        </button>
        <button onClick={resetView}
          className="px-2 h-7 min-w-[48px] rounded hover:bg-slate-100 text-[11px] font-mono font-semibold tabular-nums text-ink-700"
          title="Restablecer (100%)">
          {Math.round(zoom*100)}%
        </button>
        <button onClick={zoomIn} disabled={zoom>=2}
          className="w-7 h-7 flex items-center justify-center rounded hover:bg-slate-100 text-ink-700 disabled:text-ink-300 disabled:cursor-not-allowed"
          title="Acercar">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="w-3.5 h-3.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
        </button>
        <span className="w-px h-5 bg-slate-200 mx-0.5"/>
        <button onClick={fit}
          className="w-7 h-7 flex items-center justify-center rounded hover:bg-slate-100 text-ink-700"
          title="Ajustar al frame">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-3.5 h-3.5">
            <path d="M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"/>
          </svg>
        </button>
      </div>
    </div>
    <style>{`@keyframes trgPulse { 0%{opacity:.6; transform:scale(1)} 100%{opacity:0; transform:scale(1.06)} }`}</style>
  </div>;
}

function ReplayModal({exec, onClose}) {
  // Shared node map with WFDiagram (keep geometry in sync)
  const NW = 172, NH = 76;
  const nodes = [
    {x:30,   y:60,  kind:'trigger',   slug:'trigger',          l:'Gap > 7 días',        sub:'Disparador'},
    {x:232,  y:60,  kind:'accion',    slug:'accion-his',       l:'Consulta HIS + CRM',  sub:'Enriquecer caso'},
    {x:434,  y:60,  kind:'ia',        slug:'ia-score',         l:'Score de riesgo',     sub:'Modelo v2.4'},
    {x:636,  y:60,  kind:'decision',  slug:'decision',         l:'Canal óptimo',        sub:'3 ramas'},
    {x:838,  y:0,   kind:'accion',    slug:'whatsapp',         l:'Enviar WhatsApp',     sub:'ADH-GLP1-01'},
    {x:838,  y:80,  kind:'accion',    slug:'sms',              l:'Fallback SMS',        sub:'ADH-GLP1-SMS'},
    {x:838,  y:160, kind:'humano',    slug:'llamada',          l:'Llamada humana',      sub:'Operador'},
    {x:1040, y:80,  kind:'ia',        slug:'clasificar',       l:'Clasificar motivo',   sub:'NLU'},
    {x:1242, y:0,   kind:'resuelto',  slug:'resuelto',         l:'Dispensa reagend.',   sub:'Cierre auto'},
    {x:1242, y:80,  kind:'escalar',   slug:'escalar-clinico',  l:'Equipo clínico',      sub:'Dra. Alemán'},
    {x:1242, y:160, kind:'escalar',   slug:'escalar-farmacia', l:'Farmacia',            sub:'Supply chain'},
    // Synthetic terminal states (not rendered as nodes; handled via mapping below)
  ];
  // Pseudo-states map to an existing node visually
  const SYNTHETIC = {
    pendiente: 6, // shown on Llamada humana
    error:     1, // shown on Consulta HIS + CRM
  };
  const slugToIdx = (slug) => {
    const i = nodes.findIndex(n => n.slug === slug);
    if (i >= 0) return i;
    return SYNTHETIC[slug] ?? 0;
  };
  const pathIdx = exec.path.map(slugToIdx);
  // step-by-step log (output summary per node slug)
  const STEP_OUTPUT = {
    'trigger':          'Condición IF cumplida · paciente activo, receta vigente',
    'accion-his':       'HIS OK · última dispensa 22d · CRM: 0 contactos activos',
    'ia-score':         'Score 76/100 · perfil "respondedor WhatsApp AM"',
    'decision':         'Decisión: WhatsApp (confidence 0.82)',
    'whatsapp':         'Mensaje enviado · plantilla ADH-GLP1-01',
    'sms':              'SMS enviado · fallback tras 12h sin respuesta',
    'llamada':          'Operador asignado · intento 1 de 3',
    'clasificar':       'NLU · motivo clasificado: efecto adverso',
    'resuelto':         'Dispensa reagendada · caso cerrado automáticamente',
    'escalar-clinico':  'Caso escalado a Dra. Alemán (endocrinología)',
    'escalar-farmacia': 'Alerta enviada a supply chain',
    'pendiente':        'Sin respuesta tras 3 intentos · reagendar llamada',
    'error':            'Timeout integración · HIS no respondió en 10s',
  };

  const [playing, setPlaying] = useState(true);
  const [step, setStep]       = useState(0); // number of steps completed
  const [speed, setSpeed]     = useState('normal'); // lento/normal/rapido
  const intervalMs = speed==='lento' ? 1200 : speed==='rapido' ? 200 : 600;

  // Advance steps automatically when playing
  React.useEffect(() => {
    if (!playing) return;
    if (step >= exec.path.length) { setPlaying(false); return; }
    const t = setTimeout(() => setStep(s => s+1), intervalMs);
    return () => clearTimeout(t);
  }, [playing, step, exec.path.length, intervalMs]);

  // Auto-scroll log to active step
  const logRef = useRef(null);
  React.useEffect(() => {
    if (!logRef.current) return;
    const active = logRef.current.querySelector('[data-active="true"]');
    if (active) active.scrollIntoViewIfNeeded ? active.scrollIntoViewIfNeeded() : active.scrollIntoView({block:'nearest', behavior:'smooth'});
  }, [step]);

  const restart = () => { setStep(0); setPlaying(true); };
  const toggle  = () => {
    if (step >= exec.path.length) { setStep(0); setPlaying(true); }
    else setPlaying(p => !p);
  };
  const done = step >= exec.path.length;
  const activeIdx = step > 0 ? pathIdx[step-1] : -1;
  const activePath = pathIdx.slice(0, step); // nodes visited so far

  // Edges defined same as WFDiagram
  const allEdges = [[0,1],[1,2],[2,3],[3,4],[3,5],[3,6],[4,7],[5,7],[6,7],[7,8],[7,9],[7,10]];
  // Determine which edges are "on path" up to current step
  const activeEdges = new Set();
  for (let i = 0; i < step-1; i++) {
    const a = pathIdx[i], b = pathIdx[i+1];
    const edgeIdx = allEdges.findIndex(([x,y]) => x===a && y===b);
    if (edgeIdx >= 0) activeEdges.add(edgeIdx);
  }

  const VB_W = 1444, VB_H = 246;
  const resBadge = exec.res==='Resuelto auto'?'ok':exec.res==='Escalado a humano'?'sun':exec.res==='Error'?'danger':'slate';

  // Build step log entries
  const baseTime = exec.date; // e.g. "23/04/2026 11:42"
  const stepLog = pathIdx.map((nIdx, i) => {
    const slug = exec.path[i];
    const node = nodes[nIdx];
    const mins = Math.floor(i * (i%2?2.8:1.4));
    const secs = (i*17) % 60;
    return {
      n: node,
      slug,
      title: slug==='pendiente' ? 'Pendiente · llamada sin respuesta' :
             slug==='error'     ? 'Error · timeout integración' : node.l,
      out: STEP_OUTPUT[slug] || '—',
      ts: `+${String(mins).padStart(2,'0')}:${String(secs).padStart(2,'0')}`,
      dur: (Math.floor(20 + Math.random()*600)) + 'ms',
      isError: slug==='error',
      isPending: slug==='pendiente',
    };
  });

  return <div className="fixed inset-0 z-50 flex items-center justify-center px-4"
    style={{background:'rgba(15,23,42,0.55)', backdropFilter:'blur(4px)', animation:'fadeIn .18s ease-out both'}}
    onClick={onClose}>
    <div className="bg-white rounded-2xl shadow-2xl w-[1180px] max-w-[98vw] max-h-[92vh] flex flex-col overflow-hidden"
      style={{animation:'slideUp .22s ease-out both'}}
      onClick={(e)=>e.stopPropagation()}>

      {/* Header */}
      <div className="px-5 py-4 border-b border-slate-100 flex items-center gap-3">
        <div>
          <div className="flex items-center gap-2">
            <span className="text-[10px] font-mono uppercase tracking-wider text-ink-400 font-semibold">Replay de ejecución</span>
            <span className="font-mono text-[11px] font-bold text-ink-800">{exec.id}</span>
          </div>
          <div className="flex items-baseline gap-2 mt-0.5">
            <h2 className="text-[16px] font-display font-bold text-ink-800">{exec.pn}</h2>
            <span className="font-mono text-[11px] text-ink-500">{exec.p}</span>
            <span className="font-mono text-[11px] text-ink-400">· {exec.date} · {exec.dur}</span>
          </div>
        </div>
        <Badge tone={resBadge} size="sm" className="ml-3">{exec.res}</Badge>
        <button onClick={onClose} className="ml-auto w-8 h-8 rounded-lg hover:bg-slate-100 flex items-center justify-center text-ink-500">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="w-4 h-4"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
        </button>
      </div>

      {/* Body */}
      <div className="flex-1 flex min-h-0">
        {/* Canvas */}
        <div className="flex-1 flex flex-col min-w-0 border-r border-slate-100">
          <div className="flex-1 p-5 overflow-auto" style={{
            background:'#FAFBFC',
            backgroundImage:'radial-gradient(circle at 1px 1px, rgba(148,163,184,0.25) 1px, transparent 0)',
            backgroundSize:'18px 18px',
          }}>
            <svg viewBox={`0 0 ${VB_W} ${VB_H}`} style={{width:'100%', minWidth:1100, display:'block'}}>
              <defs>
                <marker id="rp-arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto">
                  <path d="M0,0 L10,5 L0,10 z" fill="#94A3B8"/>
                </marker>
                <marker id="rp-arr-active" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto">
                  <path d="M0,0 L10,5 L0,10 z" fill="#1B7690"/>
                </marker>
                <filter id="rp-shadow" x="-10%" y="-10%" width="120%" height="140%">
                  <feDropShadow dx="0" dy="1" stdDeviation="1.2" floodColor="#0F172A" floodOpacity="0.08"/>
                </filter>
              </defs>
              {/* Edges */}
              {allEdges.map(([a,b],i) => {
                const n1 = nodes[a], n2 = nodes[b];
                const x1 = n1.x + NW, y1 = n1.y + NH/2;
                const x2 = n2.x,      y2 = n2.y + NH/2;
                const mx = (x1+x2)/2;
                const d = `M${x1},${y1} C${mx},${y1} ${mx},${y2} ${x2},${y2}`;
                const on = activeEdges.has(i);
                return <path key={i} d={d}
                  fill="none"
                  stroke={on?'#1B7690':'#E2E8F0'}
                  strokeWidth={on?2.2:1.3}
                  markerEnd={on?'url(#rp-arr-active)':'url(#rp-arr)'}
                  opacity={on?1:0.6}
                  strokeDasharray={on ? 'none' : 'none'}
                  style={{
                    transition:'stroke .4s, stroke-width .4s, opacity .4s',
                  }}/>;
              })}
              {/* Nodes */}
              {nodes.map((n,i) => {
                const t = NODE_TYPES[n.kind];
                const isActive = activeIdx === i;
                const wasVisited = activePath.includes(i);
                const isFinal = done && pathIdx[pathIdx.length-1] === i;
                const baseOpacity = wasVisited ? 1 : 0.22;
                return <g key={i} style={{
                  opacity: baseOpacity,
                  transition:'opacity .4s ease-out',
                }}>
                  {/* Final pulse ring */}
                  {isFinal && <rect x={n.x-2} y={n.y-2} width={NW+4} height={NH+4} rx="10"
                    fill="none" stroke={t.dot} strokeWidth="2" opacity="0"
                    style={{animation:'trgPulse 1.8s ease-out infinite'}}/>}
                  {/* Active step pulse */}
                  {isActive && <rect x={n.x-2} y={n.y-2} width={NW+4} height={NH+4} rx="10"
                    fill="none" stroke={t.dot} strokeWidth="2.5" opacity="0.8"
                    style={{animation:'rpActivePulse .3s ease-out 1 both'}}/>}

                  <rect x={n.x} y={n.y} width={NW} height={NH} rx="10"
                    fill="white"
                    stroke={wasVisited ? t.fg : '#E2E8F0'}
                    strokeWidth={wasVisited ? 1.5 : 1}
                    filter="url(#rp-shadow)"/>
                  <rect x={n.x} y={n.y} width="3" height={NH} fill={wasVisited ? t.dot : '#CBD5E1'} rx="1.5"/>
                  <rect x={n.x+14} y={n.y+12} width={t.label.length*7.4+24} height="20" rx="10" fill={wasVisited ? t.bg : '#F1F5F9'}/>
                  <text x={n.x+26} y={n.y+25.5} fontSize="10" fontFamily="Inter" fill={wasVisited ? t.fg : '#94A3B8'} fontWeight="700" letterSpacing="1.2">{t.label}</text>
                  <text x={n.x+14} y={n.y+50} fontSize="12" fontFamily="Inter" fill="#0F172A" fontWeight="600">{n.l}</text>
                  <text x={n.x+14} y={n.y+64} fontSize="10.5" fontFamily="Inter" fill="#7E8798" fontWeight="400">{n.sub}</text>
                </g>;
              })}
            </svg>
          </div>

          {/* Controls */}
          <div className="border-t border-slate-100 px-5 py-3 flex items-center gap-3 bg-slate-50/40">
            <button onClick={restart}
              className="w-9 h-9 rounded-lg border border-slate-200 bg-white hover:bg-slate-50 flex items-center justify-center text-ink-700"
              title="Reiniciar">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-4 h-4"><polygon points="19 20 9 12 19 4 19 20"/><line x1="5" y1="19" x2="5" y2="5"/></svg>
            </button>
            <button onClick={toggle}
              className="w-10 h-10 rounded-full bg-helios-600 hover:bg-helios-700 text-white flex items-center justify-center shadow-sm"
              title={playing?'Pausar':done?'Reproducir de nuevo':'Reproducir'}>
              {playing && !done
                ? <svg viewBox="0 0 24 24" fill="currentColor" className="w-4 h-4"><rect x="6" y="5" width="4" height="14"/><rect x="14" y="5" width="4" height="14"/></svg>
                : <svg viewBox="0 0 24 24" fill="currentColor" className="w-4 h-4 ml-0.5"><polygon points="6,4 20,12 6,20"/></svg>}
            </button>

            {/* Progress */}
            <div className="flex-1 flex items-center gap-2">
              <span className="font-mono text-[11px] tabular-nums text-ink-500">{step}/{exec.path.length}</span>
              <div className="flex-1 h-1.5 bg-slate-200 rounded-full overflow-hidden">
                <div className="h-full bg-helios-600 rounded-full transition-all"
                  style={{width: (step/exec.path.length)*100+'%'}}/>
              </div>
            </div>

            {/* Speed selector */}
            <div className="flex items-center gap-1 bg-white border border-slate-200 rounded-lg p-0.5">
              {[{k:'lento',l:'Lento'},{k:'normal',l:'Normal'},{k:'rapido',l:'Rápido'}].map(s =>
                <button key={s.k} onClick={()=>setSpeed(s.k)}
                  className={'px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors '+
                    (speed===s.k?'bg-slate-100 text-ink-800':'text-ink-500 hover:text-ink-700')}>
                  {s.l}
                </button>)}
            </div>
          </div>
        </div>

        {/* Side log */}
        <div className="w-[260px] shrink-0 flex flex-col bg-white">
          <div className="px-4 py-3 border-b border-slate-100">
            <div className="text-[10px] font-mono uppercase tracking-wider text-ink-400 font-semibold">Log paso a paso</div>
            <div className="text-[11.5px] text-ink-500 mt-0.5">{exec.path.length} pasos · sincronizado</div>
          </div>
          <div ref={logRef} className="flex-1 overflow-y-auto py-2">
            {stepLog.map((s,i) => {
              const done_ = i < step;
              const current = i === step-1;
              const pending = i >= step;
              const tkey = s.n.kind;
              const t = NODE_TYPES[tkey];
              return <div key={i} data-active={current}
                className={'px-4 py-2.5 border-l-2 transition-all '+
                  (current?'bg-helios-50 border-helios-600':
                   done_?'border-slate-200':'border-transparent opacity-45')}>
                <div className="flex items-center gap-1.5 mb-0.5">
                  <span className="w-1.5 h-1.5 rounded-full" style={{background: done_ ? t.dot : '#CBD5E1'}}/>
                  <span className="text-[9.5px] uppercase font-bold tabular-nums text-ink-400" style={{letterSpacing:'0.14em'}}>
                    {String(i+1).padStart(2,'0')} · {t.label}
                  </span>
                  <span className="ml-auto font-mono text-[10px] text-ink-400 tabular-nums">{s.ts}</span>
                </div>
                <div className="text-[12px] font-semibold text-ink-800 leading-snug">{s.title}</div>
                <div className="text-[10.5px] text-ink-500 mt-0.5 leading-snug">{s.out}</div>
                {done_ && <div className="font-mono text-[9.5px] text-ink-400 mt-1">duración · {s.dur}</div>}
              </div>;
            })}
          </div>
        </div>
      </div>

      <style>{`
        @keyframes rpActivePulse { 0%{opacity:0; transform:scale(1)} 50%{opacity:.9; transform:scale(1.02)} 100%{opacity:0.3; transform:scale(1)} }
      `}</style>
    </div>
  </div>;
}

function WFReglas() {
  return <div className="grid grid-cols-2 gap-4">
    <div>
      <h3 className="text-[13px] font-display font-semibold text-ink-800 mb-2">Trigger</h3>
      <div className="bg-slate-50 rounded-xl p-3 font-mono text-[11.5px] text-ink-700 leading-relaxed">
        <div><span className="text-[#B93535] font-semibold">IF</span> paciente.dias_sin_dispensa &gt; <span className="text-[#D65A1D]">7</span></div>
        <div><span className="text-[#B93535] font-semibold">AND</span> paciente.estado == <span className="text-[#1E8057]">"activo"</span></div>
        <div><span className="text-[#B93535] font-semibold">AND</span> receta.vigente == <span className="text-[#1E8057]">true</span></div>
        <div className="mt-2"><span className="text-[#D28513] font-semibold">THEN</span> iniciar WF-ADH</div>
      </div>
      <h3 className="text-[13px] font-display font-semibold text-ink-800 mt-4 mb-2">Condiciones de escalamiento</h3>
      <div className="space-y-1.5">
        {['Motivo = efecto adverso → Equipo clínico','Motivo = complicación → Médico de cabecera','Sin respuesta en 72h → Llamada humana','3 gaps consecutivos → Revisión de caso'].map(r => <div key={r} className="flex gap-2 items-start p-2 bg-white rounded-lg border border-slate-100 text-[11.5px]">
          <Icon.chevR c="w-3.5 h-3.5 text-ink-400 mt-0.5 shrink-0"/>
          <span className="text-ink-700">{r}</span>
        </div>)}
      </div>
    </div>
    <div>
      <h3 className="text-[13px] font-display font-semibold text-ink-800 mb-2">Canales y plantillas</h3>
      <div className="space-y-2">
        {[
          {c:'WhatsApp',p:'ADH-GLP1-01',desc:'Primer contacto amigable · CTA reagendar'},
          {c:'WhatsApp',p:'ADH-GLP1-02',desc:'Segundo intento · énfasis en continuidad'},
          {c:'SMS',p:'ADH-GLP1-SMS',desc:'Fallback corto con link de reagendo'},
          {c:'Llamada',p:'ADH-PROT-01',desc:'Protocolo para operador humano'},
        ].map(t => <div key={t.p} className="flex items-center gap-3 p-2.5 bg-white rounded-lg border border-slate-100">
          <Badge tone="slate" size="sm">{t.c}</Badge>
          <div className="min-w-0 flex-1">
            <div className="font-mono text-[11px] font-semibold text-ink-800">{t.p}</div>
            <div className="text-[10.5px] text-ink-400">{t.desc}</div>
          </div>
        </div>)}
      </div>
      <h3 className="text-[13px] font-display font-semibold text-ink-800 mt-4 mb-2">Integraciones</h3>
      <div className="flex flex-wrap gap-1.5">
        {['HIS · GlobalHC','CRM · Salesforce','WhatsApp Business API','Twilio · SMS/voz','OpenAI · clasificación','Calendly · reagendo'].map(t => <Badge key={t} tone="slate" size="sm">{t}</Badge>)}
      </div>
    </div>
  </div>;
}

function WFExec({go}) {
  const execs = [
    {id:'EX-8821', p:'P-0428', pn:'María Elena Fernández Rossi', date:'23/04/2026 11:42', dur:'28 min', res:'Escalado a humano', path:['trigger','accion-his','ia-score','decision','whatsapp','clasificar','escalar-clinico']},
    {id:'EX-8820', p:'P-0312', pn:'Jorge Benítez',              date:'23/04/2026 11:38', dur:'4 min',  res:'Resuelto auto',    path:['trigger','accion-his','ia-score','decision','whatsapp','resuelto']},
    {id:'EX-8819', p:'P-0221', pn:'Roberto Tonini',             date:'23/04/2026 09:31', dur:'52 min', res:'Escalado a humano', path:['trigger','accion-his','ia-score','decision','whatsapp','sms','clasificar','escalar-clinico']},
    {id:'EX-8818', p:'P-0811', pn:'Esteban Funes',              date:'23/04/2026 08:14', dur:'18 min', res:'Sin respuesta',    path:['trigger','accion-his','ia-score','decision','whatsapp','sms','llamada','pendiente']},
    {id:'EX-8817', p:'P-0517', pn:'Pedro Alvarado',             date:'22/04/2026 17:22', dur:'6 min',  res:'Resuelto auto',    path:['trigger','accion-his','ia-score','decision','whatsapp','resuelto']},
    {id:'EX-8816', p:'P-0634', pn:'Javier Ramírez',             date:'22/04/2026 15:08', dur:'11 min', res:'Resuelto auto',    path:['trigger','accion-his','ia-score','decision','sms','resuelto']},
    {id:'EX-8815', p:'P-0703', pn:'Verónica Colombo',           date:'22/04/2026 13:44', dur:'34 min', res:'Escalado a humano', path:['trigger','accion-his','ia-score','decision','whatsapp','clasificar','escalar-clinico']},
    {id:'EX-8814', p:'P-0920', pn:'Matías Gutiérrez',           date:'22/04/2026 10:19', dur:'5 min',  res:'Resuelto auto',    path:['trigger','accion-his','ia-score','decision','whatsapp','resuelto']},
    {id:'EX-8813', p:'P-0402', pn:'Lucía Bravo',                date:'21/04/2026 16:55', dur:'9 min',  res:'Resuelto auto',    path:['trigger','accion-his','ia-score','decision','whatsapp','resuelto']},
    {id:'EX-8812', p:'P-0189', pn:'Carolina Mazzanti',          date:'21/04/2026 14:30', dur:'3 min',  res:'Error',            path:['trigger','accion-his','error']},
  ];
  const [replay, setReplay] = useState(null);

  const tone = (r) => r==='Resuelto auto'?'ok':r==='Escalado a humano'?'sun':r==='Error'?'danger':'slate';

  return <>
    <table className="w-full text-[12px]">
      <thead><tr className="text-[10px] font-mono uppercase tracking-wider text-ink-400 border-b border-slate-100">
        <th className="text-left py-2">Ejecución</th>
        <th className="text-left">Caso</th>
        <th className="text-left">Inicio</th>
        <th className="text-left">Duración</th>
        <th className="text-left">Resultado</th>
        <th className="text-right">Acciones</th>
      </tr></thead>
      <tbody>
        {execs.map(e => <tr key={e.id} className="border-b border-slate-100 last:border-0 hover:bg-slate-50">
          <td className="py-2.5 font-mono text-[11px] font-semibold">{e.id}</td>
          <td><span className="font-mono text-[11px] text-ink-500">{e.p}</span> · <span className="font-semibold">{e.pn}</span></td>
          <td className="font-mono text-[11px] text-ink-500">{e.date}</td>
          <td className="font-mono text-[11px]">{e.dur}</td>
          <td><Badge tone={tone(e.res)} size="sm">{e.res}</Badge></td>
          <td className="text-right">
            <div className="inline-flex gap-1.5">
              <Button variant="outline" size="sm" onClick={()=>setReplay(e)}>Ver ejecución</Button>
              <Button variant="ghost" size="sm" onClick={()=>go('caso',e.p)}>Caso</Button>
            </div>
          </td>
        </tr>)}
      </tbody>
    </table>
    {replay && <ReplayModal exec={replay} onClose={()=>setReplay(null)}/>}
  </>;
}

function WFMetricas() {
  const days = [
    {d:1,ok:72,esc:12},{d:2,ok:68,esc:14},{d:3,ok:85,esc:9},{d:4,ok:78,esc:11},
    {d:5,ok:82,esc:13},{d:6,ok:65,esc:8}, {d:7,ok:71,esc:10},{d:8,ok:88,esc:15},
    {d:9,ok:92,esc:11},{d:10,ok:79,esc:9},{d:11,ok:84,esc:13},{d:12,ok:91,esc:10},
    {d:13,ok:87,esc:14},{d:14,ok:94,esc:12},
  ];
  const max = Math.max(...days.map(d=>d.ok+d.esc));
  const wrapRefBar = useRef(null);
  const visBar = useOnScreen(wrapRefBar);
  const [hoverBar, setHoverBar] = useState(null);
  const H = 180;

  const motivos = [
    {l:'Efecto adverso',      v:42, fg:'#B93535', bg:'#FBE8E8'},
    {l:'Complicación clínica', v:23, fg:'#A06A12', bg:'#FDF0D9'},
    {l:'Sin respuesta 72h',    v:18, fg:'#D28513', bg:'#FDF0D9'},
    {l:'Motivo económico',     v:12, fg:'#1B7690', bg:'#E6F1F5'},
    {l:'Otro',                 v:5,  fg:'#64748B', bg:'#F1F5F9'},
  ];
  const wrapRefMot = useRef(null);
  const visMot = useOnScreen(wrapRefMot);

  // Tendencia de resolución · sparkline
  const trend = [72,68,74,71,78,82,79,81,85,83,87,86,89,92];
  const tMax = Math.max(...trend), tMin = Math.min(...trend);
  const W = 320, TH = 60;
  const pts = trend.map((v,i)=> {
    const x = (i/(trend.length-1))*W;
    const y = TH - ((v-tMin)/(tMax-tMin))*TH;
    return [x,y];
  });
  const linePath = pts.map((p,i)=> (i?'L':'M')+p[0]+','+p[1]).join(' ');
  const areaPath = linePath + ` L${W},${TH} L0,${TH} Z`;
  const wrapRefTrend = useRef(null);
  const visTrend = useOnScreen(wrapRefTrend);

  const total = days.reduce((a,d)=>a+d.ok+d.esc, 0);
  const resueltas = days.reduce((a,d)=>a+d.ok, 0);
  const tasa = Math.round(resueltas/total*100);

  return <div className="space-y-4">
    {/* Mini-KPIs sobre métricas */}
    <div className="grid grid-cols-4 gap-3">
      <MetricKpi l="Últimos 14 días" v={total} sub="ejecuciones totales"/>
      <MetricKpi l="Tasa resolución" v={tasa+'%'} sub="+4pp vs. 14d previos" tone="ok"/>
      <MetricKpi l="Tiempo medio" v="6m 14s" sub="P50 · auto" tone="helios"/>
      <MetricKpi l="Ahorro estimado" v="$184K" sub="ARS · mes en curso" tone="ok"/>
    </div>

    <div className="grid grid-cols-2 gap-4">
      {/* ── Bar chart ─────────────────────────────────────── */}
      <div>
        <div className="flex items-baseline justify-between mb-2">
          <h3 className="text-[13px] font-display font-semibold text-ink-800">Ejecuciones por día</h3>
          <span className="text-[10.5px] font-mono text-ink-400">últimos 14 días</span>
        </div>
        <div ref={wrapRefBar} className="relative bg-slate-50/60 rounded-xl p-3 border border-slate-100">
          <div className="h-[180px] flex items-end gap-1.5 relative" onMouseLeave={()=>setHoverBar(null)}>
            {/* Gridlines */}
            <div className="absolute inset-0 flex flex-col justify-between pointer-events-none">
              {[0,1,2,3].map(i => <div key={i} className="h-px bg-slate-200/60"/>)}
            </div>
            {days.map((d,i)=> {
              const okH = (d.ok/max)*H;
              const escH = (d.esc/max)*H;
              const dim = hoverBar!=null && hoverBar!==i ? 0.35 : 1;
              const isHover = hoverBar===i;
              return <div key={d.d}
                className="flex-1 flex flex-col justify-end gap-0.5 relative z-10 cursor-pointer"
                style={{height:H+'px', opacity:dim, transition:'opacity 150ms'}}
                onMouseEnter={()=>setHoverBar(i)}>
                {visBar && <div className="chart-bar-anim rounded-t-sm" style={{
                  height:escH+'px',
                  background: isHover ? '#C78008' : '#EEA028',
                  animationDelay: (i*0.04)+'s',
                  transition:'background 150ms',
                }} title={d.esc+' escaladas'}/>}
                {visBar && <div className="chart-bar-anim rounded-b-sm" style={{
                  height:okH+'px',
                  background: isHover ? '#16A870' : '#2EA571',
                  animationDelay: (i*0.04 + 0.05)+'s',
                  transition:'background 150ms',
                }} title={d.ok+' resueltas'}/>}
              </div>;
            })}
            {hoverBar!=null && <WFBarTooltip d={days[hoverBar]} idx={hoverBar} total={days.length}/>}
          </div>
        </div>
        <div className="flex gap-4 mt-2.5 text-[11px] text-ink-500">
          <span className="flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-sm bg-[#2EA571]"/>Resueltas</span>
          <span className="flex items-center gap-1.5"><span className="w-2.5 h-2.5 rounded-sm bg-[#EEA028]"/>Escaladas</span>
        </div>
      </div>

      {/* ── Motivos de escalamiento ─────────────────────────── */}
      <div>
        <div className="flex items-baseline justify-between mb-2">
          <h3 className="text-[13px] font-display font-semibold text-ink-800">Motivos de escalamiento</h3>
          <span className="text-[10.5px] font-mono text-ink-400">100 casos · 30 días</span>
        </div>
        <div ref={wrapRefMot} className="bg-slate-50/60 rounded-xl p-3.5 border border-slate-100 space-y-2.5">
          {motivos.map((m,i) => <div key={m.l} className="flex items-center gap-3">
            <span className="text-[12px] text-ink-700 w-36 truncate">{m.l}</span>
            <div className="flex-1 h-2.5 bg-white rounded-full overflow-hidden border border-slate-100">
              {visMot && <div className="chart-bar-anim-h h-full rounded-full" style={{
                width: (m.v/50)*100+'%',
                background: m.fg,
                animationDelay: (i*0.08)+'s',
              }}/>}
            </div>
            <span className="font-mono text-[11.5px] font-bold tabular-nums w-9 text-right" style={{color:m.fg}}>{m.v}%</span>
          </div>)}
        </div>
      </div>
    </div>

    {/* ── Tendencia de resolución ─────────────────────────── */}
    <div>
      <div className="flex items-baseline justify-between mb-2">
        <h3 className="text-[13px] font-display font-semibold text-ink-800">Tendencia de tasa de resolución automática</h3>
        <span className="text-[10.5px] font-mono text-ink-400">14 días · % diario</span>
      </div>
      <div ref={wrapRefTrend} className="bg-slate-50/60 rounded-xl p-4 border border-slate-100 flex items-center gap-5">
        <div>
          <div className="text-[10px] font-mono uppercase tracking-wider text-ink-400 font-semibold">Hoy</div>
          <div className="font-display font-extrabold text-[32px] tabular-nums leading-none text-[#1E8057]">{trend[trend.length-1]}%</div>
          <div className="text-[10.5px] font-mono text-[#1E8057] font-semibold mt-1">+{trend[trend.length-1]-trend[0]}pp en 14d</div>
        </div>
        <svg viewBox={`0 0 ${W} ${TH+4}`} className="flex-1" style={{maxHeight:70}} preserveAspectRatio="none">
          <defs>
            <linearGradient id="trendGrad" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stopColor="#2EA571" stopOpacity="0.25"/>
              <stop offset="100%" stopColor="#2EA571" stopOpacity="0"/>
            </linearGradient>
          </defs>
          {visTrend && <>
            <path d={areaPath} fill="url(#trendGrad)" className="chart-area-anim"/>
            <path d={linePath} fill="none" stroke="#2EA571" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"
              className="chart-line-anim" style={{'--dash':W*1.4}}/>
            {pts.map((p,i) => i===pts.length-1 && <circle key={i} cx={p[0]} cy={p[1]} r="4" fill="#2EA571" className="chart-dot-anim" style={{animationDelay:'.65s'}}/>)}
          </>}
        </svg>
      </div>
    </div>
  </div>;
}

function MetricKpi({l,v,sub,tone}) {
  const fg = tone==='ok'?'text-[#1E8057]':tone==='helios'?'text-helios-700':'text-ink-800';
  return <div className="bg-white rounded-xl border border-slate-100 px-3.5 py-2.5">
    <div className="text-[10px] font-mono uppercase tracking-wider text-ink-400 font-semibold">{l}</div>
    <div className={'font-display font-extrabold text-[22px] tabular-nums leading-none mt-1 '+fg}>{v}</div>
    {sub && <div className="text-[10.5px] text-ink-500 mt-1">{sub}</div>}
  </div>;
}

function WFBarTooltip({d, idx, total}) {
  const left = ((idx+0.5)/total)*100;
  const flipRight = idx < 2;
  const flipLeft = idx > total - 3;
  return <div className="absolute z-30 pointer-events-none" style={{
    left:left+'%',
    top:'-8px',
    transform: flipRight ? 'translate(8px,-100%)' : flipLeft ? 'translate(calc(-100% - 8px),-100%)' : 'translate(-50%,-100%)',
  }}>
    <div className="bg-white border border-slate-200 rounded-lg shadow-lg px-3 py-2 min-w-[140px]" style={{animation:'slideUp .15s ease-out both'}}>
      <div className="text-[10px] font-mono uppercase tracking-wider text-ink-400 font-semibold">Día {d.d}</div>
      <div className="font-display font-extrabold text-[18px] tabular-nums leading-none text-ink-800 mt-1">{d.ok+d.esc}</div>
      <div className="text-[10.5px] text-ink-500">ejecuciones</div>
      <div className="mt-1.5 pt-1.5 border-t border-slate-100 space-y-0.5">
        <div className="flex items-center justify-between gap-3 text-[11px]">
          <span className="flex items-center gap-1.5"><span className="w-2 h-2 rounded-sm bg-[#2EA571]"/>Resueltas</span>
          <span className="font-mono font-bold tabular-nums text-[#1E8057]">{d.ok}</span>
        </div>
        <div className="flex items-center justify-between gap-3 text-[11px]">
          <span className="flex items-center gap-1.5"><span className="w-2 h-2 rounded-sm bg-[#EEA028]"/>Escaladas</span>
          <span className="font-mono font-bold tabular-nums text-[#A06A12]">{d.esc}</span>
        </div>
      </div>
    </div>
  </div>;
}

function Kpi({l,v,sub,tone}) {
  const fg = tone==='ok'?'text-[#1E8057]':tone==='warn'?'text-[#D28513]':tone==='danger'?'text-[#B93535]':'text-ink-800';
  return <div className="bg-white rounded-xl border border-slate-100 px-3.5 py-2.5">
    <div className="text-[10px] font-mono uppercase tracking-wider text-ink-400 font-semibold">{l}</div>
    <div className={'font-display font-extrabold text-[22px] tabular-nums leading-none mt-1 '+fg}>{v}</div>
    {sub && <div className="text-[10.5px] text-ink-500 mt-1">{sub}</div>}
  </div>;
}
function Mini({l,v}) {
  return <div>
    <div className="text-[10px] font-mono uppercase text-ink-400">{l}</div>
    <div className="font-mono font-bold text-[13px] tabular-nums text-ink-800 mt-0.5">{v}</div>
  </div>;
}

window.WorkflowsPage = WorkflowsPage;
window.WorkflowDetailPage = WorkflowDetailPage;
