/* ============================================================
   Omnitok Analytics — Asistente IA del mantenedor de retails
   Wizard batch (alcance → generar → revisar → aplicar+impacto),
   Historial con revert y panel de impacto/materialización.
   Backend: /admin/retails/ai/* del worker materializer (OA.ai*).
   Nada escribe en `retails` hasta Aplicar (drafts persistentes).
   ============================================================ */
const { useState:aS, useEffect:aE, useRef:aR } = React;

const AI_PURPLE='#4D4A9D', AI_TEAL='#0E7490', AI_AMBER='#B45309', AI_RED='#B91C1C', AI_VIOLET='#7C3AED';
const aiInp={padding:'6px 9px',border:'1px solid #E5E5E5',borderRadius:8,fontSize:12.5,boxSizing:'border-box'};
const aiBtn=(bg,fg,bd)=>({padding:'7px 12px',border:'1px solid '+(bd||'#E5E5E5'),borderRadius:8,fontSize:12.5,
  fontWeight:700,background:bg||'#fff',color:fg||'#525252',cursor:'pointer'});

function aiConfColor(c){ return c>=0.8?'#15803D':(c>=0.6?AI_AMBER:AI_RED); }
function AiConf({c}){
  return React.createElement('span',{style:{display:'inline-flex',alignItems:'center',gap:6}},
    React.createElement('span',{style:{width:56,height:6,borderRadius:99,background:'#EEE',position:'relative',overflow:'hidden'}},
      React.createElement('span',{style:{position:'absolute',left:0,top:0,bottom:0,borderRadius:99,width:Math.round(c*100)+'%',background:aiConfColor(c)}})),
    React.createElement('b',{style:{fontSize:11.5,color:aiConfColor(c),width:34}},Math.round(c*100)+'%'));
}
function AiChip({a}){
  const es=OA.lang==='es';
  const T={assign:[es?'asociar':'assign','#E0F4F9',AI_TEAL],create:[es?'crear retail':'create','#FDF1DF',AI_AMBER],
    change:[es?'cambiar':'change','#EDE9FE',AI_VIOLET],hide:[es?'ocultar':'hide','#F3F2F8','#8B87A3'],
    none:[es?'sin acción':'none','#F5F5F5','#A3A3A3']};
  const t=T[a]||T.none;
  return React.createElement('span',{style:{fontSize:10.5,fontWeight:800,padding:'2px 9px',borderRadius:99,background:t[1],color:t[2]}},t[0]);
}
/* input de país por catálogo: resuelve 'cl'/'Chile' → CL; inválido = borde rojo */
function AiCountry({value,onPick,width}){
  const [v,setV]=aS(value?value+' — '+OA.countryName(value):'');
  aE(()=>{ setV(value?value+' — '+OA.countryName(value):''); },[value]);
  return React.createElement('input',{list:'oa-country-list',value:v,placeholder:'país…',
    style:{...aiInp,width:width||128},
    onChange:e=>setV(e.target.value),
    onBlur:e=>{ const c=OA.resolveCountry(e.target.value);
      if(!c && e.target.value.trim()!==''){ e.target.style.borderColor=AI_RED; return; }
      e.target.style.borderColor='#E5E5E5'; setV(c?c+' — '+OA.countryName(c):''); onPick(c); }});
}
window.AiCountry=AiCountry;
window.AiChip=AiChip;
window.AiConf=AiConf;

/* ---------------- Panel de impacto ---------------- */
function AiImpact({impact,onDone}){
  const es=OA.lang==='es';
  const [busy,setBusy]=aS('');
  const local=(iso)=>{ try{ return new Date(iso).toLocaleTimeString(es?'es-CL':'en-US',{hour:'2-digit',minute:'2-digit'}); }catch(_){ return ''; } };
  const force=(job)=>{
    const j=job==='rollups'?impact.rollups:impact.impl;
    if(j && j.in_min<10 && !window.confirm((es?'El job corre igual en ':'Job runs anyway in ')+j.in_min+' min. ¿Forzar de todos modos? ('+j.duration+')')) return;
    setBusy(job);
    OA.aiMaterialize(job).then(()=>{ setBusy(''); alert(es?'Materialización completa.':'Materialization done.'); })
      .catch(e=>{ setBusy(''); alert('Error: '+e.message); });
  };
  if(!impact) return null;
  const li=(t)=>React.createElement('li',{style:{margin:'3px 0'}},t);
  return React.createElement('div',{style:{background:'#F0FAFC',border:'1px solid #C8E9F2',borderRadius:10,padding:'10px 14px',fontSize:12.5}},
    React.createElement('b',null,es?'Impacto y materialización':'Impact & materialization'),
    React.createElement('ul',{style:{paddingLeft:18,margin:'8px 0'}},
      li(impact.instant), li(impact.no_backfill),
      li((es?'Rollups 30d: próximo job ':'30d rollups: next job ')+impact.rollups.utc+' ('+local(impact.rollups.iso)+' local · '+(es?'en ':'in ')+impact.rollups.in_min+' min · '+impact.rollups.duration+')'),
      li((es?'Monitor impl: próximo bake ':'Impl monitor: next bake ')+impact.impl.utc+' ('+local(impact.impl.iso)+' local · '+(es?'en ':'in ')+impact.impl.in_min+' min · '+impact.impl.duration+')')),
    React.createElement('div',{style:{display:'flex',gap:8}},
      React.createElement('button',{style:aiBtn(AI_PURPLE,'#fff',AI_PURPLE),disabled:!!busy,onClick:()=>force('rollups')},
        busy==='rollups'?(es?'Materializando…':'Running…'):'⚡ '+(es?'Forzar rollups ahora':'Force rollups now')+' ('+impact.rollups.duration+')'),
      React.createElement('button',{style:aiBtn(AI_PURPLE,'#fff',AI_PURPLE),disabled:!!busy,onClick:()=>force('impl')},
        busy==='impl'?(es?'Materializando…':'Running…'):'⚡ '+(es?'Forzar monitor ahora':'Force monitor now')+' ('+impact.impl.duration+')'),
      React.createElement('span',{style:{flex:1}}),
      onDone&&React.createElement('button',{style:aiBtn(AI_TEAL,'#fff',AI_TEAL),onClick:onDone},es?'Listo':'Done')));
}
window.AiImpact=AiImpact;

/* ---------------- Wizard ---------------- */
function RetailsAIWizard({onClose,onApplied,names}){
  const es=OA.lang==='es';
  const [step,setStep]=aS(1);
  const [scope,setScope]=aS('pending');
  const [cap,setCap]=aS(200);
  const [thr,setThr]=aS(Number(localStorage.getItem('oa_ai_thr')||0.75));
  const [est,setEst]=aS(null); const [estErr,setEstErr]=aS('');
  const [batch,setBatch]=aS(null); const [gen,setGen]=aS(null);
  const [rows,setRows]=aS([]); const [sel,setSel]=aS({});
  const [applyRes,setApplyRes]=aS(null); const [err,setErr]=aS('');
  const [busy,setBusy]=aS(false);
  const cancelRef=aR(false);
  const setThreshold=(v)=>{ setThr(v); localStorage.setItem('oa_ai_thr',String(v)); };

  aE(()=>{ setEst(null); setEstErr('');
    OA.aiEstimate({scope:scope,cap:cap}).then(setEst).catch(e=>setEstErr(e.message));
  },[scope,cap]);

  const loadDrafts=(batchId)=>OA.aiDrafts('batch_id='+encodeURIComponent(batchId)+'&status=draft,edited').then(d=>{
    const rs=d.rows||[]; setRows(rs);
    const s={}; rs.forEach(r=>{ s[r.id]= r.action!=='none' && !r.conflict && (r.confidence>=thr || r.companion===1); });
    setSel(s);
  });

  // Generación PARALELA: el 1er request crea el lote (y procesa un chunk); luego
  // 4 workers en paralelo loopean {batch_id} — el claim atómico del server
  // garantiza que cada request tome hosts DISTINTOS. La barra avanza con los
  // contadores de cada respuesta (merge por máximo).
  const finishedRef=aR(false);
  const mergeGen=(b)=>setGen(g=>(!g||(b.done+b.errors)>=((g.done||0)+(g.errors||0)))?b:g);
  const generate=()=>{ setStep(2); setErr(''); cancelRef.current=false; finishedRef.current=false;
    const finish=(batchId)=>{ if(finishedRef.current) return; finishedRef.current=true;
      setBatch(batchId); loadDrafts(batchId).then(()=>setStep(3)); };
    const workerLoop=(batchId)=>OA.aiBatch({batch_id:batchId}).then(b=>{
      if(cancelRef.current) return;
      mergeGen(b);
      if(b.status==='done') finish(batchId);
      // idle = la cola está tomada por otros workers: esperar antes de re-preguntar
      else if(b.idle) setTimeout(()=>{ if(!cancelRef.current) workerLoop(batchId); },5000);
      else workerLoop(batchId);
    }).catch(e=>{ if(!cancelRef.current) setErr(e.message); });
    OA.aiBatch({scope:scope,cap:cap,threshold:thr}).then(first=>{
      if(cancelRef.current) return;
      mergeGen(first);
      if(first.status==='done'){ finish(first.batch_id); return; }
      for(let i=0;i<4;i++) workerLoop(first.batch_id);
    }).catch(e=>setErr(e.message));
  };
  const cancel=()=>{ cancelRef.current=true; if(gen&&gen.batch_id) OA.aiBatchCancel(gen.batch_id).catch(()=>{}); setStep(1); };

  const reselect=(t)=>{ const s={}; rows.forEach(r=>{ s[r.id]= r.action!=='none' && !r.conflict && (r.confidence>=t || r.companion===1); }); setSel(s); };
  const edit=(r,f,v)=>{ OA.aiDraftEdit(r.id,{[f]:v}).then(d=>{
    setRows(rs=>rs.map(x=>x.id===r.id?{...x,...d.draft}:x)); }).catch(e=>alert(e.message)); };
  const doApply=()=>{ const ids=rows.filter(r=>sel[r.id]).map(r=>r.id);
    if(!ids.length) return;
    setBusy(true); setErr('');
    OA.aiApply({draft_ids:ids}).then(res=>{ setBusy(false); setApplyRes(res); setStep(4); if(onApplied)onApplied(); })
      .catch(e=>{ setBusy(false); setErr(e.message); });
  };

  const stepChip=(n,l)=>React.createElement('span',{key:n,style:{padding:'3px 10px',borderRadius:99,fontSize:11.5,fontWeight:700,
    background:step===n?AI_PURPLE:'#F5F5F5',color:step===n?'#fff':'#737373'}},l);
  const nSel=rows.filter(r=>sel[r.id]).length;
  const over=rows.filter(r=>r.confidence>=thr&&r.action!=='none').length;
  const nConf=rows.filter(r=>r.conflict).length;

  const isExisting=(nm)=>!!nm && (names||[]).some(n=>n.name.toLowerCase()===String(nm).trim().toLowerCase());
  const ACT_LBL={assign:es?'asociar':'assign',create:es?'crear retail':'create',change:es?'cambiar':'change',
    hide:es?'ocultar':'hide',none:es?'sin acción':'none'};
  // tag EN VIVO contra el universo: deja claro si asocia a un retail EXISTENTE
  // o crea uno NUEVO (independiente del name_is_new del server)
  const existTag=(nm)=> nm?(isExisting(nm)
    ?React.createElement('span',{title:es?'Asocia el host a un retail YA existente':'Assigns to an EXISTING retail',
        style:{color:AI_TEAL,fontSize:10.5,fontWeight:800,marginLeft:5,whiteSpace:'nowrap'}},'✓ '+(es?'EXISTENTE':'EXISTING'))
    :React.createElement('span',{title:es?'Creará un retail NUEVO con este nombre':'Creates a NEW retail',
        style:{color:AI_AMBER,fontSize:10.5,fontWeight:800,marginLeft:5,whiteSpace:'nowrap'}},'➕ '+(es?'NUEVO':'NEW'))):null;
  // umbral = slider + selector numérico; en revisión re-selecciona EN VIVO sin
  // ningún request (la confianza ya es output del LLM por fila)
  const thrCtl=(withNote)=>React.createElement('span',{style:{display:'inline-flex',alignItems:'center',gap:8}},
    React.createElement('span',{style:{fontSize:12,fontWeight:700}},es?'Umbral de certeza':'Confidence threshold'),
    React.createElement('input',{type:'range',min:0.5,max:0.95,step:0.05,value:thr,style:{accentColor:AI_PURPLE},
      onChange:e=>{ const t=Number(e.target.value); setThreshold(t); if(step===3) reselect(t); }}),
    React.createElement('select',{value:String(Math.round(thr*100)),style:{...aiInp,padding:'4px 6px'},
      onChange:e=>{ const t=Number(e.target.value)/100; setThreshold(t); if(step===3) reselect(t); }},
      [50,55,60,65,70,75,80,85,90,95].map(v=>React.createElement('option',{key:v,value:String(v)},v+'%'))),
    withNote&&React.createElement('span',{style:{fontSize:10.5,color:'#8B87A3'}},
      es?'(re-selección local, sin nuevo request)':'(local re-select, no new request)'));

  let body=null;
  if(step===1) body=React.createElement('div',null,
    React.createElement('div',{style:{display:'flex',gap:12,alignItems:'center',flexWrap:'wrap'}},
      React.createElement('div',{className:'seg'},
        ['pending','named','all'].map(s0=>React.createElement('button',{key:s0,className:scope===s0?'on':'',
          onClick:()=>setScope(s0)},s0==='pending'?'Pending':(s0==='named'?(es?'Asociados':'Named'):(es?'Todos':'All'))))),
      React.createElement('label',{style:{fontSize:12,fontWeight:700}},'Cap ',
        React.createElement('input',{type:'number',value:cap,min:1,max:300,style:{...aiInp,width:70},
          onChange:e=>setCap(Math.max(1,Math.min(300,Number(e.target.value)||1)))})),
      thrCtl(false)),
    estErr&&React.createElement('div',{style:{color:AI_RED,fontSize:12.5,marginTop:10}},estErr),
    est&&React.createElement('div',{style:{background:'#F0FAFC',border:'1px solid #C8E9F2',borderRadius:10,padding:'9px 12px',fontSize:12.5,marginTop:10}},
      '📊 ',React.createElement('b',null,est.hosts),' hosts ('+est.available+' disponibles) · '+est.calls+' '+(es?'llamada(s)':'call(s)')+
      ' · ~'+(est.est_tokens_in||0).toLocaleString()+' tokens in / ~'+(est.est_tokens_out||0).toLocaleString()+' out · ',
      React.createElement('b',null,'~US$ '+est.est_cost_usd),' · ',React.createElement('b',null,est.model)),
    React.createElement('div',{style:{textAlign:'right',marginTop:12}},
      React.createElement('button',{style:aiBtn(AI_PURPLE,'#fff',AI_PURPLE),disabled:!est||!est.hosts,
        onClick:generate},(es?'Generar recomendaciones':'Generate recommendations')+' →')));

  if(step===2) body=React.createElement('div',null,
    React.createElement('div',{style:{fontSize:12.5,marginBottom:6}},
      React.createElement('b',null,es?'Generando…':'Generating…'),' ',
      gen?('lote '+String(gen.batch_id||'').slice(0,8)+'…'):''),
    React.createElement('div',{style:{height:10,background:'#EEE',borderRadius:99,overflow:'hidden',margin:'8px 0'}},
      React.createElement('div',{style:{height:'100%',borderRadius:99,background:AI_PURPLE,transition:'width .4s',
        width:(gen&&gen.total?Math.round(100*(gen.done+gen.errors)/gen.total):4)+'%'}})),
    React.createElement('div',{style:{fontSize:12,color:'#737373'}},
      gen?((gen.done+gen.errors)+' / '+gen.total+' hosts · '+gen.errors+' error(es)'):(es?'iniciando…':'starting…')),
    err&&React.createElement('div',{style:{color:AI_RED,fontSize:12.5,marginTop:8}},err),
    React.createElement('div',{style:{textAlign:'right',marginTop:10}},
      React.createElement('button',{style:aiBtn(),onClick:cancel},es?'Cancelar':'Cancel')));

  if(step===3) body=React.createElement('div',null,
    React.createElement('div',{style:{display:'flex',gap:12,alignItems:'center',flexWrap:'wrap',marginBottom:8}},
      thrCtl(true),
      React.createElement('span',{style:{fontSize:12,color:'#737373'}},
        rows.length+' '+(es?'recomendaciones':'recs')+' · '+over+' '+(es?'sobre umbral':'over')+' · '+nSel+' '+(es?'seleccionadas':'selected')+
        (nConf?(' · '+nConf+' '+(es?'conflicto(s)':'conflict(s)')):'')),
      React.createElement('span',{style:{flex:1}}),
      err&&React.createElement('span',{style:{color:AI_RED,fontSize:12}},err),
      React.createElement('button',{style:aiBtn(AI_TEAL,'#fff',AI_TEAL),disabled:!nSel||busy,onClick:doApply},
        busy?'…':((es?'Aplicar ':'Apply ')+nSel+' →'))),
    React.createElement('div',{style:{maxHeight:'55vh',overflow:'auto'}},
      React.createElement('table',{className:'tbl'},
        React.createElement('thead',null,React.createElement('tr',null,
          ['','Hostname',es?'Acción':'Action',es?'Retail (existente o nuevo)':'Retail (existing or new)',es?'País':'Country',es?'Confianza':'Confidence',es?'Razón':'Reason'].map((h,i)=>
            React.createElement('th',{key:i},h)))),
        React.createElement('tbody',null,rows.map(r=>{
          const editable=r.action==='assign'||r.action==='create'||r.action==='change';
          return React.createElement('tr',{key:r.id,style:r.action==='none'?{opacity:.6}:null},
            React.createElement('td',null,React.createElement('input',{type:'checkbox',checked:!!sel[r.id],
              disabled:r.action==='none',onChange:e=>setSel(s=>({...s,[r.id]:e.target.checked}))})),
            React.createElement('td',null,React.createElement('span',{className:'mono',style:{fontSize:12}},r.host),
              r.conflict?React.createElement('span',{title:es?'La fila cambió después de generar el draft':'Row changed after draft',
                style:{marginLeft:6,fontSize:10,fontWeight:800,color:AI_RED,background:'#FEE2E2',borderRadius:99,padding:'1px 7px'}},'✎ conflicto'):null,
              r.companion===1?React.createElement('span',{title:es?'Renombre automático: el nombre base colisiona entre países':'Auto-rename: base name collides across countries',
                style:{marginLeft:6,fontSize:10,fontWeight:800,color:'#854D0E',background:'#FEF9C3',borderRadius:99,padding:'1px 7px'}},es?'regla de nombres':'naming rule'):null),
            // acción SIEMPRE editable: un 'ocultar'/'sin acción' puede pasar a
            // asociar/crear con retail y país manuales
            React.createElement('td',null,React.createElement('select',{value:r.action,
              style:{...aiInp,padding:'4px 6px',fontSize:11.5,fontWeight:700},
              onChange:e=>{ const a=e.target.value; edit(r,'action',a);
                if((a==='assign'||a==='create'||a==='change')&&!sel[r.id]) setSel(s=>({...s,[r.id]:true}));
                if(a==='none') setSel(s=>({...s,[r.id]:false})); }},
              Object.keys(ACT_LBL).map(a=>React.createElement('option',{key:a,value:a},ACT_LBL[a])))),
            React.createElement('td',null,editable?React.createElement('span',{style:{display:'inline-flex',alignItems:'center'}},
              React.createElement('input',{list:'oa-retail-names',defaultValue:r.name||'',style:{...aiInp,width:168},
                placeholder:es?'elige o escribe…':'pick or type…',
                onBlur:e=>{ if(e.target.value!==(r.name||'')) edit(r,'name',e.target.value); }}),
              existTag(r.name)):
              React.createElement('button',{title:es?'Asignar retail manualmente':'Assign retail manually',
                style:{...aiBtn(),padding:'3px 9px',fontSize:11},
                onClick:()=>{ edit(r,'action','assign'); }},'✎ '+(es?'manual':'manual'))),
            React.createElement('td',null,editable?React.createElement(AiCountry,{value:r.country,width:120,
              onPick:c=>edit(r,'country',c)}):'—'),
            React.createElement('td',null,React.createElement(AiConf,{c:r.confidence||0})),
            React.createElement('td',{style:{maxWidth:240,fontSize:11.5,color:'#5B5470'},title:r.reasoning||''},
              (r.reasoning||'').slice(0,88)+((r.reasoning||'').length>88?'…':'')));
        })))));

  if(step===4) body=React.createElement('div',null,
    applyRes&&React.createElement('div',{style:{background:'#F0FDF4',border:'1px solid #BBF7D0',borderRadius:10,padding:'9px 12px',fontSize:12.5,marginBottom:10}},
      '✅ ',React.createElement('b',null,applyRes.applied),' ',(es?'cambio(s) aplicados':'change(s) applied'),
      applyRes.skipped&&applyRes.skipped.length?(' · '+applyRes.skipped.length+' '+(es?'saltado(s): ':'skipped: ')+
        applyRes.skipped.map(s0=>s0.host+' ('+s0.reason+')').join(', ')):null,
      ' — ',(es?'reversible desde el Historial':'revertible from History')),
    applyRes&&React.createElement(AiImpact,{impact:applyRes.impact,onDone:onClose}));

  return React.createElement('div',{style:{position:'fixed',inset:0,background:'rgba(20,18,40,.45)',zIndex:60,
      display:'flex',alignItems:'flex-start',justifyContent:'center',padding:'40px 16px',overflow:'auto'},
      onClick:e=>{ if(e.target===e.currentTarget&&step!==2) onClose(); }},
    React.createElement('div',{style:{background:'#fff',borderRadius:14,maxWidth:1040,width:'100%',padding:'16px 20px',boxShadow:'0 20px 60px rgba(0,0,0,.25)'}},
      React.createElement('div',{style:{display:'flex',alignItems:'center',gap:10,marginBottom:8}},
        React.createElement('b',{style:{fontSize:14.5}},'✨ '+(es?'Asistente IA — recomendaciones en lote':'AI assistant — batch recommendations')),
        React.createElement('button',{style:{...aiBtn(),border:'none',marginLeft:'auto',fontWeight:800},onClick:onClose},'×')),
      React.createElement('div',{style:{display:'flex',gap:6,alignItems:'center',marginBottom:12}},
        stepChip(1,'1 · '+(es?'Alcance':'Scope')),React.createElement('span',{style:{color:'#D4D4D4'}},'→'),
        stepChip(2,'2 · '+(es?'Generar':'Generate')),React.createElement('span',{style:{color:'#D4D4D4'}},'→'),
        stepChip(3,'3 · '+(es?'Revisar':'Review')),React.createElement('span',{style:{color:'#D4D4D4'}},'→'),
        stepChip(4,'4 · '+(es?'Aplicar e impacto':'Apply & impact'))),
      body));
}
window.RetailsAIWizard=RetailsAIWizard;

/* ---------------- Historial ---------------- */
function RetailsAIHistory({onClose,onChanged}){
  const es=OA.lang==='es';
  const [rows,setRows]=aS(null); const [q,setQ]=aS(''); const [busy,setBusy]=aS('');
  const load=()=>OA.aiAudit(q?('host='+encodeURIComponent(q)):'').then(d=>setRows(d.rows||[])).catch(()=>setRows([]));
  aE(()=>{ load(); },[q]);
  const revert=(p,label)=>{ if(!window.confirm((es?'¿Revertir ':'Revert ')+label+'?')) return;
    setBusy(label);
    OA.aiRevert(p).then(d=>{ setBusy(''); load(); if(onChanged)onChanged();
      alert((es?'Revertido(s): ':'Reverted: ')+d.reverted); })
      .catch(e=>{ setBusy(''); alert('Error: '+e.message); }); };
  const groups={};
  (rows||[]).forEach(a=>{ const k=a.apply_batch_id||('#'+a.id); (groups[k]=groups[k]||[]).push(a); });
  return React.createElement('div',{style:{position:'fixed',top:0,right:0,width:560,maxWidth:'94vw',height:'100vh',
      background:'#fff',borderLeft:'1px solid #E5E5E5',boxShadow:'-12px 0 40px rgba(0,0,0,.12)',zIndex:70,padding:16,overflow:'auto'}},
    React.createElement('div',{style:{display:'flex',alignItems:'center',gap:8,marginBottom:10}},
      React.createElement('b',{style:{fontSize:13.5}},'🕘 '+(es?'Historial de cambios de retails':'Retail change history')),
      React.createElement('button',{style:{...aiBtn(),border:'none',marginLeft:'auto',fontWeight:800},onClick:onClose},'×')),
    React.createElement('input',{placeholder:es?'Filtrar por host…':'Filter by host…',value:q,
      onChange:e=>setQ(e.target.value),style:{...aiInp,width:'100%',marginBottom:10}}),
    rows===null?React.createElement('div',{className:'empty'},React.createElement('div',{className:'spinner'})):
    !rows.length?React.createElement('div',{className:'empty'},es?'Sin cambios registrados':'No changes yet'):
    Object.entries(groups).map(([k,items])=>{
      const isBatch=!k.startsWith('#');
      const revertible=items.filter(i=>!i.reverted_by&&i.actor!=='revert');
      return React.createElement('div',{key:k,style:{background:'#F3F2F8',borderRadius:10,padding:'9px 11px',marginBottom:10}},
        React.createElement('div',{style:{display:'flex',alignItems:'center',gap:8,marginBottom:5}},
          React.createElement('b',{style:{fontSize:11.5}},isBatch?((es?'Lote ':'Batch ')+k.slice(0,8)+'…'):(es?'Cambio individual':'Single change')),
          React.createElement('span',{style:{fontSize:11,color:'#737373'}},items.length+(es?' cambio(s)':' change(s)')),
          isBatch&&revertible.length?React.createElement('button',{style:{...aiBtn(),fontSize:11,marginLeft:'auto'},
            disabled:busy===k,onClick:()=>revert({apply_batch_id:k},(es?'lote completo (':'full batch (')+revertible.length+')')},
            '↩ '+(es?'Revertir lote (':'Revert batch (')+revertible.length+')'):null),
        items.map(a=>React.createElement('div',{key:a.id,style:{display:'flex',gap:8,alignItems:'center',fontSize:11.8,
            padding:'4px 0',borderTop:'1px solid #E9E7F2',
            textDecoration:a.reverted_by?'line-through':'none',opacity:a.reverted_by?.55:1}},
          React.createElement('span',{className:'mono',style:{flex:1,minWidth:0,overflow:'hidden',textOverflow:'ellipsis'}},a.host),
          React.createElement('span',{style:{color:'#737373'}},
            (a.prev_name||'pending')+(a.prev_status==='hidden'?' (oculto)':'')+' → '),
          React.createElement('b',null,a.new_status==='hidden'?(es?'OCULTO':'HIDDEN'):((a.new_name||'')+(a.new_country?(' · '+a.new_country):''))),
          React.createElement('span',{style:{fontSize:10,fontWeight:800,padding:'1px 7px',borderRadius:99,
            background:a.actor==='ai-apply'?'#EDE9FE':(a.actor==='revert'?'#F3F2F8':'#E0F4F9'),
            color:a.actor==='ai-apply'?AI_VIOLET:(a.actor==='revert'?'#8B87A3':AI_TEAL)}},
            a.actor==='ai-apply'?'IA':(a.actor==='revert'?'revert':'manual')),
          React.createElement('span',{style:{color:'#A3A3A3',fontSize:10.5,whiteSpace:'nowrap'}},String(a.created_at||'').slice(5,16)),
          (!a.reverted_by&&a.actor!=='revert')?React.createElement('button',{title:es?'Revertir este cambio':'Revert this change',
            style:{...aiBtn(),padding:'2px 8px',fontSize:11},onClick:()=>revert({audit_id:a.id},a.host)},'↩'):null)));
    }));
}
window.RetailsAIHistory=RetailsAIHistory;
