// ─── Documento del expediente: Orden de Compra ───────────────────────────
// OrdenCompraScreen: segundo documento del pipeline (PRESUPUESTO →
// ORDEN_COMPRA), hereda ítems del presupuesto. Extraída de screens-docs.jsx
// en P7 junto con las otras 6 pantallas de documento. Expone a window:
// OrdenCompraScreen. Consume window.resolveDocExp (screens/docs/
// compartido.jsx), DocumentShell/DocCard/PartyBlock/Totals/
// MedicalContextCard/ObservacionesCard/buildEmisorFields/buildClienteFields
// (ui/doc-kit-shell.jsx), DocMetaStrip (ui/doc-kit-meta.jsx), ItemsTable/
// FileUploadCard (ui/doc-kit-items.jsx/doc-kit-edit.jsx), useDocEdit/
// buildDocActions (ui/doc-kit-edit.jsx), emptyOrdenCompra/saveDocOnExp
// (dominio/expediente-docs.js), window.MicosItemsMath (doc-itemmath.js),
// window.PartySelectorModal (ui/party-selector.jsx)/ENTIDADES (core/colecciones.js) —
// DECISIÓN 4 (06/07/2026, ver comentario junto al estado `clientePicker` más abajo).
//
// FIX P13 (A0, hallazgo ALTO de la consolidación — misma familia que
// presupuesto.jsx): el PartyBlock "Comprador" leía `exp.particular.nombre`/
// `.apellido` sin guarda (una de las 5 copias del baseline, `77b36f5`) —
// blindado igual que las demás; ver presupuesto.jsx para el detalle completo
// de la causa de fondo (id-race de Expedientes, arreglado en core/app.jsx +
// screens/expedientes/alta.jsx).

// `startEditing` (opcional): lo inyecta DocSubrouteGate (screens/docs/compartido.jsx)
// en un F5/deep-link directo a esta sub-ruta, para abrir la OC REAL ya en edición
// (datos reales, no un alta en blanco). En navegación normal llega false y no cambia
// nada (startEditing sigue siendo isCreate).
function OrdenCompraScreen({ expediente, onBack, startEditing = false }) {
  const exp = resolveDocExp(expediente);
  const co = COMPANY_CONFIG;
  const isCreate = !exp.ordenCompra;
  const original = React.useMemo(() => exp.ordenCompra || emptyOrdenCompra(exp), [exp.ordenCompra]);
  const [toast, setToast] = React.useState(null);
  const [tick, setTick] = React.useState(0); // recomputa los adjuntos persistidos tras subir
  const uploaderRef = React.useRef(null);    // DECISIÓN 9: captura los adjuntos pendientes de FileUploadCard
  // DECISIÓN 9 (4ª superficie): "Orden de compra firmada por el cliente" persistida — se deriva
  // de DOCUMENTOS por FK+tipo (mismo criterio que makeCompraDetail para el comprobante de la
  // compra), NO de la sesión, así sobrevive el F5. `tick` la recomputa tras subir un adjunto.
  const archivosOC = React.useMemo(
    () => (window.DOCUMENTOS || []).filter(
      (dd) => dd.expedienteId === exp.id
        && String(dd.tipo || '').toUpperCase() === 'ORDEN_COMPRA_FIRMADA'
        && !dd.deletedAt,
    ),
    [exp.id, tick],
  );
  // DECISIÓN 4 (06/07/2026): lápiz "Cambiar comprador" — antes no-op y mal targeteado
  // (`onClick={() => {}}`, "Cambiar proveedor" sobre el bloque "Proveedor" — que en esta OC es
  // SIEMPRE Micos/`co`, fijo, igual que "Emisor" en Presupuesto/Remito). El único override real
  // que soporta el schema (`ordenes_compra.entidad_id`, ya existía desde el diseño original) es
  // el del COMPRADOR (cliente del expediente) — mismo dato que "Cliente" en los otros 2
  // documentos, ver comentario del header.
  const [clientePicker, setClientePicker] = React.useState(false);

  const { editing, draft, setDraft, enterEdit, discardEdit, saveEdit, patch } = useDocEdit(() => ({
    fechaEmision: original.fechaEmision,
    fechaVencimiento: original.fechaVencimiento,
    tipoContratacion: original.tipoContratacion,
    lugarEntrega: original.lugarEntrega,
    plazoEntrega: original.plazoEntrega,
    moneda: original.moneda || 'Pesos argentinos',
    observaciones: original.observaciones || '',
    importeLetras: original.importeLetras || '',
    entidadId: original.entidadId || null,
    items: original.items.map((it) => window.MicosItemsMath.migrate(it)),
  }), {
    startEditing: isCreate || startEditing,
    onCancel: () => { if (isCreate) onBack(); },
    onSave: async (d) => {
      // DECISIÓN 9 (4ª superficie) — al GUARDAR la OC, el adjunto "OC firmada por el cliente"
      // sube al bucket `erp-adjuntos` + se registra en `documentos` (tipo ORDEN_COMPRA_FIRMADA,
      // colgado del expediente, misma infra que doc. médica/extra). Si falla, abortamos el
      // guardado (sigue en edición) en vez de fingir éxito — igual que doc-medica.jsx.
      const live = (window.EXPEDIENTES || []).find((e) => e.id === exp.id) || exp;
      const pend = uploaderRef.current ? uploaderRef.current.getPending() : [];
      if (pend.length && window.MicosAdjuntos) {
        try {
          await window.MicosAdjuntos.subir(pend, { tipo: 'ORDEN_COMPRA_FIRMADA', expedienteId: live.id });
          uploaderRef.current.clearPending();
          setTick((t) => t + 1);
        } catch (err) {
          setToast('No se pudieron subir los archivos: ' + ((err && err.message) || 'error'));
          setTimeout(() => setToast(null), 5000);
          return false;
        }
      }
      // Ítems con `total` de línea (subtotal = base+IVA−bonif) + `total` de cabecera
      // (summary con IVA). Antes el docObj no mandaba `total` de cabecera (ordenes_compra.total
      // quedaba NULL) y los ítems heredados venían sin `total` (migrate lo dropea) —
      // orden_compra_item.total NULL. Invariante flujo 2 herencia:
      // sum(orden_compra_item.total) == ordenes_compra.total. Mismo criterio que presupuesto.jsx.
      const M = window.MicosItemsMath;
      const items = (d.items || []).map((it) => ({ ...it, total: M._round(M.normalize(it).subtotal) }));
      const docObj = {
        ...original,
        fechaEmision: d.fechaEmision,
        fechaVencimiento: d.fechaVencimiento,
        tipoContratacion: d.tipoContratacion,
        lugarEntrega: d.lugarEntrega,
        plazoEntrega: d.plazoEntrega,
        // FIX (hallazgo "Moneda", AUDITORIA-ui-decorativa-05-07-2026.md): docObj llevaba
        // moneda solo vía el spread `...original` (arriba) — el valor EDITADO (d.moneda)
        // nunca pisaba al viejo, así que cambiar el select y guardar no tenía efecto.
        moneda: d.moneda || '',
        observaciones: d.observaciones || '',
        importeLetras: d.importeLetras || '',
        // DECISIÓN 4: mismo criterio — el spread de `...original` solo trae el valor VIEJO.
        entidadId: d.entidadId || null,
        items,
        total: M.summary(items).total,
      };
      saveDocOnExp(exp, 'ordenCompra', docObj);
      setToast(`Orden de compra OC-${docObj.numero} ${isCreate ? 'creada' : 'guardada'}`);
      setTimeout(() => setToast(null), 3600);
    },
  });

  const oc = editing && draft ? draft : original;
  // DECISIÓN 4: comprador = override de ESTA OC (oc.entidadId) o el del expediente (de
  // siempre) — resolveClienteDocumento (compartido.jsx) compartida con presupuesto/remito.
  const comprador = resolveClienteDocumento(exp, oc.entidadId);

  const patchItem = (idx, field, value) => setDraft((d) => {
    const items = d.items.map((it, i) => {
      if (i !== idx) return it;
      const next = { ...it, [field]: value };
      const cant = Number(next.cantidad) || 0;
      const unit = Number(next.unitario) || 0;
      const bonif = Number(next.bonifPct) || 0;
      next.total = cant * unit * (1 - bonif / 100);
      return next;
    });
    return { ...d, items };
  });
  const addItem = () => setDraft((d) => ({ ...d, items: [...d.items, window.MicosItemsMath.blank()] }));
  const removeItem = (idx) => setDraft((d) => ({ ...d, items: d.items.filter((_, i) => i !== idx) }));

  // ── Autocompletado desde foto/PDF (extracción IA, solo en sesión) ──
  // Resalta los campos completados y, si no estábamos editando, entra en edición.
  const [flash, setFlash] = React.useState({ keys: new Set(), token: 0 });
  const pendingExtract = React.useRef(null);
  function mergeExtract(data) {
    const keys = new Set();
    setDraft((d) => {
      const next = { ...d };
      ['fechaEmision', 'fechaVencimiento', 'tipoContratacion', 'lugarEntrega', 'plazoEntrega', 'observaciones'].forEach((k) => {
        if (data[k] != null && String(data[k]).trim() !== '') { next[k] = data[k]; keys.add(k); }
      });
      if (Array.isArray(data.items) && data.items.length) {
        next.items = data.items.map((it) => ({ sku: it.sku || '', descripcion: it.descripcion || '', cantidad: Number(it.cantidad) || 0, unitario: Number(it.unitario) || 0, bonifPct: Number(it.bonifPct) || 0, ivaPct: it.ivaPct == null ? 21 : Number(it.ivaPct), total: Number(it.total) || 0 }));
        keys.add('items');
      }
      return next;
    });
    setFlash({ keys, token: Date.now() });
  }
  function applyExtracted(data) {
    if (editing) mergeExtract(data);
    else { pendingExtract.current = data; enterEdit(); }
  }
  React.useEffect(() => {
    if (editing && draft && pendingExtract.current) {
      const d = pendingExtract.current; pendingExtract.current = null;
      mergeExtract(d);
    }
  }, [editing, draft]);

  // Totals
  const finOC = window.MicosItemsMath.summary(oc.items);
  const netoGravado = finOC.totalBase;
  const bonifTotal = finOC.bonifTotal;
  const ivaLines = finOC.ivaLines;
  const total = finOC.total;

  const actions = buildDocActions({ editing, enterEdit, discardEdit, saveEdit });

  return (
    <DocumentShell
      onBack={onBack}
      eyebrow="Orden de Compra"
      // Pill = estado PERSISTIDO real (ordenes_compra.estado: PENDIENTE/EN_TRANSITO/RECIBIDA/
      // ANULADA), no un rótulo fijo. Fallback a 'Emitida' solo si la OC todavía no tiene estado.
      statusLabel={editing ? 'Editando' : (((window.OC_ESTADOS || {})[original.estado] || {}).label || original.estado || 'Emitida')}
      statusPill="pill-oc"
      // FIX (P15, hallazgo H2 de la review): antes `OC-${original.numero}` —
      // dropeaba el `L-` de una OC legacy. `original.publicId` es el id real
      // (con o sin `L-`); en modo alta (sin fila real todavía) cae al mismo
      // placeholder de siempre.
      bigId={original.publicId || `OC-${original.numero}`}
      expedienteId={exp.publicId}
      fechaEmision={oc.fechaEmision}
      editing={editing}
      isCreate={isCreate}
      toast={toast}
      actions={actions}
    >
      <FileUploadCard
        eyebrow="Autorización del cliente · documento adjunto"
        title="Orden de compra firmada por el cliente"
        description="Subí el PDF que envía el cliente (obra social, prepaga u hospital) autorizando la operación. Vinculado a este expediente."
        files={archivosOC.slice(0, 1)}
        editing={editing}
        extractable
        realUpload
        persistTarget={{ tipo: 'ORDEN_COMPRA_FIRMADA', expedienteId: exp.id }}
        onUploaderReady={(api) => { uploaderRef.current = api; }}
        onExtracted={applyExtracted}
      />

      <MedicalContextCard exp={exp} />
      <DocMetaStrip editing={editing} items={[
        // FIX (P15, H2): idem bigId de arriba — mostrar el publicId real.
        { label: 'Número', value: original.publicId || `OC-${original.numero}`, mono: true, accent: true },
        { label: 'Emisión', value: editing ? draft.fechaEmision : formatDate(original.fechaEmision), mono: true, editable: editing, inputType: 'date', onChange: (v) => patch('fechaEmision', v), flash: editing && flash.keys.has('fechaEmision'), flashToken: flash.token },
        { label: 'Vencimiento', value: editing ? draft.fechaVencimiento : formatDate(original.fechaVencimiento), mono: true, editable: editing, inputType: 'date', onChange: (v) => patch('fechaVencimiento', v), flash: editing && flash.keys.has('fechaVencimiento'), flashToken: flash.token },
        { label: 'Expediente', value: exp.publicId, mono: true, accent: true },
        { label: 'Tipo contratación', value: editing ? draft.tipoContratacion : original.tipoContratacion, editable: editing, inputType: 'select', options: ['Compra directa', 'Licitación privada', 'Licitación pública', 'Contratación menor'], onChange: (v) => patch('tipoContratacion', v), flash: editing && flash.keys.has('tipoContratacion'), flashToken: flash.token },
        { label: 'Lugar de entrega', value: editing ? draft.lugarEntrega : original.lugarEntrega, editable: editing, onChange: (v) => patch('lugarEntrega', v), flash: editing && flash.keys.has('lugarEntrega'), flashToken: flash.token },
        { label: 'Plazo de entrega', value: editing ? draft.plazoEntrega : original.plazoEntrega, editable: editing, onChange: (v) => patch('plazoEntrega', v), flash: editing && flash.keys.has('plazoEntrega'), flashToken: flash.token },
        // P17a (desbloqueo general): antes hardcodeada sin onChange —
        // inconsistente con Presupuesto/Remito, que sí la dejan elegir (mismo
        // patrón/opciones que esos dos; ver header de ambos — tampoco viaja al
        // backend todavía, ninguno de los 3 documentos la persiste hoy).
        { label: 'Moneda', value: editing ? draft.moneda : (original.moneda || 'Pesos argentinos'), editable: editing, inputType: 'select', options: ['Pesos argentinos', 'Dólares (USD)', 'Euros (EUR)'], onChange: (v) => patch('moneda', v) },
      ]} />

      {/* Comprador (cliente del expediente, o el override de ESTA OC — DECISIÓN 4) +
          Proveedor (fijo, Micos) — la OC del expediente es cliente→nosotros */}
      <DocCard>
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
          <PartyBlock
            eyebrow="Comprador"
            name={comprador.nombre}
            sub={comprador.sub}
            fields={comprador.fields}
            onEdit={editing ? () => setClientePicker(true) : undefined}
            editLabel="Cambiar comprador"
          />
          <PartyBlock
            eyebrow="Proveedor"
            name={co.nombre}
            sub={co.situacionIva}
            fields={buildEmisorFields(co)}
          />
        </div>
      </DocCard>

      {editing && clientePicker && window.PartySelectorModal && (
        <window.PartySelectorModal
          type="entidad"
          open={true}
          onClose={() => setClientePicker(false)}
          onPick={(obj) => {
            if (obj && obj.id) patch('entidadId', obj.id);
            setClientePicker(false);
          }}
        />
      )}

      {/* Items + Totals */}
      <DocCard editing={editing}>
        <ItemsTable
          items={oc.items}
          showGanancia
          showBonif
          showIva
          editing={editing}
          onItemChange={patchItem}
          onItemRemove={removeItem}
          onAdd={addItem}
          flash={flash.keys.has('items') ? flash.token : 0}
          // Procurement: el selector de inventario ofrece ítems SIN stock (es lo que se repone).
          mostrarSinStock
        />
        <Totals
          subtotal={netoGravado}
          bonificaciones={bonifTotal}
          ivaLines={ivaLines}
          total={total}
          importeLetras={editing ? draft.importeLetras : original.importeLetras}
        />
      </DocCard>

      <ObservacionesCard editing={editing} value={editing ? draft.observaciones : original.observaciones} onChange={(v) => patch('observaciones', v)} />
    </DocumentShell>
  );
}

Object.assign(window, { OrdenCompraScreen });
