// ─────────────────────────────────────────────────────
// GUT-252 — Estado de una línea de material y sus procesos. Lo usan
// Expediente › Materiales (bom.jsx), Programación › Materiales y Demanda.
//
// Tres partes que no se mezclan (ver src/services/materialesLinea.js):
//   Compra    pendiente → pedido → recibido. La mueve la OC ("Crear pedido").
//             Excepción: "de stock" (ya está en fábrica) mientras no haya OC.
//             Desde aquí se puede corregir (marcar recibido, deshacer, volver a
//             pendiente): con OC se toca su línea de la OC, sin OC la de la lista.
//   Procesos  lacado / acción, uno tras otro, sobre material recibido.
//   Preparado cierre final.
//   Enviado   GUT-272: la línea va en un albarán de entrega vigente. Lo pone el
//             albarán y solo se deshace anulándolo: mientras, el panel no deja
//             tocar nada.
// La píldora enseña el estado derivado; al pasar el ratón, el historial; al
// hacer clic, el panel con las acciones posibles.
// ─────────────────────────────────────────────────────

const MAT_ESTADOS = {
  pendiente:  { cls: 'warn', label: 'Pendiente de pedir' },
  pedido:     { cls: 'info', label: 'Pedido' },
  recibido:   { cls: 'ok',   label: 'Recibido' },
  en_proceso: { cls: 'info', label: 'En proceso' },
  esperando:  { cls: 'err',  label: 'Esperando decisión' },
  preparado:  { cls: 'ok',   label: 'Preparado' },
  enviado:    { cls: 'ok',   label: 'Enviado' },
};
const MAT_TIPOS_PROCESO = { lacado: 'Lacado', accion: 'Acción' };
const MAT_ESTADOS_PROCESO = { pendiente: 'Pendiente', en_curso: 'En curso', completado: 'Completado' };

const matFecha = (v) => (v ? String(v).slice(0, 10).split('-').reverse().slice(0, 2).join('/') : '');

// Proveedores para elegir el lacador (una sola carga por página).
let matProveedoresCache = null;
const useMatProveedores = () => {
  const [items, setItems] = React.useState(matProveedoresCache || []);
  React.useEffect(() => {
    if (matProveedoresCache) return;
    API.get('/api/proveedores').then((rows) => {
      matProveedoresCache = rows.map((p) => ({ id: p.id, label: p.nombre }));
      setItems(matProveedoresCache);
    }).catch(() => {});
  }, []);
  return items;
};

// Texto del proceso: "Lacado RAL 7016 (ALUCOSUR)".
const matProcesoTxt = (p) => [MAT_TIPOS_PROCESO[p.tipo], p.descripcion, p.proveedor ? `(${p.proveedor})` : ''].filter(Boolean).join(' ');

// Estado derivado + etiqueta ("En lacado", "Cortar: en curso"…).
function matEstado(linea) {
  const key = linea.estado_material || linea.estado || 'pendiente';
  const base = MAT_ESTADOS[key] || { cls: 'info', label: key };
  if (key === 'en_proceso') {
    const p = (linea.procesos || []).find((x) => x.estado !== 'completado');
    if (p) {
      const label = p.tipo === 'lacado'
        ? `${p.estado === 'en_curso' ? 'En lacado' : 'Por lacar'}${p.proveedor ? ` · ${p.proveedor}` : ''}`
        : `${p.descripcion || 'Acción'}: ${MAT_ESTADOS_PROCESO[p.estado].toLowerCase()}`;
      return { ...base, key, label };
    }
  }
  if (key === 'pedido' && linea.oc_numero) return { ...base, key, label: `Pedido · OC ${linea.oc_numero}` };
  if (key === 'enviado' && linea.albaran_numero) return { ...base, key, label: `Enviado · ${linea.albaran_numero}` };
  return { ...base, key };
}

// Historial para el tooltip.
function matHistorial(linea) {
  const compra = linea.estado_compra || linea.estado;
  const partes = [];
  if (linea.de_stock) partes.push('De stock (ya en fábrica)');
  else {
    if (linea.oc_numero || linea.fecha_pedido) partes.push(`Pedido${linea.oc_numero ? ` OC ${linea.oc_numero}` : ''}${linea.fecha_pedido ? ` el ${matFecha(linea.fecha_pedido)}` : ''}`);
    if (compra === 'pedido' && linea.fecha_estimada) partes.push(`Llega ~${matFecha(linea.fecha_estimada)}`);
    if (compra === 'recibido') partes.push(`Recibido${linea.fecha_recepcion ? ` el ${matFecha(linea.fecha_recepcion)}` : ''}`);
    if (compra === 'pendiente') partes.push('Sin pedir');
  }
  (linea.procesos || []).forEach((p) => {
    const f = p.estado === 'completado' ? matFecha(p.fecha_fin) : p.estado === 'en_curso' ? `desde ${matFecha(p.fecha_inicio)}` : '';
    partes.push(`${matProcesoTxt(p)}: ${MAT_ESTADOS_PROCESO[p.estado].toLowerCase()}${f ? ` ${f}` : ''}`);
  });
  if (linea.preparado) partes.push(`Preparado${linea.fecha_preparado ? ` el ${matFecha(linea.fecha_preparado)}` : ''}`);
  else if (linea.estado_material === 'esperando') partes.push('→ Falta decidir: ¿otro proceso o preparado?');
  if (linea.estado_material === 'enviado') partes.push(`Enviado en ${linea.albaran_numero || 'albarán'}${linea.fecha_enviado ? ` el ${matFecha(linea.fecha_enviado)}` : ''}`);
  return partes.join('\n');
}

// Alta de un proceso (lacado o acción).
const MatProcesoForm = ({ lineaId, onDone, onCancel, onToast }) => {
  const provs = useMatProveedores();
  const [f, setF] = React.useState({ tipo: 'lacado', descripcion: '', proveedor_id: '', fecha_estimada: '' });
  const [busy, setBusy] = React.useState(false);
  const set = (k) => (e) => setF((x) => ({ ...x, [k]: e.target.value }));
  const guardar = async () => {
    setBusy(true);
    try { await API.post(`/api/demanda/lineas/${lineaId}/procesos`, f); onDone(); }
    catch (e) { onToast && onToast(e.message, true); }
    finally { setBusy(false); }
  };
  const lacado = f.tipo === 'lacado';
  return (
    <div className="mat-form">
      <div className="mat-seg">
        {Object.entries(MAT_TIPOS_PROCESO).map(([k, l]) => (
          <button key={k} type="button" className={f.tipo === k ? 'on' : ''} onClick={() => setF((x) => ({ ...x, tipo: k }))}>{l}</button>
        ))}
      </div>
      <input autoFocus placeholder={lacado ? 'Color (p. ej. RAL 7016)' : 'Qué se hace (cortar a 2300, mecanizar…) *'} value={f.descripcion} onChange={set('descripcion')} />
      {lacado && (
        <>
          <select value={f.proveedor_id} onChange={set('proveedor_id')}>
            <option value="">— Empresa de lacado —</option>
            {provs.map((p) => <option key={p.id} value={p.id}>{p.label}</option>)}
          </select>
          <label className="mat-lbl">Vuelta prevista <input type="date" value={f.fecha_estimada} onChange={set('fecha_estimada')} /></label>
        </>
      )}
      <div className="mat-actions">
        <button className="btn primary sm" disabled={busy || (!lacado && !f.descripcion.trim())} onClick={guardar}>Añadir proceso</button>
        <button className="btn ghost sm" onClick={onCancel}>Cancelar</button>
      </div>
    </div>
  );
};

// Panel con el detalle y las acciones de la línea.
const MatPanel = ({ linea, onChanged, onToast }) => {
  const [form, setForm] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const compra = linea.estado_compra || linea.estado;
  const procs = linea.procesos || [];
  const abierto = procs.find((p) => p.estado !== 'completado');
  const run = async (fn, ok) => {
    setBusy(true);
    try { await fn(); if (ok) onToast && onToast(ok); onChanged && onChanged(); }
    catch (e) { onToast && onToast(e.message, true); }
    finally { setBusy(false); }
  };
  // Corrección manual de la compra (PUT /compra). Con OC, volver a pendiente la saca de la OC.
  const compraA = (estado, ok) => {
    if (estado === 'pendiente' && linea.oc_numero
      && !confirm(`La línea se quitará de la OC ${linea.oc_numero} y volverá a "Pendiente de pedir". ¿Seguir?`)) return;
    run(() => API.put(`/api/demanda/lineas/${linea.id}/compra`, { estado }), ok);
  };
  const retrocede = !linea.preparado && !procs.length;
  const stock = (v) => run(() => API.put(`/api/demanda/lineas/${linea.id}/stock`, { de_stock: v }), v ? 'Marcado de stock ✓' : 'Vuelve a pendiente de pedir');
  const preparado = (v) => run(() => API.put(`/api/demanda/lineas/${linea.id}/preparado`, { preparado: v }), v ? 'Material preparado ✓' : null);
  const proceso = (p, estado) => run(() => API.patch(`/api/demanda/procesos/${p.id}`, { estado }));
  const borrar = (p) => confirm(`¿Quitar el proceso "${matProcesoTxt(p)}"?`) && run(() => API.del(`/api/demanda/procesos/${p.id}`));

  // GUT-272: enviada en un albarán vigente → solo lectura. Se deshace anulando el albarán.
  if (linea.estado_material === 'enviado') {
    return (
      <div className="mat-panel">
        <div className="mat-sec">
          <div className="mat-h">Enviado</div>
          <div>En el albarán <b className="mono">{linea.albaran_numero}</b>{linea.fecha_enviado ? ` del ${matFecha(linea.fecha_enviado)}` : ''}.</div>
          <div className="muted" style={{ fontSize: 11.5, marginTop: 4 }}>Enviado en {linea.albaran_numero}; anula el albarán para deshacerlo (botón «Albarán» › Albaranes emitidos).</div>
        </div>
        <div className="mat-sec">
          <div className="mat-h">Historial</div>
          <div className="muted" style={{ whiteSpace: 'pre-line', fontSize: 12 }}>{matHistorial(linea)}</div>
        </div>
      </div>
    );
  }

  return (
    <div className="mat-panel">
      <div className="mat-sec">
        <div className="mat-h">Compra</div>
        {linea.de_stock ? (
          <div>De stock: ya está en fábrica.{' '}
            {!linea.preparado && !procs.length && <button className="btn ghost sm" disabled={busy} onClick={() => stock(false)}>No es de stock</button>}
          </div>
        ) : compra === 'pendiente' ? (
          <div>
            <div className="muted">Se pasa a "Pedido" al crear la orden a proveedor.</div>
            <div className="mat-actions" style={{ marginTop: 6 }}>
              <button className="btn ghost sm" disabled={busy} onClick={() => stock(true)}>Es de stock (ya está en fábrica)</button>
              <button className="btn ghost sm" disabled={busy} onClick={() => compraA('recibido', 'Marcado recibido ✓')}>Ya ha llegado</button>
            </div>
          </div>
        ) : (
          <div style={{ whiteSpace: 'pre-line' }}>
            {linea.oc_numero ? <button className="btn ghost sm" onClick={() => window.dispatchEvent(new CustomEvent('erp:open-orden', { detail: { id: linea.oc_id } }))}>OC {linea.oc_numero}</button> : null}
            {' '}{compra === 'pedido' ? `Pedido ${matFecha(linea.fecha_pedido)}${linea.fecha_estimada ? ` · llega ~${matFecha(linea.fecha_estimada)}` : ''}` : `Recibido ${matFecha(linea.fecha_recepcion)}`}
            {compra === 'pedido' && !linea.oc_numero && <div className="muted" style={{ fontSize: 11 }}>Sin orden a proveedor (venía del Excel o se pidió fuera del ERP).</div>}
            {compra === 'pedido' && (
              <div className="mat-actions" style={{ marginTop: 6 }}>
                <button className="btn primary sm" disabled={busy} onClick={() => compraA('recibido', linea.oc_numero ? `Recibido ✓ (también en la OC ${linea.oc_numero})` : 'Marcado recibido ✓')}>Marcar recibido</button>
                {retrocede && <button className="btn ghost sm" disabled={busy} onClick={() => compraA('pendiente', 'Vuelve a pendiente de pedir')}>Volver a pendiente</button>}
              </div>
            )}
            {compra === 'recibido' && retrocede && (
              <div className="mat-actions" style={{ marginTop: 6 }}>
                <button className="btn ghost sm" disabled={busy} onClick={() => compraA(linea.oc_numero || linea.fecha_pedido ? 'pedido' : 'pendiente', 'Recepción deshecha')}>Deshacer recepción</button>
              </div>
            )}
          </div>
        )}
      </div>

      {(procs.length > 0 || compra === 'recibido') && (
        <div className="mat-sec">
          <div className="mat-h">Procesos</div>
          {procs.length === 0 && <div className="muted">Ninguno.</div>}
          {procs.map((p, i) => (
            <div key={p.id} className="mat-proc">
              <span className="muted">{i + 1}.</span>
              <span style={{ flex: 1 }}>{matProcesoTxt(p)}
                <span className="muted" style={{ fontSize: 11 }}>
                  {p.fecha_inicio ? ` · inicio ${matFecha(p.fecha_inicio)}` : ''}
                  {p.estado !== 'completado' && p.fecha_estimada ? ` · vuelta ~${matFecha(p.fecha_estimada)}` : ''}
                  {p.fecha_fin ? ` · fin ${matFecha(p.fecha_fin)}` : ''}
                </span>
              </span>
              <span className={`pill ${p.estado === 'completado' ? 'ok' : p.estado === 'en_curso' ? 'info' : 'warn'}`}><span className="d" />{MAT_ESTADOS_PROCESO[p.estado]}</span>
              {p.estado === 'pendiente' && <button className="btn ghost sm" disabled={busy} onClick={() => proceso(p, 'en_curso')}>Empezar</button>}
              {p.estado !== 'completado' && <button className="btn primary sm" disabled={busy} onClick={() => proceso(p, 'completado')}>Completar</button>}
              {p.estado === 'completado' && !linea.preparado && i === procs.length - 1 && <button className="btn ghost sm" disabled={busy} onClick={() => proceso(p, 'en_curso')}>Reabrir</button>}
              {!linea.preparado && <button className="icon-btn" disabled={busy} onClick={() => borrar(p)}><Icon name="trash" size={12} /></button>}
            </div>
          ))}
        </div>
      )}

      {compra === 'recibido' && !linea.preparado && !abierto && (
        form ? <MatProcesoForm lineaId={linea.id} onToast={onToast} onCancel={() => setForm(false)} onDone={() => { setForm(false); onChanged && onChanged(); }} /> : (
          <div className={`mat-sec mat-decide ${procs.length ? 'esperando' : ''}`}>
            <div className="mat-h">{procs.length ? 'Proceso completado. ¿Qué hacemos?' : '¿Necesita algún proceso?'}</div>
            <div className="mat-actions">
              <button className="btn ghost sm" disabled={busy} onClick={() => setForm(true)}><Icon name="plus" size={12} /> {procs.length ? 'Otro proceso' : 'Añadir proceso'}</button>
              <button className="btn primary sm" disabled={busy} onClick={() => preparado(true)}>Material preparado</button>
            </div>
          </div>
        )
      )}

      {linea.preparado && (
        <div className="mat-sec">
          <div>Preparado {matFecha(linea.fecha_preparado)} <button className="btn ghost sm" disabled={busy} onClick={() => preparado(false)}>Deshacer</button></div>
        </div>
      )}
    </div>
  );
};

// Píldora de estado: tooltip con el historial y panel flotante al hacer clic.
const MaterialEstado = ({ linea, onChanged, onToast }) => {
  const [open, setOpen] = React.useState(false);
  const [pos, setPos] = React.useState({ left: 0, top: 0 });
  const btnRef = React.useRef(null);
  const ddRef = React.useRef(null);
  const est = matEstado(linea);
  const abrir = (e) => {
    e.stopPropagation();
    const r = btnRef.current.getBoundingClientRect();
    const width = 380;
    const left = Math.max(8, Math.min(r.left, window.innerWidth - width - 8));
    const abajo = window.innerHeight - r.bottom - 8;
    setPos(abajo < 320 && r.top > abajo
      ? { left, width, bottom: window.innerHeight - r.top + 4, maxHeight: r.top - 16 }
      : { left, width, top: r.bottom + 4, maxHeight: abajo - 8 });
    setOpen((o) => !o);
  };
  React.useEffect(() => {
    if (!open) return;
    const fuera = (e) => { if (!ddRef.current?.contains(e.target) && !btnRef.current?.contains(e.target)) setOpen(false); };
    const esc = (e) => { if (e.key === 'Escape') setOpen(false); };
    const scroll = (e) => { if (!ddRef.current?.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', fuera); document.addEventListener('keydown', esc);
    window.addEventListener('scroll', scroll, true);
    return () => { document.removeEventListener('mousedown', fuera); document.removeEventListener('keydown', esc); window.removeEventListener('scroll', scroll, true); };
  }, [open]);
  return (
    <>
      <button type="button" ref={btnRef} className={`pill ${est.cls} mat-pill`} title={matHistorial(linea)} onClick={abrir}>
        <span className="d" />{est.label}{linea.de_stock && est.key === 'recibido' ? ' (stock)' : ''}
      </button>
      {open && ReactDOM.createPortal(
        <div ref={ddRef} className="mat-dd" style={pos} onClick={(e) => e.stopPropagation()} onMouseDown={(e) => e.stopPropagation()}>
          <MatPanel linea={linea} onToast={onToast} onChanged={() => { onChanged && onChanged(); }} />
        </div>,
        document.body,
      )}
    </>
  );
};

window.MaterialEstado = MaterialEstado;
window.useMatProveedores = useMatProveedores;
window.MAT_ESTADOS = MAT_ESTADOS;
