// ─────────────────────────────────────────────────────
// GUT-66 (F3.4) — RfqComparador: peticiones de presupuesto a
// proveedores + comparador por expediente. Digitaliza la hoja
// PRESUPUESTOS del Excel SEGUIMIENTO DE PEDIDOS DE COMPRA.
//
// expedienteId = pedidos.id. API REST bajo
// /api/expedientes/:pedidoId/rfqs (GUT-66 rfq.js).
//
// GUT-67 renderiza este window.RfqComparador ARRIBA de la pestaña
// "Compras" del expediente (fallback si no existe).
//
// "Elegir" → OC (contrato GUT-67): PATCH de estados en la API de
// RFQ (POST .../elegir) + POST de la OC en firme client-side a
// POST /api/expedientes/:pedidoId/ordenes con body
// { proveedor_id, rfq_id, lineas:[{ bom_linea_id?, descripcion,
//   cantidad, precio_unitario }] }.
// ─────────────────────────────────────────────────────

const RFQ_ESTADO_PILL = {
  enviada:    { cls: 'info', label: 'Enviada' },
  recibida:   { cls: 'warn', label: 'Recibida' },
  elegida:    { cls: 'ok',   label: 'Elegida' },
  descartada: { cls: 'muted', label: 'Descartada' },
};

const RFQ_OFERTA_CATEGORIA = '05 PRESUPUESTO';

function rfqFmtFecha(val) {
  if (!val) return '—';
  const s = String(val).slice(0, 10);
  const [y, m, d] = s.split('-');
  return (y && m && d) ? `${d}/${m}/${y}` : s;
}

function rfqFmtImporte(val) {
  if (val == null || val === '') return '—';
  const n = Number(val);
  if (!Number.isFinite(n)) return '—';
  return n.toLocaleString('es-ES', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' €';
}

// ── Formulario de alta de RFQ (proveedor + líneas de la BOM) ──
// La petición se crea SIN precio: al proveedor solo se le pregunta cuánto
// costará. Importe/validez/plazo son datos de SU respuesta y se anotan en
// la columna del comparador cuando llega la oferta.
const RfqAlta = ({ pedidoId, proveedores, bomLineas, onAdded, onCancel, onToast }) => {
  const [proveedorId, setProveedorId] = React.useState('');
  const [notas, setNotas] = React.useState('');
  // Set de bom_linea_id seleccionados.
  const [sel, setSel] = React.useState({});
  const [busy, setBusy] = React.useState(false);
  // El usuario eligió el proveedor a mano → no autoseleccionar.
  const [provTouched, setProvTouched] = React.useState(false);

  const elegirProveedor = (val) => { setProvTouched(true); setProveedorId(val); };

  const toggle = (id) => setSel(s => {
    const next = { ...s, [id]: !s[id] };
    // Autoseleccionar el proveedor de la línea BOM si el usuario no lo ha
    // fijado a mano y todas las líneas marcadas (con proveedor) coinciden.
    if (!provTouched) {
      const provs = bomLineas
        .filter(l => next[l.id] && l.proveedor_id != null)
        .map(l => String(l.proveedor_id));
      const unico = provs.length > 0 && provs.every(p => p === provs[0]);
      setProveedorId(unico ? provs[0] : '');
    }
    return next;
  });

  const guardar = async () => {
    if (!proveedorId) { onToast && onToast('Selecciona un proveedor', true); return; }
    const lineas = bomLineas
      .filter(l => sel[l.id])
      .map(l => ({
        bom_linea_id: l.id,
        descripcion: l.material_referencia
          ? `${l.material_referencia}${l.material_nombre ? ' · ' + l.material_nombre : ''}`
          : (l.nombre || ''),
        cantidad: l.cantidad == null || l.cantidad === '' ? null : Number(l.cantidad),
        precio_unitario: null,
      }));
    setBusy(true);
    try {
      await API.post(`/api/expedientes/${pedidoId}/rfqs`, {
        proveedor_id: Number(proveedorId),
        notas,
        lineas,
      });
      onAdded && onAdded();
    } catch (e) { onToast && onToast(e.message || 'Error al crear RFQ', true); }
    finally { setBusy(false); }
  };

  return (
    <div style={{padding:12,marginBottom:12,border:'1px solid var(--line)',borderRadius:8}}>
      <div className="section-title" style={{marginTop:0}}>Nueva petición de presupuesto (RFQ)</div>
      <div className="fields-grid" style={{alignItems:'end'}}>
        <div className="field">
          <label>Proveedor *</label>
          <select value={proveedorId} onChange={e=>elegirProveedor(e.target.value)}>
            <option value="">— Selecciona —</option>
            {proveedores.map(p => <option key={p.id} value={p.id}>{p.nombre}</option>)}
          </select>
        </div>
        <div className="field" style={{gridColumn:'1 / -1'}}><label>Notas</label><input value={notas} onChange={e=>setNotas(e.target.value)}/></div>
      </div>
      <div className="muted" style={{fontSize:11.5,marginTop:6}}>
        Se le pide al proveedor cuánto costará; su precio por material, importe, validez y plazo se anotan en el comparador cuando responda.
      </div>

      <div className="muted" style={{fontSize:12,margin:'10px 0 6px'}}>Líneas de la BOM a solicitar:</div>
      {bomLineas.length === 0 ? (
        <div className="muted" style={{fontSize:12}}>Sin líneas en la BOM. Añade líneas en la pestaña BOM primero.</div>
      ) : (
        <div style={{maxHeight:180,overflowY:'auto',border:'1px solid var(--line)',borderRadius:6,padding:6}}>
          {bomLineas.map(l => {
            const art = l.material_referencia
              ? `${l.material_referencia}${l.material_nombre ? ' · ' + l.material_nombre : ''}`
              : (l.nombre || '—');
            // La línea se clonará si tiene proveedor y difiere del RFQ elegido.
            const seDuplica = sel[l.id] && l.proveedor_id != null
              && proveedorId !== '' && String(l.proveedor_id) !== String(proveedorId);
            return (
              <label key={l.id} style={{display:'flex',alignItems:'center',gap:8,fontSize:12.5,padding:'3px 0',cursor:'pointer'}}>
                <input type="checkbox" checked={!!sel[l.id]} onChange={()=>toggle(l.id)}/>
                <span style={{flex:1}}>{art}</span>
                {l.proveedor_id != null && <span className="muted" style={{fontSize:11.5}}>{l.proveedor_nombre || 'Sin proveedor'}</span>}
                {seDuplica && <span className="muted" style={{fontSize:11,opacity:.8,fontStyle:'italic'}}>se duplicará</span>}
                <span className="muted">{l.cantidad != null ? `${Number(l.cantidad)}${l.unidad ? ' ' + l.unidad : ''}` : ''}</span>
              </label>
            );
          })}
        </div>
      )}

      <div style={{display:'flex',gap:6,marginTop:10}}>
        <button className="btn primary sm" onClick={guardar} disabled={busy}>{busy ? 'Guardando…' : 'Crear RFQ'}</button>
        <button className="btn ghost sm" onClick={onCancel}>Cancelar</button>
      </div>
    </div>
  );
};

// ── Precio ofertado por el proveedor para una línea ──
// Se guarda al salir del campo; el backend recalcula el importe de la
// cabecera y pasa la RFQ 'enviada' → 'recibida' automáticamente.
const RfqLineaPrecio = ({ pedidoId, rfqId, linea, esMejor, disabled, onChanged, onToast }) => {
  const [val, setVal] = React.useState(linea.precio_unitario ?? '');
  React.useEffect(() => { setVal(linea.precio_unitario ?? ''); }, [linea.precio_unitario]);
  const guardar = async () => {
    const prev = linea.precio_unitario == null ? null : Number(linea.precio_unitario);
    const next = val === '' ? null : Number(val);
    if (prev === next) return;
    try {
      await API.patch(`/api/expedientes/${pedidoId}/rfqs/${rfqId}/lineas/${linea.id}`, { precio_unitario: next });
      onChanged && onChanged();
    } catch (e) { onToast && onToast(e.message || 'Error al guardar precio', true); }
  };
  return (
    <div style={{display:'flex',alignItems:'center',gap:6,padding:'2px 0'}}>
      <span style={{flex:1,fontSize:11.5,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}} title={linea.descripcion || ''}>{linea.descripcion || '—'}</span>
      {linea.cantidad != null && <span className="muted" style={{fontSize:11}}>×{Number(linea.cantidad)}</span>}
      <input
        type="number" step="0.01" min="0" value={val} disabled={disabled}
        onChange={e=>setVal(e.target.value)} onBlur={guardar} placeholder="€/ud"
        className={esMejor ? 'tip' : undefined}
        data-tip={esMejor ? 'Mejor precio' : undefined}
        style={{width:74,fontSize:12, ...(esMejor ? {border:'1px solid var(--ok)',background:'var(--ok-soft, #f0fdf4)',fontWeight:700} : {})}}
      />
    </div>
  );
};

// ── Columna de una oferta en el comparador ──
const RfqColumna = ({ pedidoId, rfq, mejores, onChanged, onToast }) => {
  const [busy, setBusy] = React.useState(false);
  const [plazo, setPlazo] = React.useState(rfq.plazo_dias ?? '');
  const [validez, setValidez] = React.useState(rfq.validez || '');
  React.useEffect(() => { setPlazo(rfq.plazo_dias ?? ''); setValidez(rfq.validez || ''); }, [rfq.plazo_dias, rfq.validez]);
  const inputRef = React.useRef(null);
  const pill = RFQ_ESTADO_PILL[rfq.estado] || { cls: 'info', label: rfq.estado };
  const toast = (m, e) => onToast && onToast(m, e);

  // Guardar un campo de la respuesta del proveedor en la cabecera.
  const saveCab = async (campos) => {
    try {
      await API.patch(`/api/expedientes/${pedidoId}/rfqs/${rfq.id}`, campos);
      onChanged && onChanged();
    } catch (e) { toast(e.message || 'Error al guardar', true); }
  };

  // Cambio rápido de estado (enviada/recibida) desde el select.
  const setEstado = async (estado) => {
    setBusy(true);
    try {
      await API.patch(`/api/expedientes/${pedidoId}/rfqs/${rfq.id}`, { estado });
      onChanged && onChanged();
    } catch (e) { toast(e.message || 'Error al cambiar estado', true); }
    finally { setBusy(false); }
  };

  // Adjuntar oferta: sube PDF a `archivos` (categoria 05 PRESUPUESTO,
  // contrato GUT-68) y guarda el archivo_id en la RFQ.
  const adjuntar = async (ev) => {
    const file = (ev.target.files || [])[0];
    if (inputRef.current) inputRef.current.value = '';
    if (!file) return;
    setBusy(true);
    try {
      const fd = new FormData();
      fd.append('entity_type', 'expedientes');
      fd.append('entity_id', String(pedidoId));
      fd.append('categoria', RFQ_OFERTA_CATEGORIA);
      fd.append('files', file);
      const up = await API.upload('/api/archivos', fd);
      const archivoId = up && up.uploaded && up.uploaded[0] && up.uploaded[0].id;
      if (archivoId) {
        await API.patch(`/api/expedientes/${pedidoId}/rfqs/${rfq.id}`, {
          oferta_archivo_id: archivoId,
          // Adjuntar una oferta implica que ya fue recibida.
          estado: rfq.estado === 'enviada' ? 'recibida' : rfq.estado,
        });
      }
      toast('Oferta adjuntada ✓');
      onChanged && onChanged();
    } catch (e) { toast(e.message || 'Error al adjuntar oferta', true); }
    finally { setBusy(false); }
  };

  const abrirOferta = async () => {
    if (!rfq.oferta_archivo_id) return;
    try {
      const res = await API.request(`/api/archivos/${rfq.oferta_archivo_id}/download`);
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      window.open(url, '_blank');
      setTimeout(() => URL.revokeObjectURL(url), 30000);
    } catch (e) { toast(e.message || 'Error al abrir oferta', true); }
  };

  // Elegir → OC: marca estados en la API y genera la OC en firme
  // (contrato GUT-67) client-side.
  const elegir = async () => {
    if (!confirm(`¿Elegir la oferta de ${rfq.proveedor_nombre || 'este proveedor'}? Las demás quedarán descartadas y se generará la OC.`)) return;
    setBusy(true);
    try {
      const chosen = await API.post(`/api/expedientes/${pedidoId}/rfqs/${rfq.id}/elegir`);
      // Genera la OC en firme (GUT-67). Si su endpoint aún no existe,
      // los estados ya quedaron aplicados; avisamos sin romper.
      try {
        await API.post(`/api/expedientes/${pedidoId}/ordenes`, {
          proveedor_id: chosen.proveedor_id,
          rfq_id: chosen.id,
          lineas: (chosen.lineas || []).map(l => ({
            bom_linea_id: l.bom_linea_id || undefined,
            descripcion: l.descripcion || '',
            cantidad: l.cantidad == null ? null : Number(l.cantidad),
            precio_unitario: l.precio_unitario == null ? null : Number(l.precio_unitario),
          })),
        });
        toast('Oferta elegida y OC generada ✓');
      } catch (ocErr) {
        toast('Oferta elegida ✓ (OC pendiente: ' + (ocErr.message || 'endpoint OC no disponible') + ')', true);
      }
      onChanged && onChanged();
    } catch (e) { toast(e.message || 'Error al elegir oferta', true); }
    finally { setBusy(false); }
  };

  const borrar = async () => {
    if (!confirm('¿Eliminar esta RFQ?')) return;
    try {
      await API.del(`/api/expedientes/${pedidoId}/rfqs/${rfq.id}`);
      onChanged && onChanged();
    } catch (e) { toast(e.message || 'Error al eliminar', true); }
  };

  const elegida = rfq.estado === 'elegida';
  return (
    <div style={{
      flex:'1 1 240px', minWidth:230, border:'1px solid var(--line)', borderRadius:8,
      padding:12, background: elegida ? 'var(--ok-soft, #f0fdf4)' : 'var(--bg-soft, #f9fafb)',
      outline: elegida ? '2px solid var(--ok)' : 'none',
    }}>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',gap:8,marginBottom:8}}>
        <span style={{fontWeight:700,fontSize:13}}>{rfq.proveedor_nombre || 'Sin proveedor'}</span>
        <span className={`pill ${pill.cls}`}><span className="d"/>{pill.label}</span>
      </div>

      <div style={{fontSize:13,lineHeight:1.9}}>
        <div style={{display:'flex',justifyContent:'space-between'}}><span className="muted">Importe</span><b>{rfqFmtImporte(rfq.importe)}</b></div>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',gap:6}}>
          <span className="muted">Plazo (días)</span>
          <input type="number" min="0" value={plazo} disabled={busy || elegida}
            onChange={e=>setPlazo(e.target.value)}
            onBlur={()=>{ if (String(plazo) !== String(rfq.plazo_dias ?? '')) saveCab({ plazo_dias: plazo === '' ? null : plazo }); }}
            style={{width:64,fontSize:12}}/>
        </div>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',gap:6}}>
          <span className="muted">Validez</span>
          <input type="date" value={validez} disabled={busy || elegida}
            onChange={e=>{ setValidez(e.target.value); saveCab({ validez: e.target.value || '' }); }}
            style={{width:130,fontSize:12}}/>
        </div>
      </div>

      {(rfq.lineas || []).length > 0 && (
        <div style={{marginTop:8,borderTop:'1px solid var(--line)',paddingTop:6}}>
          <div className="muted" style={{fontSize:11,marginBottom:2}}>Precio del proveedor por material</div>
          {rfq.lineas.map(l => {
            const key = l.material_key != null ? String(l.material_key) : (l.descripcion || '');
            const mejor = mejores && mejores[key];
            const esMejor = !!(mejor && mejor.count > 1 && l.precio_unitario != null && Number(l.precio_unitario) === mejor.min);
            return (
              <RfqLineaPrecio key={l.id} pedidoId={pedidoId} rfqId={rfq.id} linea={l}
                esMejor={esMejor} disabled={busy || elegida} onChanged={onChanged} onToast={onToast}/>
            );
          })}
        </div>
      )}

      {rfq.notas && <div className="muted" style={{fontSize:12,marginTop:6}}>{rfq.notas}</div>}

      <div style={{marginTop:10,display:'flex',flexDirection:'column',gap:6}}>
        <div style={{display:'flex',alignItems:'center',gap:6}}>
          <select value={rfq.estado} disabled={busy || elegida} onChange={e=>setEstado(e.target.value)} style={{flex:1,background:'var(--surface)',border:'1px solid var(--line)',borderRadius:'var(--r-md, 6px)',padding:'6px 10px',color:'var(--ink)',fontSize:12.5}}>
            <option value="enviada">Enviada</option>
            <option value="recibida">Recibida</option>
            {elegida && <option value="elegida">Elegida</option>}
            {rfq.estado === 'descartada' && <option value="descartada">Descartada</option>}
          </select>
        </div>

        {rfq.oferta_archivo_id ? (
          <button type="button" className="btn ghost sm" onClick={abrirOferta}>
            <Icon name="file" size={12}/> Ver oferta (PDF)
          </button>
        ) : (
          <label className="btn ghost sm" style={{cursor:'pointer'}}>
            <Icon name="upload" size={12}/> {busy ? 'Subiendo…' : 'Adjuntar oferta'}
            <input ref={inputRef} type="file" accept=".pdf" style={{display:'none'}} onChange={adjuntar} disabled={busy}/>
          </label>
        )}

        <div style={{display:'flex',gap:6}}>
          <button className="btn primary sm" style={{flex:1}} onClick={elegir} disabled={busy || elegida}>
            {elegida ? 'Elegida' : 'Elegir → OC'}
          </button>
          <button className="btn ghost sm tip" data-tip="Eliminar" style={{color:'var(--err)'}} onClick={borrar} disabled={busy}>
            <Icon name="trash" size={12}/>
          </button>
        </div>
      </div>
    </div>
  );
};

const RfqComparador = ({ expedienteId, onToast, onChanged }) => {
  const [rfqs, setRfqs] = React.useState(null);
  const [proveedores, setProveedores] = React.useState([]);
  const [bomLineas, setBomLineas] = React.useState([]);
  const [adding, setAdding] = React.useState(false);

  const load = React.useCallback(() => {
    if (!expedienteId) return;
    API.get(`/api/expedientes/${expedienteId}/rfqs`)
      .then(d => setRfqs(Array.isArray(d.rfqs) ? d.rfqs : []))
      .catch(e => { setRfqs([]); onToast && onToast(e.message || 'Error al cargar RFQs', true); });
  }, [expedienteId]);

  React.useEffect(() => { load(); }, [load]);
  React.useEffect(() => {
    API.get('/api/proveedores')
      .then(rows => setProveedores(Array.isArray(rows) ? rows : (rows && rows.data) || []))
      .catch(() => setProveedores([]));
  }, []);
  React.useEffect(() => {
    if (!expedienteId) return;
    API.get(`/api/expedientes/${expedienteId}/bom`)
      .then(d => setBomLineas(Array.isArray(d.lineas) ? d.lineas : []))
      .catch(() => setBomLineas([]));
  }, [expedienteId]);

  // Mejor precio ofertado por material (material_key agrupa la línea BOM
  // original con sus clones comparativos) para destacarlo en las columnas.
  const mejores = React.useMemo(() => {
    const map = {};
    for (const r of rfqs || []) {
      for (const l of r.lineas || []) {
        if (l.precio_unitario == null) continue;
        const key = l.material_key != null ? String(l.material_key) : (l.descripcion || '');
        if (!key) continue;
        const p = Number(l.precio_unitario);
        if (!map[key]) map[key] = { min: p, count: 1 };
        else { map[key].min = Math.min(map[key].min, p); map[key].count++; }
      }
    }
    return map;
  }, [rfqs]);

  if (!expedienteId) return <p className="muted" style={{fontSize:12}}>Expediente no disponible.</p>;
  if (rfqs === null) return <p className="muted" style={{fontSize:12}}>Cargando…</p>;

  return (
    <div style={{marginBottom:18}}>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',gap:12,marginBottom:12,flexWrap:'wrap'}}>
        <div className="section-title" style={{margin:0}}>Peticiones de presupuesto (RFQ)</div>
        <button className="btn primary sm" onClick={()=>setAdding(a=>!a)}><Icon name="plus" size={12}/> RFQ</button>
      </div>

      {adding && (
        <RfqAlta
          pedidoId={expedienteId}
          proveedores={proveedores}
          bomLineas={bomLineas}
          onAdded={()=>{ setAdding(false); load(); }}
          onCancel={()=>setAdding(false)}
          onToast={onToast}
        />
      )}

      {rfqs.length === 0 && !adding && (
        <p className="muted" style={{fontSize:12}}>Sin RFQs todavía. Crea una petición a un proveedor sobre líneas de la BOM.</p>
      )}

      {rfqs.length > 0 && (
        <div style={{display:'flex',gap:12,flexWrap:'wrap',alignItems:'stretch'}}>
          {rfqs.map(r => (
            <RfqColumna key={r.id} pedidoId={expedienteId} rfq={r} mejores={mejores} onChanged={()=>{ load(); onChanged && onChanged(); }} onToast={onToast}/>
          ))}
        </div>
      )}
    </div>
  );
};

window.RfqComparador = RfqComparador;
