// ─────────────────────────────────────────────────────
// GUT-63 (F3.1) — Expedientes.
// Vista lista + drawer de expediente con pestañas
// (info | mediciones | materiales | fabricación | compras | documentos).
// El expediente ES un pedido (pedidos.id) con numero_expediente.
// Pestañas de features hermanas (F3.2..F3.5) degradan con gracia.
// ─────────────────────────────────────────────────────

const EXP_ESTADO_PILL = {
  abierto:    { cls: 'info', label: 'Abierto' },
  en_curso:   { cls: 'warn', label: 'En curso' },
  cerrado:    { cls: 'ok',   label: 'Cerrado' },
};
const ExpedienteEstadoPill = ({ v }) => {
  const meta = EXP_ESTADO_PILL[(v || '').toLowerCase()] || { cls: 'info', label: v || '—' };
  return <span className={`pill ${meta.cls}`}><span className="d"/>{meta.label}</span>;
};

// ── Estado de producción + resumen de materiales ──
// (absorbido de la vista Pedidos legacy al consolidarla aquí)
const EXP_MAT_LABELS = {
  medicion:'Medición', perfiles:'Perfiles', lacado:'Lacado', vidrios:'Vidrios', tubos:'Tubos',
  panel_sandwich:'Panel Sándwich', accesorios:'Accesorios', cerraduras:'Cerraduras',
  toldo_estores:'Toldo/Estores', otros_materiales:'Otros materiales',
};
const expMatVal = (v) => {
  if (!v || !String(v).trim()) return null;
  const u = String(v).trim().toUpperCase();
  if (u.startsWith('OK'))   return 'ok';
  if (u.startsWith('PDTE')) return 'warn';
  return 'text';
};
const expMatsPendientes = (r) =>
  Object.keys(EXP_MAT_LABELS).filter(k => expMatVal(r[k]) === 'warn');

const EXP_PROD_PILL = {
  PROCESANDO:            { cls:'info', label:'En producción' },
  PARCIAL:               { cls:'warn', label:'Parcial' },
  LISTO_PARA_PRODUCCION: { cls:'ok',   label:'Listo p/ producción' },
  COMPLETADO:            { cls:'ok',   label:'Completado' },
};
const ExpedienteProdPill = ({ v }) => {
  if (!v || !String(v).trim()) return <span className="muted">—</span>;
  const meta = EXP_PROD_PILL[String(v).toUpperCase()] || { cls:'info', label:v };
  return <span className={`pill ${meta.cls}`}><span className="d"/>{meta.label}</span>;
};

const MaterialesResumenPill = ({ r }) => {
  const pdte = expMatsPendientes(r);
  const ok = Object.keys(EXP_MAT_LABELS).filter(k => expMatVal(r[k]) === 'ok');
  if (!pdte.length && !ok.length) return <span className="muted">—</span>;
  if (!pdte.length) return <span className="pill ok"><span className="d"/>Materiales OK</span>;
  return (
    <span className="pill warn" title={'Pendiente: ' + pdte.map(k => EXP_MAT_LABELS[k]).join(', ')}>
      <span className="d"/>{pdte.length} pdte
    </span>
  );
};

// ── Bloque de hitos de cobro (editable, marcar-pagado, timeline) ──
const CobrosPanel = ({ pedidoId, cobros, onChange, onToast }) => {
  const [rows, setRows] = React.useState(cobros || []);
  const [adding, setAdding] = React.useState(false);
  const [draft, setDraft] = React.useState({ concepto: '', porcentaje: '', importe: '' });
  React.useEffect(() => { setRows(cobros || []); }, [cobros]);

  const toast = (m, e) => onToast && onToast(m, e);

  // Plantillas rápidas de hitos.
  const aplicarPlantilla = async (reparto) => {
    if (rows.length && !confirm('Esto añadirá nuevos hitos al expediente. ¿Continuar?')) return;
    try {
      for (let i = 0; i < reparto.length; i++) {
        const pct = reparto[i];
        await API.post(`/api/expedientes/${pedidoId}/cobros`, {
          concepto: `Hito ${i + 1} (${pct}%)`, porcentaje: pct, orden: rows.length + i,
        });
      }
      toast('Hitos creados ✓');
      onChange && onChange();
    } catch (e) { toast(e.message || 'Error al crear hitos', true); }
  };

  const addCobro = async () => {
    try {
      await API.post(`/api/expedientes/${pedidoId}/cobros`, {
        concepto: draft.concepto || null,
        porcentaje: draft.porcentaje || null,
        importe: draft.importe || null,
        orden: rows.length,
      });
      setDraft({ concepto: '', porcentaje: '', importe: '' });
      setAdding(false);
      onChange && onChange();
    } catch (e) { toast(e.message || 'Error al añadir hito', true); }
  };

  const marcarPagado = async (c) => {
    try {
      await API.post(`/api/expedientes/${pedidoId}/cobros/${c.id}/pagar`, {});
      toast('Cobro marcado como pagado ✓');
      onChange && onChange();
    } catch (e) { toast(e.message || 'Error al marcar pagado', true); }
  };

  const marcarPendiente = async (c) => {
    try {
      await API.put(`/api/expedientes/${pedidoId}/cobros/${c.id}`, { estado: 'pendiente' });
      onChange && onChange();
    } catch (e) { toast(e.message || 'Error', true); }
  };

  const delCobro = async (c) => {
    if (!confirm('¿Eliminar este hito de cobro?')) return;
    try {
      await API.del(`/api/expedientes/${pedidoId}/cobros/${c.id}`);
      onChange && onChange();
    } catch (e) { toast(e.message || 'Error al eliminar', true); }
  };

  const pctTotal = rows.reduce((s, c) => s + Number(c.porcentaje || 0), 0);
  const pagados = rows.filter(c => c.estado === 'pagado').length;

  return (
    <div>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:10}}>
        <div className="section-title" style={{margin:0}}>Hitos de cobro</div>
        <div style={{display:'flex',gap:6}}>
          <button className="btn ghost sm" onClick={()=>aplicarPlantilla([50,40,10])}>50/40/10</button>
          <button className="btn ghost sm" onClick={()=>aplicarPlantilla([50,25,25])}>50/25/25</button>
          <button className="btn primary sm" onClick={()=>setAdding(true)}><Icon name="plus" size={12}/> Hito</button>
        </div>
      </div>

      {rows.length === 0 && !adding && (
        <div className="muted" style={{fontSize:12,padding:'8px 0'}}>
          Sin hitos de cobro. Usa una plantilla (50/40/10…) o añade uno manualmente.
        </div>
      )}

      {rows.length > 0 && (
        <table className="tbl" style={{fontSize:12.5,marginBottom:8}}>
          <thead>
            <tr><th>Concepto</th><th>%</th><th>Importe</th><th>Estado</th><th>Fecha</th><th></th></tr>
          </thead>
          <tbody>
            {rows.map(c => (
              <tr key={c.id}>
                <td>{c.concepto || '—'}</td>
                <td className="num">{c.porcentaje != null ? `${Number(c.porcentaje)}%` : '—'}</td>
                <td className="num">{c.importe != null ? `${Number(c.importe).toFixed(2)} €` : '—'}</td>
                <td>
                  {c.estado === 'pagado'
                    ? <span className="pill ok"><span className="d"/>Pagado</span>
                    : <span className="pill warn"><span className="d"/>Pendiente</span>}
                </td>
                <td className="num muted">{c.fecha || '—'}</td>
                <td style={{whiteSpace:'nowrap'}}>
                  {c.estado === 'pagado'
                    ? <button className="btn ghost sm tip" data-tip="Marcar pendiente" onClick={()=>marcarPendiente(c)}>↺</button>
                    : <button className="btn primary sm tip" data-tip="Marcar pagado" onClick={()=>marcarPagado(c)}><Icon name="check" size={12}/></button>}
                  <button className="btn ghost sm tip" data-tip="Eliminar" style={{color:'var(--err)'}} onClick={()=>delCobro(c)}><Icon name="trash" size={12}/></button>
                </td>
              </tr>
            ))}
            <tr style={{fontWeight:600}}>
              <td>Total</td>
              <td className="num">{pctTotal}%</td>
              <td colSpan={4} className="muted">{pagados}/{rows.length} pagados</td>
            </tr>
          </tbody>
        </table>
      )}

      {adding && (
        <div className="fields-grid" style={{marginBottom:8,alignItems:'end'}}>
          <div className="field"><label>Concepto</label><input value={draft.concepto} onChange={e=>setDraft(d=>({...d,concepto:e.target.value}))}/></div>
          <div className="field"><label>%</label><input type="number" value={draft.porcentaje} onChange={e=>setDraft(d=>({...d,porcentaje:e.target.value}))}/></div>
          <div className="field"><label>Importe (€)</label><input type="number" value={draft.importe} onChange={e=>setDraft(d=>({...d,importe:e.target.value}))}/></div>
          <div className="field" style={{display:'flex',gap:6}}>
            <button className="btn primary sm" onClick={addCobro}>Guardar</button>
            <button className="btn ghost sm" onClick={()=>{setAdding(false);setDraft({concepto:'',porcentaje:'',importe:''});}}>Cancelar</button>
          </div>
        </div>
      )}

      {/* Timeline de cobros */}
      {rows.length > 0 && (
        <div style={{marginTop:14}}>
          <div className="section-title">Timeline</div>
          <div style={{display:'flex',flexDirection:'column',gap:0,paddingLeft:6}}>
            {rows.map((c, i) => {
              const done = c.estado === 'pagado';
              return (
                <div key={c.id} style={{display:'flex',gap:10,alignItems:'flex-start',position:'relative',paddingBottom:i<rows.length-1?14:0}}>
                  <div style={{display:'flex',flexDirection:'column',alignItems:'center'}}>
                    <span style={{width:12,height:12,borderRadius:'50%',background:done?'var(--ok)':'var(--warn)',flexShrink:0,marginTop:2}}/>
                    {i < rows.length - 1 && <span style={{width:2,flex:1,minHeight:18,background:'var(--line)'}}/>}
                  </div>
                  <div style={{paddingBottom:6}}>
                    <div style={{fontSize:12.5,fontWeight:600}}>{c.concepto || `Hito ${i+1}`}</div>
                    <div className="muted" style={{fontSize:11.5}}>
                      {c.porcentaje != null ? `${Number(c.porcentaje)}% · ` : ''}
                      {done ? `Pagado${c.fecha ? ' el ' + c.fecha : ''}` : 'Pendiente'}
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
};

// ── Drawer de expediente ──────────────────────────────
const ExpedienteDrawer = ({ pedidoId, onClose, onToast, onRefresh }) => {
  const [exp, setExp] = React.useState(null);
  const [ordenesCount, setOrdenesCount] = React.useState(0);
  const [partes, setPartes] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [tab, setTab] = React.useState('info');
  const [instalDraft, setInstalDraft] = React.useState('');

  const load = React.useCallback(() => {
    if (!pedidoId) return;
    setLoading(true);
    Promise.all([
      API.get(`/api/expedientes/${pedidoId}`),
      API.get(`/api/expedientes/${pedidoId}/ordenes`).catch(() => []),
      API.get(`/api/expedientes/${pedidoId}/partes`).catch(() => []),
    ])
      .then(([e, ocs, prts]) => {
        setExp(e);
        setOrdenesCount(Array.isArray(ocs) ? ocs.length : 0);
        setPartes(Array.isArray(prts) ? prts : []);
      })
      .catch(e => onToast && onToast(e.message || 'Error al cargar expediente', true))
      .finally(() => setLoading(false));
  }, [pedidoId]);

  React.useEffect(() => { setTab('info'); setInstalDraft(''); load(); }, [pedidoId]);

  const reload = () => { load(); onRefresh && onRefresh(); };

  const open = !!pedidoId;
  const d = exp || {};

  // ── Acciones de ciclo de vida ───────────────────────────────
  const setEstado = async (estado) => {
    if (busy) return;
    setBusy(true);
    try {
      await API.put(`/api/expedientes/${pedidoId}`, { estado_expediente: estado });
      reload();
    } catch (e) { onToast && onToast(e.message || 'Error al cambiar estado', true); }
    finally { setBusy(false); }
  };
  const cerrar = async () => { if (confirm('¿Cerrar este expediente?')) await setEstado('cerrado'); };
  const reabrir = () => setEstado('en_curso');

  // Marca pagado el primer hito de cobro pendiente (la "señal").
  const marcarSenal = async () => {
    const pend = (d.cobros || []).find(c => c.estado !== 'pagado');
    if (!pend) return;
    setBusy(true);
    try {
      await API.post(`/api/expedientes/${pedidoId}/cobros/${pend.id}/pagar`, {});
      onToast && onToast('Cobro de señal registrado ✓');
      reload();
    } catch (e) { onToast && onToast(e.message || 'Error', true); }
    finally { setBusy(false); }
  };

  const guardarInstal = async () => {
    if (!instalDraft) return;
    setBusy(true);
    try {
      await API.put(`/api/expedientes/${pedidoId}`, { fecha_instalacion: instalDraft });
      onToast && onToast('Fecha de instalación guardada ✓');
      setInstalDraft('');
      reload();
    } catch (e) { onToast && onToast(e.message || 'Error', true); }
    finally { setBusy(false); }
  };

  // ── Siguiente paso guiado (banner) ──────────────────────────
  const estadoExp = (d.estado_expediente || '').toLowerCase();
  const cobros = d.cobros || [];
  const senalPagada = cobros.some(c => c.estado === 'pagado');
  const hayCobroPendiente = cobros.some(c => c.estado !== 'pagado');
  const tieneOC = ordenesCount > 0;
  const tieneInstal = !!d.fecha_instalacion;
  let nextStep = null;
  if (estadoExp && estadoExp !== 'cerrado') {
    if (!senalPagada) nextStep = 'senal';
    else if (!tieneOC) nextStep = 'material';
    else if (!tieneInstal) nextStep = 'instalacion';
    else nextStep = 'cerrar';
  }

  return (
    <>
      <div className={`drawer-bg ${open ? 'open' : ''}`} onClick={onClose}/>
      <div className={`drawer ${open ? 'open' : ''}`}>
        <div className="dr-head">
          <span className="id mono">{d.numero_expediente ? `Exp. ${d.numero_expediente}` : '—'}</span>
          <h2>{d.cliente || '—'}</h2>
          <ExpedienteEstadoPill v={d.estado_expediente}/>
          <div className="actions">
            {d.numero_expediente && estadoExp !== 'cerrado' && (
              <button className="btn ghost sm" onClick={cerrar} disabled={busy}><Icon name="check" size={12}/> Cerrar expediente</button>
            )}
            {estadoExp === 'cerrado' && (
              <button className="btn ghost sm" onClick={reabrir} disabled={busy}>Reabrir</button>
            )}
            <button className="icon-btn" onClick={onClose}><Icon name="x"/></button>
          </div>
        </div>

        <div className="dr-tabs">
          <button className={tab==='info'?'on':''}        onClick={()=>setTab('info')}>Info</button>
          <button className={tab==='mediciones'?'on':''}  onClick={()=>setTab('mediciones')}>Mediciones</button>
          <button className={tab==='materiales'?'on':''}  onClick={()=>setTab('materiales')}>Materiales</button>
          <button className={tab==='fabricacion'?'on':''} onClick={()=>setTab('fabricacion')}>Fabricación</button>
          <button className={tab==='compras'?'on':''}     onClick={()=>setTab('compras')}>Compras</button>
          <button className={tab==='documentos'?'on':''}  onClick={()=>setTab('documentos')}>Documentos</button>
        </div>

        <div className="dr-body">
          {loading && <div style={{padding:30,textAlign:'center',color:'var(--ink-3)'}}>Cargando…</div>}

          {!loading && tab === 'info' && (
            <div className="dr-grid">
              <div>
                {nextStep && (
                  <div style={{display:'flex',alignItems:'center',gap:12,padding:'12px 14px',marginBottom:14,background:'var(--surface-2,#f4f3ff)',border:'1px solid var(--line)',borderLeft:'3px solid var(--accent,#6c5ce7)',borderRadius:8}}>
                    <Icon name="bolt" size={18}/>
                    <div style={{flex:1,minWidth:0}}>
                      <div style={{fontSize:10,fontWeight:700,letterSpacing:.5,textTransform:'uppercase',color:'var(--accent,#6c5ce7)'}}>Siguiente paso</div>
                      <div style={{fontSize:13.5,fontWeight:600}}>
                        {nextStep === 'senal'       && 'Registra el cobro de la señal'}
                        {nextStep === 'material'    && 'Pide el material a proveedor'}
                        {nextStep === 'instalacion' && 'Fija la fecha de instalación'}
                        {nextStep === 'cerrar'      && 'Todo listo · puedes cerrar el expediente'}
                      </div>
                    </div>
                    {nextStep === 'senal' && hayCobroPendiente && (
                      <button className="btn primary sm" onClick={marcarSenal} disabled={busy}><Icon name="check" size={12}/> Marcar señal pagada</button>
                    )}
                    {nextStep === 'material' && (
                      <button className="btn primary sm" onClick={()=>setTab('compras')}><Icon name="cart" size={12}/> Ir a Compras</button>
                    )}
                    {nextStep === 'instalacion' && (
                      <span style={{display:'flex',gap:6,alignItems:'center'}}>
                        <input type="date" value={instalDraft} onChange={e=>setInstalDraft(e.target.value)} style={{fontSize:12,padding:'5px 8px',border:'1px solid var(--line)',borderRadius:6}}/>
                        <button className="btn primary sm" onClick={guardarInstal} disabled={busy || !instalDraft}>Guardar</button>
                      </span>
                    )}
                    {nextStep === 'cerrar' && (
                      <button className="btn primary sm" onClick={cerrar} disabled={busy}><Icon name="check" size={12}/> Cerrar expediente</button>
                    )}
                  </div>
                )}
                <div className="section-title">Cabecera</div>
                <div className="fields-grid">
                  <div className="field"><label>Nº expediente</label><div className="v mono">{d.numero_expediente || '—'}</div></div>
                  <div className="field"><label>Nº pedido</label><div className="v mono">{d.numero_pedido || '—'}</div></div>
                  <div className="field full"><label>Cliente</label><div className="v">{d.cliente || '—'}</div></div>
                  <div className="field"><label>Estado</label><div className="v"><ExpedienteEstadoPill v={d.estado_expediente}/></div></div>
                  <div className="field"><label>F. confirmación</label><div className="v">{d.fecha_confirmacion || '—'}</div></div>
                  <div className="field"><label>F. pedido</label><div className="v">{d.fecha_pedido || '—'}</div></div>
                  <div className="field"><label>F. instalación</label><div className="v">{d.fecha_instalacion || '—'}</div></div>
                </div>

                {/* Enlaces de navegación: lead → presupuesto → expediente */}
                <div style={{display:'flex',gap:8,margin:'4px 0 14px'}}>
                  {d.presupuesto_id && (
                    <button className="btn ghost sm" onClick={()=>window.dispatchEvent(new CustomEvent('erp:open-presupuesto',{detail:{id:d.presupuesto_id}}))}>
                      <Icon name="eye" size={12}/> Ver presupuesto
                    </button>
                  )}
                  {d.presupuesto_id && (
                    <button className="btn ghost sm" onClick={()=>API.download(`/api/presupuestos/${d.presupuesto_id}/pdf`, `presupuesto_${d.presupuesto_id}.pdf`).catch(e=>onToast&&onToast(e.message,true))}>
                      <Icon name="print" size={12}/> PDF presupuesto
                    </button>
                  )}
                </div>

                {d.productos_resumen && (
                  <>
                    <div className="section-title">Productos</div>
                    <div className="muted" style={{fontSize:12.5,marginBottom:8}}>{d.productos_resumen}</div>
                  </>
                )}

                <CobrosPanel pedidoId={pedidoId} cobros={d.cobros || []} onChange={reload} onToast={onToast}/>

                {/* GUT-188 — Partes de instalación vinculados a este expediente */}
                <div className="section-title" style={{marginTop:18}}>Partes de instalación</div>
                {partes.length === 0 ? (
                  <div className="muted" style={{fontSize:12.5,marginBottom:8}}>Sin partes vinculados.</div>
                ) : (
                  <table className="mini-table" style={{width:'100%',fontSize:12.5,borderCollapse:'collapse'}}>
                    <thead>
                      <tr style={{textAlign:'left',color:'var(--ink-3)'}}>
                        <th style={{padding:'4px 6px'}}>Fecha</th>
                        <th style={{padding:'4px 6px'}}>Operario</th>
                        <th style={{padding:'4px 6px'}}>Instalador</th>
                        <th style={{padding:'4px 6px',textAlign:'right'}}>Kms</th>
                      </tr>
                    </thead>
                    <tbody>
                      {partes.map(pt => (
                        <tr key={pt.id} style={{borderTop:'1px solid var(--line)'}}>
                          <td style={{padding:'4px 6px'}}>{pt.fecha || '—'}</td>
                          <td style={{padding:'4px 6px'}}>{pt.operario || '—'}</td>
                          <td style={{padding:'4px 6px'}}>{pt.nombre || '—'}</td>
                          <td style={{padding:'4px 6px',textAlign:'right'}}>{pt.total_kms != null ? pt.total_kms : '—'}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                )}
              </div>
            </div>
          )}

          {!loading && tab === 'mediciones' && (
            window.MedicionesPanel
              ? <window.MedicionesPanel expedienteId={pedidoId} onToast={onToast}/>
              : <div className="muted" style={{fontSize:12,padding:20}}>Mediciones — cargando módulo…</div>
          )}

          {!loading && tab === 'materiales' && (
            window.BomPanel
              ? <window.BomPanel expedienteId={pedidoId} onToast={onToast}/>
              : <div className="muted" style={{fontSize:12,padding:20}}>BOM / materiales — disponible en F3.3.</div>
          )}

          {!loading && tab === 'fabricacion' && (
            window.FabricacionPanel
              ? <window.FabricacionPanel expedienteId={pedidoId} onToast={onToast}/>
              : <div className="muted" style={{fontSize:12,padding:20}}>Fabricación — disponible en F3.4.</div>
          )}

          {!loading && tab === 'compras' && (
            window.ComprasExpedientePanel
              ? <window.ComprasExpedientePanel expedienteId={pedidoId} onToast={onToast}/>
              : <div className="muted" style={{fontSize:12,padding:20}}>Compras / OCs — disponible en F3.5.</div>
          )}

          {!loading && tab === 'documentos' && (
            window.ExpedienteDocumentos
              ? <window.ExpedienteDocumentos expedienteId={pedidoId} onToast={onToast}/>
              : <ArchivosPanel entityType="expedientes" entityId={pedidoId} title="Documentos" onToast={onToast}/>
          )}
        </div>
      </div>
    </>
  );
};

// ── Vista lista de expedientes ────────────────────────
const ExpedientesView = ({ onToast, onNew, onOpenPedido, refreshKey }) => {
  const [rows, setRows] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [search, setSearch] = React.useState('');
  // Auto-abrir un expediente si veníamos navegando desde otra vista.
  const pendingId = (typeof window !== 'undefined') ? window.__erpPendingExpedienteId : null;
  const [open, setOpen] = React.useState(pendingId || null); // pedidoId
  React.useEffect(() => { if (pendingId) window.__erpPendingExpedienteId = null; }, []);
  const [reloadKey, setReloadKey] = React.useState(0);
  const reload = () => setReloadKey(k => k + 1);

  React.useEffect(() => {
    let alive = true;
    setLoading(true);
    API.get('/api/expedientes', search ? { search } : undefined)
      .then(r => { if (alive) { setRows(r); setLoading(false); } })
      .catch(e => { if (alive) { setLoading(false); onToast && onToast(e.message || 'Error al cargar', true); } });
    return () => { alive = false; };
  }, [search, reloadKey, refreshKey]);

  // Permite abrir un expediente concreto desde otra vista.
  React.useEffect(() => {
    const handler = (e) => { if (e.detail && e.detail.pedidoId) setOpen(e.detail.pedidoId); };
    window.addEventListener('erp:open-expediente', handler);
    return () => window.removeEventListener('erp:open-expediente', handler);
  }, []);

  const abiertos = rows.filter(r => (r.estado_expediente || '').toLowerCase() !== 'cerrado').length;
  const enProduccion = rows.filter(r => (r.estado_general || '').toUpperCase() === 'PROCESANDO').length;
  const matsPdte = rows.reduce((s, r) => s + expMatsPendientes(r).length, 0);

  const doExport = (ext) => {
    const qs = search ? '?' + new URLSearchParams({ search }).toString() : '';
    const today = new Date().toISOString().slice(0, 10);
    API.download(`/api/compras/export/${ext}${qs}`,
      `pedidos_${today}.${ext === 'excel' ? 'xlsx' : 'pdf'}`)
      .catch(e => onToast && onToast(e.message || 'Error al exportar', true));
  };

  return (
    <>
      <div className="page-h">
        <div>
          <h1>Expedientes</h1>
          <div className="sub">Expediente por pedido confirmado · {rows.length} total</div>
        </div>
        <div className="page-h-actions">
          <button className="btn" onClick={() => doExport('excel')}><Icon name="download" /> Excel</button>
          <button className="btn" onClick={() => doExport('pdf')}><Icon name="print" /> PDF</button>
          {onNew && <button className="btn primary" onClick={onNew}><Icon name="plus" /> Nuevo pedido</button>}
        </div>
      </div>

      <div className="kpi-grid" style={{gridTemplateColumns:'repeat(4,1fr)'}}>
        <div className="kpi">
          <div className="lbl">Total expedientes</div>
          <div className="row"><div className="num">{rows.length}</div></div>
        </div>
        <div className="kpi">
          <div className="lbl"><span className="dot" style={{background:'var(--info)'}}/> Activos</div>
          <div className="row"><div className="num">{abiertos}</div><span className="sub">sin cerrar</span></div>
        </div>
        <div className="kpi">
          <div className="lbl"><span className="dot" style={{background:'var(--info)'}}/> En producción</div>
          <div className="row"><div className="num">{enProduccion}</div></div>
        </div>
        <div className="kpi">
          <div className="lbl"><span className="dot" style={{background:'var(--warn)'}}/> Mat. pendientes</div>
          <div className="row"><div className="num">{matsPdte}</div><span className="sub">por recibir</span></div>
        </div>
      </div>

      <div className="toolbar">
        <div className="tb-search">
          <Icon name="search" />
          <input placeholder="Nº expediente, cliente…" value={search} onChange={e=>setSearch(e.target.value)}/>
        </div>
      </div>

      {loading && <div style={{padding:40,textAlign:'center',color:'var(--ink-3)'}}>Cargando expedientes…</div>}

      {!loading && (
        <div className="tbl-wrap">
          <div className="tbl-scroll">
            <table className="tbl">
              <thead>
                <tr>
                  <th>Nº expediente</th>
                  <th>Cliente</th>
                  <th>Nº pedido</th>
                  <th>Productos</th>
                  <th>F. confirmación</th>
                  <th>Estado</th>
                  <th>Producción</th>
                  <th>Materiales</th>
                </tr>
              </thead>
              <tbody>
                {rows.length === 0 && (
                  <tr><td colSpan={8} style={{textAlign:'center',padding:32,color:'var(--ink-3)'}}>Sin expedientes</td></tr>
                )}
                {rows.map(r => (
                  <tr key={r.id} onClick={()=>setOpen(r.id)} style={{cursor:'pointer'}}>
                    <td className="num strong mono">{r.numero_expediente}</td>
                    <td className="strong truncate">{r.cliente || '—'}</td>
                    <td className="num muted mono">{r.numero_pedido || '—'}</td>
                    <td className="truncate muted" style={{fontSize:11.5,maxWidth:160}}>{r.productos_resumen || '—'}</td>
                    <td className="num muted">{r.fecha_confirmacion || '—'}</td>
                    <td><ExpedienteEstadoPill v={r.estado_expediente}/></td>
                    <td><ExpedienteProdPill v={r.estado_general}/></td>
                    <td
                      title="Ver / editar materiales del pedido"
                      onClick={onOpenPedido ? (e)=>{ e.stopPropagation(); onOpenPedido({ id: r.id }); } : undefined}
                    >
                      <MaterialesResumenPill r={r}/>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      <ExpedienteDrawer
        pedidoId={open}
        onClose={()=>setOpen(null)}
        onToast={onToast}
        onRefresh={reload}
      />
    </>
  );
};

window.ExpedientesView   = ExpedientesView;
window.ExpedienteDrawer  = ExpedienteDrawer;
