var OrdenesCompra = Object.assign({}, TablaGenerica);

OrdenesCompra.detalleItems = [];

OrdenesCompra.renderDetalle = function() {
    var tbody = document.getElementById('ocDetalleBody');
    if (!tbody) return;
    var html = '';
    this.detalleItems.forEach(function(item, idx) {
        var descPct = parseFloat(item.descuento_pct) || 0;
        html += '<tr>' +
            '<td>' + (item.cod_articulo || '') + '</td>' +
            '<td>' + (item.nombre || '') + '</td>' +
            '<td>' + (item.cod_unidad || '') + '</td>' +
'<td><input type="number" class="oc-det-cant" data-idx="' + idx + '" value="' + (item.cantidad ? parseFloat(item.cantidad).toFixed(3) : '') + '" step="0.001" min="0" style="width:100px;padding:4px 8px;border:1px solid #d1d5db;border-radius:4px;text-align:right;font-family:inherit;font-size:inherit;outline:none"></td>' +
'<td><input type="number" class="oc-det-precio" data-idx="' + idx + '" value="' + (item.precio ? parseFloat(item.precio).toFixed(3) : '') + '" step="0.001" min="0" style="width:110px;padding:4px 8px;border:1px solid #d1d5db;border-radius:4px;text-align:right;font-family:inherit;font-size:inherit;outline:none"></td>' +
'<td><input type="number" class="oc-det-desc" data-idx="' + idx + '" value="' + (descPct > 0 ? descPct : '') + '" step="any" min="0" max="100" placeholder="" style="width:65px;padding:4px 8px;border:1px solid #d1d5db;border-radius:4px;text-align:right;font-family:inherit;font-size:inherit;outline:none"></td>' +
            '<td class="oc-det-total">' + (parseFloat(item.total) || 0).toFixed(2) + '</td>' +
            '<td><button class="oc-btn-del" data-idx="' + idx + '" title="Eliminar" style="background:none;border:none;color:#ef4444;cursor:pointer;font-size:0.9rem"><i class="fas fa-trash-alt"></i></button></td>' +
            '</tr>';
    });
    tbody.innerHTML = html;
    tbody.querySelectorAll('.oc-det-cant').forEach(function(inp) {
        inp.addEventListener('change', function() {
            var idx = parseInt(this.dataset.idx);
            if (!isNaN(idx) && OrdenesCompra.detalleItems[idx]) {
                OrdenesCompra.detalleItems[idx].cantidad = parseFloat(this.value) || 0;
                OrdenesCompra.detalleItems[idx].total = parseFloat(OrdenesCompra.detalleItems[idx].cantidad * OrdenesCompra.detalleItems[idx].precio) || 0;
                OrdenesCompra.renderDetalle();
                OrdenesCompra.calcularTotales();
            }
        });
    });
    tbody.querySelectorAll('.oc-det-precio').forEach(function(inp) {
        inp.addEventListener('change', function() {
            var idx = parseInt(this.dataset.idx);
            if (!isNaN(idx) && OrdenesCompra.detalleItems[idx]) {
                OrdenesCompra.detalleItems[idx].precio = parseFloat(this.value) || 0;
                OrdenesCompra.detalleItems[idx].total = parseFloat(OrdenesCompra.detalleItems[idx].cantidad * OrdenesCompra.detalleItems[idx].precio) || 0;
                OrdenesCompra.renderDetalle();
                OrdenesCompra.calcularTotales();
            }
        });
    });
    tbody.querySelectorAll('.oc-det-desc').forEach(function(inp) {
        inp.addEventListener('change', function() {
            var idx = parseInt(this.dataset.idx);
            if (!isNaN(idx) && OrdenesCompra.detalleItems[idx]) {
                OrdenesCompra.detalleItems[idx].descuento_pct = parseFloat(this.value) || 0;
                OrdenesCompra.calcularTotales();
            }
        });
    });
    tbody.querySelectorAll('.oc-btn-del').forEach(function(btn) {
        btn.addEventListener('click', function() {
            var idx = parseInt(this.dataset.idx);
            if (!isNaN(idx)) {
                OrdenesCompra.detalleItems.splice(idx, 1);
                OrdenesCompra.renderDetalle();
                OrdenesCompra.calcularTotales();
            }
        });
    });
    var count = document.getElementById('ocDetCount');
    if (count) count.textContent = '(' + OrdenesCompra.detalleItems.length + ' items)';
};

OrdenesCompra.calcularTotales = function() {
    var subtotal = 0;
    var descuentoLineas = 0;
    OrdenesCompra.detalleItems.forEach(function(item) {
        var itemTotal = parseFloat(item.total) || 0;
        var itemDescPct = parseFloat(item.descuento_pct) || 0;
        var itemDescMonto = itemTotal * itemDescPct / 100;
        subtotal += itemTotal;
        descuentoLineas += itemDescMonto;
    });
    var porc = parseFloat(OrdenesCompra.porcentajeIgv) || 18;
    var subtotalBruto = subtotal;
    var subtotalNeto = subtotalBruto - descuentoLineas;

    var descGlobalTipo = OrdenesCompra.descuentoGlobalTipo || '%';
    var descGlobalVal = parseFloat(document.getElementById('ocFormDescGlobal')?.value) || 0;
    var descGlobalMonto = 0;
    if (descGlobalTipo === '%') {
        descGlobalMonto = subtotalNeto * descGlobalVal / 100;
    } else {
        descGlobalMonto = descGlobalVal;
    }
    subtotalNeto = subtotalNeto - descGlobalMonto;
    var descuentoTotal = descuentoLineas + descGlobalMonto;
    var igv = subtotalNeto * porc / 100;
    var total = subtotalNeto + igv;

    var elSub = document.getElementById('ocFormSubtotal');
    var elDesc = document.getElementById('ocFormDescuento');
    var elIgv = document.getElementById('ocFormIgv');
    var elTot = document.getElementById('ocFormTotal');
    var elLabel = document.getElementById('ocIgvLabel');
    if (elSub) elSub.value = subtotalBruto.toFixed(2);
    if (elDesc) elDesc.value = descuentoTotal.toFixed(2);
    if (elIgv) elIgv.value = igv.toFixed(2);
    if (elTot) elTot.value = total.toFixed(2);
    if (elLabel) elLabel.textContent = 'IGV (' + porc + '%):';
};

OrdenesCompra.iniciarAutocompleteProveedor = function() {
    var input = document.getElementById('ocFormProveedor');
    if (!input || input.dataset._autoProvOk) return;
    input.dataset._autoProvOk = '1';
    var hiddenId = document.getElementById('ocFormIdProveedor');

    var dd = document.createElement('div');
    dd.style.cssText = 'position:fixed;z-index:9999;background:#fff;border:1px solid #e2e8f0;border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,0.1);max-height:350px;overflow-y:auto;display:none';
    document.body.appendChild(dd);
    var timer;
    function ocultar() { dd.style.display = 'none'; dd.innerHTML = ''; }
    function posicionar() {
        var r = input.getBoundingClientRect();
        dd.style.top = r.bottom + 'px';
        dd.style.left = r.left + 'px';
        dd.style.width = Math.max(r.width, 420) + 'px';
    }
    input.addEventListener('input', function() {
        clearTimeout(timer);
        var v = this.value.trim();
        if (v.length < 1) { ocultar(); return; }
        timer = setTimeout(function() {
            var url = OrdenesCompra.API_URL + '/proveedores?buscar=' + encodeURIComponent(v) + '&limit=20&estado=1&id_empresa=' + (OrdenesCompra.sesion ? OrdenesCompra.sesion.id_empresa : '');
            if (OrdenesCompra.sesion && OrdenesCompra.sesion.id_sucursal) url += '&id_sucursal=' + OrdenesCompra.sesion.id_sucursal;
            fetch(url).then(function(r) { return r.json(); }).then(function(res) {
                posicionar();
                if (!res.ok || !res.data || res.data.length === 0) {
                    dd.innerHTML = '<div style="padding:10px;color:#94a3b8;font-size:13px;text-align:center">Sin resultados</div>';
                    dd.style.display = 'block'; return;
                }
                var h = '';
                res.data.forEach(function(item) {
                    h += '<div class="prov-ubigeo-dd-item prov-autocomplete-item" style="cursor:pointer" data-id="' + item.id_proveedor + '" data-razon="' + (item.razon_social || '').replace(/"/g, '&quot;') + '">' + item.razon_social + ' - ' + item.num_documento + '</div>';
                });
                dd.innerHTML = h;
                dd.style.display = 'block';
                dd.querySelectorAll('.prov-autocomplete-item').forEach(function(el) {
                    el.addEventListener('click', function() {
                        input.value = this.dataset.razon;
                        if (hiddenId) hiddenId.value = this.dataset.id;
                        ocultar();
                    });
                });
            });
        }, 300);
    });
    document.addEventListener('click', function(e) {
        if (!e.target.closest('#ocFormProveedor') && !dd.contains(e.target)) ocultar();
    });
    input.addEventListener('blur', function() {
        setTimeout(ocultar, 200);
    });
};

OrdenesCompra.iniciarAutocompleteEmpleado = function() {
    var input = document.getElementById('ocFormSolicitadoPor');
    if (!input || input.dataset._autoEmpOk) return;
    input.dataset._autoEmpOk = '1';
    var hiddenId = document.getElementById('ocFormIdEmpleado');
    var dd = document.createElement('div');
    dd.style.cssText = 'position:fixed;z-index:9999;background:#fff;border:1px solid #e2e8f0;border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,0.1);max-height:350px;overflow-y:auto;display:none';
    document.body.appendChild(dd);
    var timer;
    function ocultar() { dd.style.display = 'none'; dd.innerHTML = ''; }
    function posicionar() {
        var r = input.getBoundingClientRect();
        dd.style.top = r.bottom + 'px';
        dd.style.left = r.left + 'px';
        dd.style.width = Math.max(r.width, 420) + 'px';
    }
    input.addEventListener('input', function() {
        clearTimeout(timer);
        var v = this.value.trim();
        if (v.length < 1) { ocultar(); return; }
        timer = setTimeout(function() {
            var url = OrdenesCompra.API_URL + '/empleados?buscar=' + encodeURIComponent(v) + '&limit=20&estado=1&id_empresa=' + (OrdenesCompra.sesion ? OrdenesCompra.sesion.id_empresa : '');
            if (OrdenesCompra.sesion && OrdenesCompra.sesion.id_sucursal) url += '&id_sucursal=' + OrdenesCompra.sesion.id_sucursal;
            fetch(url).then(function(r) { return r.json(); }).then(function(res) {
                posicionar();
                if (!res.ok || !res.data || res.data.length === 0) {
                    dd.innerHTML = '<div style="padding:10px;color:#94a3b8;font-size:13px;text-align:center">Sin resultados</div>';
                    dd.style.display = 'block'; return;
                }
                var h = '';
                res.data.forEach(function(item) {
                    h += '<div class="prov-ubigeo-dd-item prov-autocomplete-item" style="cursor:pointer" data-id="' + item.id_empleado + '" data-nombre="' + (item.nombre || '').replace(/"/g, '&quot;') + '">' + item.nombre + '</div>';
                });
                dd.innerHTML = h;
                dd.style.display = 'block';
                dd.querySelectorAll('.prov-autocomplete-item').forEach(function(el) {
                    el.addEventListener('click', function() {
                        input.value = this.dataset.nombre;
                        if (hiddenId) hiddenId.value = this.dataset.id;
                        ocultar();
                    });
                });
            });
        }, 300);
    });
    document.addEventListener('click', function(e) {
        if (!e.target.closest('#ocFormSolicitadoPor') && !dd.contains(e.target)) ocultar();
    });
    input.addEventListener('blur', function() {
        setTimeout(ocultar, 200);
    });
};

OrdenesCompra.iniciarAutocompleteArticulo = function() {
    var input = document.getElementById('ocAddArticulo');
    if (!input || input.dataset._autoArtOk) return;
    input.dataset._autoArtOk = '1';
    var hiddenId = document.getElementById('ocAddIdArticulo');
    var hiddenCod = document.getElementById('ocAddCodArticulo');
    var hiddenUni = document.getElementById('ocAddCodUnidad');
    var dd = document.createElement('div');
    dd.style.cssText = 'position:fixed;z-index:9999;background:#fff;border:1px solid #e2e8f0;border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,0.1);max-height:350px;overflow-y:auto;display:none';
    document.body.appendChild(dd);
    var timer;
    function ocultar() { dd.style.display = 'none'; dd.innerHTML = ''; }
    function posicionar() {
        var r = input.getBoundingClientRect();
        dd.style.top = r.bottom + 'px';
        dd.style.left = r.left + 'px';
        dd.style.width = Math.max(r.width, 420) + 'px';
    }
    input.addEventListener('input', function() {
        clearTimeout(timer);
        var v = this.value.trim();
        if (v.length < 1) { ocultar(); return; }
        timer = setTimeout(function() {
            var url = OrdenesCompra.API_URL + '/articulos?buscar=' + encodeURIComponent(v) + '&limit=20&estado=1&id_empresa=' + (OrdenesCompra.sesion ? OrdenesCompra.sesion.id_empresa : '');
            if (OrdenesCompra.sesion && OrdenesCompra.sesion.id_sucursal) url += '&id_sucursal=' + OrdenesCompra.sesion.id_sucursal;
            fetch(url).then(function(r) { return r.json(); }).then(function(res) {
                posicionar();
                if (!res.ok || !res.data || res.data.length === 0) {
                    dd.innerHTML = '<div style="padding:10px;color:#94a3b8;font-size:13px;text-align:center">Sin resultados</div>';
                    dd.style.display = 'block'; return;
                }
                var h = '';
                res.data.forEach(function(item) {
                    h += '<div class="prov-ubigeo-dd-item prov-autocomplete-item" style="cursor:pointer" data-id="' + item.id_articulo + '" data-cod="' + item.cod_articulo + '" data-unidad="' + (item.cod_unidad || '') + '" data-nombre="' + (item.nombre || '').replace(/"/g, '&quot;') + '">' + item.cod_articulo + ' - ' + item.nombre + '</div>';
                });
                dd.innerHTML = h;
                dd.style.display = 'block';
                dd.querySelectorAll('.prov-autocomplete-item').forEach(function(el) {
                    el.addEventListener('click', function() {
                        input.value = this.dataset.nombre;
                        if (hiddenId) hiddenId.value = this.dataset.id;
                        if (hiddenCod) hiddenCod.value = this.dataset.cod;
                        if (hiddenUni) hiddenUni.value = this.dataset.unidad;
                        setTimeout(function() { document.getElementById('ocAddCantidad').focus(); }, 100);
                        ocultar();
                    });
                });
            });
        }, 300);
    });
    document.addEventListener('click', function(e) {
        if (!e.target.closest('#ocAddArticulo') && !dd.contains(e.target)) ocultar();
    });
    input.addEventListener('blur', function() {
        setTimeout(ocultar, 200);
    });
};

OrdenesCompra.agregarItemDesdeForm = function() {
    var idArt = document.getElementById('ocAddIdArticulo');
    var codArt = document.getElementById('ocAddCodArticulo');
    var nombre = document.getElementById('ocAddArticulo');
    var cantidad = document.getElementById('ocAddCantidad');
    var precio = document.getElementById('ocAddPrecio');
    var unidad = document.getElementById('ocAddCodUnidad');
    var descuentoInput = document.getElementById('ocAddDescuento');

    if (!idArt || !idArt.value) { Mensaje.error({ titulo: 'Validación', texto: 'Seleccione un artículo' }); return; }
    var cant = parseFloat(cantidad ? cantidad.value : 0) || 0;
    if (cant <= 0) { Mensaje.error({ titulo: 'Validación', texto: 'Ingrese cantidad mayor a 0' }); return; }
    var prec = parseFloat(precio ? precio.value : 0) || 0;
    if (prec <= 0) { Mensaje.error({ titulo: 'Validación', texto: 'Ingrese precio mayor a 0' }); return; }
    var descPct = parseFloat(descuentoInput ? descuentoInput.value : 0) || 0;

    var dup = OrdenesCompra.detalleItems.find(function(item) { return item.id_articulo == idArt.value; });
    if (dup) { Mensaje.error({ titulo: 'Validación', texto: 'El artículo ya está en el detalle' }); return; }

    OrdenesCompra.detalleItems.push({
        id_articulo: parseInt(idArt.value),
        cod_articulo: codArt ? codArt.value : '',
        nombre: nombre ? nombre.value : '',
        cod_unidad: unidad ? unidad.value : '',
        cantidad: cant,
        precio: prec,
        total: cant * prec,
        descuento_pct: descPct,
        descuento: (cant * prec) * descPct / 100
    });

    OrdenesCompra.renderDetalle();
    OrdenesCompra.calcularTotales();

    if (nombre) nombre.value = '';
    if (idArt) idArt.value = '';
    if (codArt) codArt.value = '';
    if (unidad) unidad.value = '';
    if (cantidad) cantidad.value = '';
    if (precio) precio.value = '';
    if (descuentoInput) descuentoInput.value = '';
    if (nombre) nombre.focus();
};

var _ocMostrarVista = OrdenesCompra.mostrarVista;
OrdenesCompra.mostrarVista = function() {
    var self = this;

    var _origCargar = this.cargarTabla;
    var skipFirst = true;
    this.cargarTabla = function() {
        if (skipFirst) { skipFirst = false; return Promise.resolve(); }
        return _origCargar.apply(this, arguments);
    };
    _ocMostrarVista.call(this);
    this.cargarTabla = _origCargar;

    var h2 = document.querySelector('#' + this.elementId + ' .prov-header-titulo h2');
    if (h2) h2.style.display = 'none';
    var pTitle = document.querySelector('#' + this.elementId + ' .prov-header-titulo p');
    if (pTitle && this.sesion && this.sesion.empresa_razon) pTitle.textContent = this.sesion.empresa_razon;

    var wrap = document.getElementById(this.elementId + 'TablaWrap');
    if (!wrap) return;

    var oldBar = document.getElementById('ocFechaBar');
    if (oldBar) oldBar.remove();

    var hoy = new Date();
    var fmtHoy = hoy.toLocaleDateString('en-CA');
    var fmtMes = new Date(hoy.getFullYear(), hoy.getMonth(), 1).toLocaleDateString('en-CA');

    var bar = document.createElement('div');
    bar.id = 'ocFechaBar';
    bar.style.cssText = 'display:flex;align-items:center;gap:10px;padding:10px 20px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:0.82rem';
    bar.innerHTML =
        '<i class="fas fa-calendar-alt" style="color:#1A4480;font-size:0.9rem"></i>' +
        '<span style="color:#475569;font-weight:600">Desde:</span>' +
        '<input type="date" id="ocFechaDesde" class="prov-input" value="' + fmtMes + '" style="width:150px;padding:5px 8px;font-size:0.8rem">' +
        '<span style="color:#475569;font-weight:600">Hasta:</span>' +
        '<input type="date" id="ocFechaHasta" class="prov-input" value="' + fmtHoy + '" style="width:150px;padding:5px 8px;font-size:0.8rem">' +
        '<button class="btn-prov btn-prov-primario" id="ocBtnLimpiarFecha" style="padding:5px 14px;font-size:0.78rem">Limpiar</button>';

    wrap.parentNode.insertBefore(bar, wrap);

    function recargar() { self.paginaActual = 1; self.cargarTabla(); }
    document.getElementById('ocFechaDesde').addEventListener('change', recargar);
    document.getElementById('ocFechaHasta').addEventListener('change', recargar);
    document.getElementById('ocBtnLimpiarFecha').addEventListener('click', function() {
        document.getElementById('ocFechaDesde').value = fmtMes;
        document.getElementById('ocFechaHasta').value = fmtHoy;
        recargar();
    });

    self.cargarTabla();
};

OrdenesCompra.obtenerParamsExtra = function() {
    var desde = document.getElementById('ocFechaDesde');
    var hasta = document.getElementById('ocFechaHasta');
    var s = '';
    if (desde && desde.value) s += '&fecha_desde=' + encodeURIComponent(desde.value);
    if (hasta && hasta.value) s += '&fecha_hasta=' + encodeURIComponent(hasta.value);
    return s;
};

var _ocCargarTabla = OrdenesCompra.cargarTabla;
OrdenesCompra.cargarTabla = function() {
    var self = this;
    return _ocCargarTabla.call(this).then(function() {
        var wrap = document.getElementById(self.elementId + 'TablaWrap');
        if (!wrap || !self.currentData) return;
        var rows = wrap.querySelectorAll('table tbody tr');
        rows.forEach(function(tr, idx) {
            var rowData = self.currentData[idx];
            if (!rowData) return;
            var badges = { P: 'prov-badge-pendiente', A: 'prov-badge-activo', C: 'prov-badge-cerrado', N: 'prov-badge-anulado' };
            var tds = tr.querySelectorAll('td');
            var colIdx = self.columns.findIndex(function(c) { return c.field === 'estado'; });
            if (colIdx >= 0 && tds[colIdx] && badges[rowData.estado]) {
                tds[colIdx].innerHTML = '<span class="prov-badge ' + badges[rowData.estado] + '">' + tds[colIdx].textContent.trim() + '</span>';
            }
            var acc = tr.querySelector('.prov-acciones');
            if (!acc) return;
            var est = rowData.estado;
            var numOc = rowData.num_oc;
            if (est === 'P') {
                acc.insertAdjacentHTML('beforeend', '<button class="prov-btn-accion oc-btn-estado" title="Aprobar" data-id="' + numOc + '" data-estado="A"><i class="fas fa-check" style="color:#10b981"></i></button>');
                acc.insertAdjacentHTML('beforeend', '<button class="prov-btn-accion oc-btn-estado" title="Anular" data-id="' + numOc + '" data-estado="N"><i class="fas fa-ban" style="color:#ef4444"></i></button>');
            } else if (est === 'A') {
                acc.insertAdjacentHTML('beforeend', '<button class="prov-btn-accion oc-btn-estado" title="Cerrar" data-id="' + numOc + '" data-estado="C"><i class="fas fa-lock" style="color:#1A4480"></i></button>');
                acc.insertAdjacentHTML('beforeend', '<button class="prov-btn-accion oc-btn-estado" title="Anular" data-id="' + numOc + '" data-estado="N"><i class="fas fa-ban" style="color:#ef4444"></i></button>');
            }
        });
        wrap.querySelectorAll('.oc-btn-estado').forEach(function(btn) {
            btn.addEventListener('click', function(e) {
                e.stopPropagation();
                self.cambiarEstado(this.dataset.id, this.dataset.estado);
            });
        });

        // Context menu for Pedido column
        var pedColIdx = self.columns.findIndex(function(c) { return c.field === 'num_ped'; });
        if (pedColIdx >= 0) {
            var ctxMenu = document.getElementById('ocCtxMenu');
            if (!ctxMenu) {
                ctxMenu = document.createElement('div');
                ctxMenu.id = 'ocCtxMenu';
                ctxMenu.style.cssText = 'position:fixed;z-index:99999;background:#fff;border:1px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 16px rgba(0,0,0,0.12);padding:4px 0;display:none;min-width:180px';
                document.body.appendChild(ctxMenu);
                document.addEventListener('click', function(e) {
                    if (!ctxMenu.contains(e.target)) ctxMenu.style.display = 'none';
                });
                document.addEventListener('contextmenu', function(e) {
                    if (!ctxMenu.contains(e.target)) ctxMenu.style.display = 'none';
                });
            }
            rows.forEach(function(tr) {
                var td = tr.querySelectorAll('td')[pedColIdx];
                if (!td) return;
                td.style.cursor = 'context-menu';
                td.addEventListener('contextmenu', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    var numPed = (this.textContent || '').trim();
                    if (!numPed || numPed === '-') return;
                    ctxMenu.innerHTML =
                        '<div class="oc-ctx-item" data-ped="' + numPed + '" data-action="ver" style="padding:8px 14px;cursor:pointer;font-size:0.78rem;color:#1e293b;display:flex;align-items:center;gap:8px"><i class="fas fa-eye" style="color:#1A4480;width:16px;text-align:center"></i> Ver Pedido ' + numPed + '</div>' +
                        '<div class="oc-ctx-item" data-ped="' + numPed + '" data-action="imprimir" style="padding:8px 14px;cursor:pointer;font-size:0.78rem;color:#1e293b;display:flex;align-items:center;gap:8px"><i class="fas fa-print" style="color:#64748b;width:16px;text-align:center"></i> Imprimir Pedido ' + numPed + '</div>';
                    ctxMenu.style.left = e.clientX + 'px';
                    ctxMenu.style.top = e.clientY + 'px';
                    ctxMenu.style.display = 'block';
                    requestAnimationFrame(function() {
                        var r = ctxMenu.getBoundingClientRect();
                        if (r.right > window.innerWidth) ctxMenu.style.left = Math.max(0, e.clientX - r.width) + 'px';
                        if (r.bottom > window.innerHeight) ctxMenu.style.top = Math.max(0, e.clientY - r.height) + 'px';
                    });
                    ctxMenu.querySelectorAll('.oc-ctx-item').forEach(function(item) {
                        item.addEventListener('click', function(ev) {
                            ev.stopPropagation();
                            ctxMenu.style.display = 'none';
                            var ped = this.dataset.ped;
                            var parts = ped.split('-');
                            var pedEjercicio = parts.length > 1 ? parseInt(parts[0]) : new Date().getFullYear();
                            var pedNum = parts.length > 1 ? parts[1] : ped;
                            if (this.dataset.action === 'ver') {
                                if (typeof Pedidos !== 'undefined') {
                                    Pedidos.verDetalle(pedNum, pedEjercicio);
                                }
                            } else if (this.dataset.action === 'imprimir') {
                                if (typeof Pedidos !== 'undefined') {
                                    Pedidos.imprimirDetalleVer(pedNum, pedEjercicio);
                                }
                            }
                        });
                        item.addEventListener('mouseenter', function() { this.style.background = '#f1f5f9'; });
                        item.addEventListener('mouseleave', function() { this.style.background = ''; });
                    });
                });
            });
        }
    });
};

var _ocImprimir = OrdenesCompra.imprimir;
OrdenesCompra.imprimir = async function() {
    var datos = await this.obtenerTodosDatos();
    if (!datos || datos.length === 0) { Mensaje.error({ titulo: 'Imprimir', texto: 'No hay datos para imprimir' }); return; }
    var colMap = {};
    this.columns.forEach(function(c) { colMap[c.field] = c.label; });
    var filtros = [];
    if (Object.keys(this.filtrosColumna).length > 0) {
        for (var k in this.filtrosColumna) {
            if (k === 'estado') {
                var estMap = { P: 'Pendiente', A: 'Aprobado', C: 'Cerrado', N: 'Anulado' };
                filtros.push('Estado: ' + this.filtrosColumna[k].split(',').map(function(v) { return estMap[v.trim()] || v.trim(); }).join(', '));
            } else if (k === 'tipo') {
                filtros.push('Tipo: ' + this.filtrosColumna[k].split(',').map(function(v) { return v.trim() === 'M' ? 'Materiales' : 'Gastos'; }).join(', '));
            } else {
                filtros.push((colMap[k] || k) + ': ' + this.filtrosColumna[k]);
            }
        }
    }
    var buscarVal = document.getElementById(this.elementId + 'Buscar');
    if (buscarVal && buscarVal.value.trim()) filtros.push('Búsqueda: ' + buscarVal.value.trim());
    var desde = document.getElementById('ocFechaDesde');
    var hasta = document.getElementById('ocFechaHasta');
    if (desde && hasta) {
        var strDesde = desde.value ? fmtFecha(desde.value) : '';
        var strHasta = hasta.value ? fmtFecha(hasta.value) : '';
        if (strDesde || strHasta) filtros.push('Fecha: ' + (strDesde || '...') + ' - ' + (strHasta || '...'));
    }

    function fmtFecha(iso) {
        if (!iso) return '';
        var d = new Date(iso);
        if (isNaN(d.getTime())) return iso;
        return ('0' + d.getDate()).slice(-2) + '/' + ('0' + (d.getMonth() + 1)).slice(-2) + '/' + d.getFullYear();
    }

    var ahora = new Date();
    var fechaHora = ahora.toLocaleDateString('es-PE', { day: '2-digit', month: '2-digit', year: 'numeric' }) + ' ' + ahora.toLocaleTimeString('es-PE', { hour: '2-digit', minute: '2-digit' });

    var filasHtml = '';
    datos.forEach(function(row) {
        filasHtml += '<tr>';
        OrdenesCompra.columns.forEach(function(col, ci) {
            var val = row[col.field];
            if (col.render) val = col.render(row, val);
            else val = (val !== null && val !== undefined) ? String(val) : '';
            var cls = col.field === 'total' ? ' class="numeric"' : '';
            filasHtml += '<td' + cls + '>' + val + '</td>';
        }, OrdenesCompra);
        filasHtml += '</tr>';
    });

    var nCols = OrdenesCompra.columns.length;
    var cabecerasHtml = OrdenesCompra.columns.map(function(c) { var cls = c.field === 'total' ? ' class="numeric"' : ''; return '<th' + cls + '>' + c.label + '</th>'; }).join('');
    var di = await TablaGenerica._obtenerDatosImpresion();
    var ph = this._fechaHoraStr();

    var headerContent = '<div style="display:flex;justify-content:space-between;align-items:flex-start"><div>' + di.logoHtml + '<div style="display:inline-block;vertical-align:middle"><div style="font-size:1rem;font-weight:800;color:#1A4480;text-transform:uppercase;letter-spacing:0.5px">Órdenes de Compra</div>' + (di.empresa ? '<div style="font-size:0.72rem;color:#1A4480;font-weight:600;margin-top:3px">' + di.empresa + '</div>' : '') + (di.sucursal ? '<div style="font-size:0.65rem;color:#64748B;margin-top:1px">' + di.sucursal + '</div>' : '') + '</div></div><div style="text-align:right;font-size:0.6rem;color:#64748B;white-space:nowrap">' + ph + '</div></div>';
    var titleRow = '<tr><th class="print-title-row" colspan="' + nCols + '" style="background:#fff;color:#1E293B;padding:14px 8px 4px;text-align:left;font-weight:400;text-transform:none;letter-spacing:0;border-bottom:none">' + headerContent + '</th></tr>';
    var filtrosRow = filtros.length > 0 ? '<tr><th class="print-filtros-row" colspan="' + nCols + '" style="background:#fff;color:#475569;padding:6px 8px 10px;text-align:left;font-weight:400;text-transform:none;letter-spacing:0;border-bottom:none;font-size:0.65rem">' + filtros.join(' | ') + '</th></tr>' : '';
    var colRow = '<tr style="clip-path:inset(0 round 6px 6px 0 0)">' + cabecerasHtml + '</tr>';
    var tablaHtml = '<div style="border-radius:8px;overflow:hidden"><table><thead>' + titleRow + filtrosRow + colRow + '</thead><tbody>' + filasHtml + '</tbody></table></div>';

    this._imprimirSrcdoc(tablaHtml + '<div class="prov-print-total">Total: ' + datos.length + ' registro(s)</div>', 'Órdenes de Compra');
};

OrdenesCompra.cargarCondicionesPago = function(valorSeleccionado) {
    var sel = document.getElementById('ocFormCondicion');
    if (!sel) return;
    if (sel.dataset._cargado) {
        if (arguments.length && valorSeleccionado !== undefined && valorSeleccionado !== '') sel.value = valorSeleccionado;
        return;
    }
    fetch(OrdenesCompra.API_URL + '/condiciones-pago?limit=100&estado=1&id_empresa=' + (OrdenesCompra.sesion ? OrdenesCompra.sesion.id_empresa : ''))
        .then(function(r) { return r.json(); })
        .then(function(res) {
            if (res.ok && res.data) {
                sel.innerHTML = '<option value="">Seleccione...</option>';
                res.data.forEach(function(item) { sel.innerHTML += '<option value="' + item.id_condicion + '">' + item.nombre + '</option>'; });
                sel.dataset._cargado = '1';
                if (valorSeleccionado !== undefined && valorSeleccionado !== '') sel.value = valorSeleccionado;
            }
        });
};

OrdenesCompra.init({
    title: 'Órdenes de Compra',
    icon: 'fa-file-invoice',
    idSingular: 'OC',
    idField: 'num_oc',
    endpoint: '/ordenes-compra',
    sortDefault: 'fecha_oc',
    limite: 50,
    searchPlaceholder: 'Buscar por N° OC o proveedor...',
    filtroEstado: false,
    showEstado: false,
    showAcciones: true,
    exportFileName: 'OrdenesCompra',
    elementId: 'pageOrdenesCompra',
    menuPage: 'OrdenesCompra',
    columnFilters: {},
    columns: [
        { field: 'ejercicio', label: 'Ejerc.', sortable: true, filterable: true, width: '5%' },
        { field: 'num_oc', label: 'N° OC', sortable: true, filterable: true, width: '7%' },
        { field: 'num_ped', label: 'Pedido', sortable: true, filterable: true, width: '8%',
            render: function(row) { return (row.ped_ejercicio ? row.ped_ejercicio + '-' : '') + (row.num_ped || ''); }
        },
        { field: 'fecha_oc', label: 'Fecha', sortable: true, filterable: false, width: '9%',
            render: function(row) {
                if (!row.fecha_oc) return '';
                var d = new Date(row.fecha_oc);
                if (isNaN(d.getTime())) return row.fecha_oc;
                return ('0' + d.getDate()).slice(-2) + '/' + ('0' + (d.getMonth() + 1)).slice(-2) + '/' + d.getFullYear();
            }
        },
        { field: 'proveedor_razon_social', label: 'Proveedor', sortable: true, filterable: true, width: '23%' },
        { field: 'tipo', label: 'Tipo', sortable: true, filterable: true, width: '11%',
            render: function(row) { return row.tipo === 'M' ? 'Materiales' : 'Gastos'; }
        },
        { field: 'condicion_nombre', label: 'Cond. Pago', sortable: true, filterable: true, width: '10%',
            render: function(row) { return row.condicion_nombre || ''; }
        },
        { field: 'total', label: 'Total', sortable: true, filterable: false, width: '9%',
            render: function(row) {
                var total = parseFloat(row.total) || 0;
                return total.toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
            }
        },
        { field: 'estado', label: 'Estado', sortable: true, filterable: true, width: '10%',
            render: function(row) {
                var estados = { P: 'Pendiente', A: 'Aprobado', C: 'Cerrado', N: 'Anulado' };
                return estados[row.estado] || row.estado;
            }
        }
    ],
    onEliminar: function(numOc) {
        Mensaje.confirmar({
            titulo: 'Eliminar OC',
            texto: '¿Está seguro de eliminar la OC ' + numOc + '?',
            icono: 'warning'
        }, function() {
            fetch(OrdenesCompra.API_URL + OrdenesCompra.endpoint + '/' + numOc + '?id_empresa=' + (OrdenesCompra.sesion ? OrdenesCompra.sesion.id_empresa : ''), { method: 'DELETE' })
                .then(function(r) { return r.json(); })
                .then(function(res) {
                    if (res.ok) {
                        Mensaje.exito({ titulo: 'Eliminado', texto: res.mensaje });
                        OrdenesCompra.paginaActual = 1;
                        OrdenesCompra.cargarTabla();
                    } else {
                        Mensaje.error({ titulo: 'Error', texto: res.mensaje });
                    }
                })
                .catch(function() { Mensaje.error({ titulo: 'Error', texto: 'Error al eliminar' }); });
        });
    },
    renderFormulario: function(data) {
        OrdenesCompra.detalleItems = [];
        var html = '';
        html += '<div class="oc-section"><div class="oc-section-title"><i class="fas fa-file-invoice"></i> Cabecera</div>';
        html += '<div class="oc-grid-4">';
        html += '<div class="prov-field"><label>N° OC</label><div style="display:flex;gap:4px"><input type="text" id="ocFormEjercicio" class="prov-input" readonly style="background:#f3f4f6;color:#6b7280;width:70px;flex:none"><input type="text" id="ocFormNum" class="prov-input" readonly style="background:#f3f4f6;color:#6b7280;flex:1"></div></div>';
        html += '<div class="prov-field"><label>Fecha <span class="req">*</span></label><input type="date" id="ocFormFecha" class="prov-input" required></div>';
        html += '<div class="prov-field"><label>Fecha Entrega</label><input type="date" id="ocFormFechaEntrega" class="prov-input"></div>';
        html += '<div class="prov-field"><label>Tipo</label><select id="ocFormTipo" class="prov-input"><option value="M">Materiales</option><option value="G">Gastos</option></select></div>';
        html += '<div class="prov-field oc-field-full"><label>Proveedor <span class="req">*</span></label><input type="text" id="ocFormProveedor" class="prov-input" autocomplete="off" placeholder="Escriba nombre o RUC del proveedor..."><input type="hidden" id="ocFormIdProveedor"></div>';
        html += '<div class="prov-field"><label>Contacto</label><input type="text" id="ocFormContacto" class="prov-input" maxlength="100" placeholder="Nombre del contacto"></div>';
        html += '<div class="prov-field"><label>Solicitado por</label><input type="text" id="ocFormSolicitadoPor" class="prov-input" autocomplete="off" placeholder="Buscar empleado..."><input type="hidden" id="ocFormIdEmpleado"></div>';
        html += '<div class="prov-field"><label>Condición de Pago</label><select id="ocFormCondicion" class="prov-input"><option value="">Seleccione...</option></select></div>';
        html += '<div class="prov-field"><label>Moneda</label><select id="ocFormMoneda" class="prov-input"><option value="MN">Soles (MN)</option><option value="ME">Dólares (ME)</option></select></div>';
        html += '<div class="prov-field"><label>Tipo de Cambio</label><input type="number" id="ocFormTipoCambio" class="prov-input" step="0.001" min="0" placeholder="0.000"></div>';
        html += '<div class="prov-field oc-field-span-3"><label>Observaciones</label><input type="text" id="ocFormObs" class="prov-input" maxlength="500" placeholder="Opcional"></div>';
        html += '</div></div>';

        html += '<div class="oc-section oc-section-detalle"><div class="oc-section-title"><i class="fas fa-list"></i> Detalle <span id="ocDetCount" class="oc-count">(0 items)</span><button class="ped-detalle-print-btn oc-excel-btn" id="ocBtnExcelDetalle" title="Exportar Excel" style="color:#059669"><i class="fas fa-file-excel" style="color:#059669"></i></button><button class="ped-detalle-print-btn" id="ocBtnPrintDetalle" title="Imprimir OC" style="color:#1A4480"><i class="fas fa-print" style="color:#1A4480"></i></button></div>';
        html += '<div class="oc-detalle-table-wrap">';
        html += '<table class="oc-detalle-table"><thead><tr>' +
            '<th style="width:70px">Código</th><th>Artículo</th><th style="width:50px">Und</th><th style="width:100px">Cantidad</th><th style="width:110px">Precio</th><th style="width:70px">Desc %</th><th style="width:110px">Total</th><th style="width:45px"></th>' +
            '</tr></thead><tbody id="ocDetalleBody"></tbody></table>';
        html += '</div>';
        html += '<div class="oc-detalle-toolbar">';
        html += '<div class="prov-field oc-field-art"><label>Artículo</label><input type="text" id="ocAddArticulo" class="prov-input" placeholder="Buscar artículo..." autocomplete="off"><input type="hidden" id="ocAddIdArticulo"><input type="hidden" id="ocAddCodArticulo"><input type="hidden" id="ocAddCodUnidad"></div>';
        html += '<div class="prov-field oc-field-qty"><label>Cantidad</label><input type="number" id="ocAddCantidad" class="prov-input" step="0.001" min="0" placeholder="0.00" style="text-align:right"></div>';
        html += '<div class="prov-field oc-field-price"><label>Precio</label><input type="number" id="ocAddPrecio" class="prov-input" step="0.001" min="0" placeholder="0.000" style="text-align:right"></div>';
        html += '<div class="prov-field" style="width:80px"><label>Desc %</label><input type="number" id="ocAddDescuento" class="prov-input" step="any" min="0" max="100" placeholder="0" style="text-align:right"></div>';
        html += '<button class="btn-prov btn-prov-primario oc-btn-add-item" id="ocBtnAddItem"><i class="fas fa-plus"></i> Agregar</button>';
        html += '</div>';
        html += '<div class="oc-totales">';
        html += '<div class="oc-total-row"><span>Subtotal:</span><input type="text" id="ocFormSubtotal" class="oc-total-input" readonly value="0.00"></div>';
        html += '<div class="oc-total-row"><span>Descuento global:</span><button type="button" id="ocBtnDescTipo" class="oc-desc-toggle" style="padding:5px 8px;border:1px solid #d1d5db;border-right:none;border-radius:4px 0 0 4px;background:#1A4480;color:#fff;font-weight:700;font-size:0.78rem;cursor:pointer;white-space:nowrap">%</button><input type="number" id="ocFormDescGlobal" class="oc-total-input oc-desc-input" min="0" step="any" value="" placeholder="0" style="width:90px;border-radius:0 4px 4px 0"></div>';
        html += '<div class="oc-total-row"><span>Descuento:</span><input type="text" id="ocFormDescuento" class="oc-total-input" readonly value="0.00"></div>';
        html += '<div class="oc-total-row"><span id="ocIgvLabel">IGV:</span><input type="text" id="ocFormIgv" class="oc-total-input" readonly value="0.00"></div>';
        html += '<div class="oc-total-row oc-total-row-final"><span>Total:</span><input type="text" id="ocFormTotal" class="oc-total-input" readonly value="0.00"></div>';
        html += '</div>';
        html += '</div>';

        return html;
    },
    abrirModal: function(id) {
        var self = this;
        var pendingPedido = window._pedidoParaOC;
        window._pedidoParaOC = null;
        var titulo = pendingPedido ? 'Nueva OC desde Pedido ' + pendingPedido.num_ped : (id ? 'Editar OC' : 'Nueva Orden de Compra');
        var esNuevo = !id;

        var contenido = '<div class="oc-modal-form" id="' + this.elementId + 'Form">';
        contenido += '<input type="hidden" id="' + this.elementId + 'FormId" value="' + (id || '') + '">';
        contenido += '<input type="hidden" id="ocFormNumPedRef" value="' + (pendingPedido ? pendingPedido.num_ped : '') + '">';
        contenido += this.renderFormulario(null);
        contenido += '</div>';

        Modal.abrir({
            titulo: titulo,
            ancho: '1100px',
            alto: '95vh',
            contenido: contenido,
            botones: [
                { texto: 'Cancelar', tipo: 'secundario', accion: function() { Modal.cerrar(); } },
                { texto: 'Guardar', tipo: 'primario', accion: function() { self.onGuardar(); } }
            ]
        });

        OrdenesCompra.descuentoGlobalTipo = '%';
        var btnTipo = document.getElementById('ocBtnDescTipo');
        if (btnTipo) {
            btnTipo.addEventListener('click', function() {
                OrdenesCompra.descuentoGlobalTipo = OrdenesCompra.descuentoGlobalTipo === '%' ? 'S' : '%';
                this.textContent = OrdenesCompra.descuentoGlobalTipo === '%' ? '%' : 'S/';
                this.style.background = OrdenesCompra.descuentoGlobalTipo === '%' ? '#1A4480' : '#059669';
                OrdenesCompra.calcularTotales();
            });
        }
        var elDescGlobal = document.getElementById('ocFormDescGlobal');
        if (elDescGlobal) {
            elDescGlobal.addEventListener('input', function() { OrdenesCompra.calcularTotales(); });
            elDescGlobal.addEventListener('change', function() { OrdenesCompra.calcularTotales(); });
        }

        if (pendingPedido) {
            self._poblarDesdePedido(pendingPedido);
        } else if (esNuevo) {
            this.onCargarFormulario(null);
        } else {
            this.cargarDatos(id);
        }
    },
    onGuardar: function() {
        var numOc = document.getElementById('ocFormNum').value;
        var id = document.getElementById(OrdenesCompra.elementId + 'FormId').value;
        var fecha = document.getElementById('ocFormFecha').value;
        var idProv = document.getElementById('ocFormIdProveedor').value;
        var tipo = document.getElementById('ocFormTipo').value;
        var condicion = document.getElementById('ocFormCondicion').value;
        var moneda = document.getElementById('ocFormMoneda').value;
        var tipoCambio = document.getElementById('ocFormTipoCambio').value;
        var contacto = document.getElementById('ocFormContacto').value;
        var solicitadoPor = document.getElementById('ocFormSolicitadoPor').value;
        var fechaEntrega = document.getElementById('ocFormFechaEntrega').value;
        var obs = document.getElementById('ocFormObs').value;
        var subtotal = document.getElementById('ocFormSubtotal').value;
        var descuento = document.getElementById('ocFormDescuento')?.value || '0.00';
        var igv = document.getElementById('ocFormIgv').value;
        var total = document.getElementById('ocFormTotal').value;

        if (!fecha) { Mensaje.error({ titulo: 'Validación', texto: 'La fecha es requerida' }); return; }
        if (!idProv) { Mensaje.error({ titulo: 'Validación', texto: 'Seleccione un proveedor' }); return; }
        if (OrdenesCompra.detalleItems.length === 0) { Mensaje.error({ titulo: 'Validación', texto: 'Debe agregar al menos un artículo' }); return; }
        var sinPrecio = OrdenesCompra.detalleItems.some(function(item) { return !item.precio || parseFloat(item.precio) <= 0; });
        if (sinPrecio) { Mensaje.error({ titulo: 'Validación', texto: 'Todos los artículos deben tener un precio mayor a 0' }); return; }

        var descGlobalTipo = OrdenesCompra.descuentoGlobalTipo || '%';
        var descGlobalInput = parseFloat(document.getElementById('ocFormDescGlobal')?.value) || 0;
        var descLineasTotal = 0;
        OrdenesCompra.detalleItems.forEach(function(item) {
            var it = parseFloat(item.total) || 0;
            var dp = parseFloat(item.descuento_pct) || 0;
            descLineasTotal += it * dp / 100;
        });
        var subtotalBruto = parseFloat(subtotal) || 0;
        var subtotalNetoCalc = subtotalBruto - descLineasTotal;
        var descGlobalMonto = descGlobalTipo === '%' ? (subtotalNetoCalc * descGlobalInput / 100) : descGlobalInput;

        var body = {
            id_empresa: OrdenesCompra.sesion ? OrdenesCompra.sesion.id_empresa : null,
            ejercicio: parseInt(document.getElementById('ocFormEjercicio').value) || new Date().getFullYear(),
            fecha_oc: fecha,
            id_proveedor: parseInt(idProv),
            tipo: tipo,
            id_condicion: condicion ? parseInt(condicion) : null,
            moneda: moneda,
            tipo_cambio: tipoCambio ? parseFloat(tipoCambio) : null,
            con_igv: true,
            porcentaje_igv: parseFloat(OrdenesCompra.porcentajeIgv) || 18,
            subtotal: parseFloat(subtotal) || 0,
            descuento: descGlobalMonto,
            descuento_tipo: descGlobalTipo,
            descuento_valor: descGlobalInput,
            igv: parseFloat(igv) || 0,
            total: parseFloat(total) || 0,
            contacto: contacto || null,
            solicitado_por: solicitadoPor || null,
            fecha_entrega: fechaEntrega || null,
            observaciones: obs || null,
            num_ped: document.getElementById('ocFormNumPedRef')?.value || null,
            usuario_crea: OrdenesCompra.sesion ? OrdenesCompra.sesion.id_usuario : null,
            detalle: OrdenesCompra.detalleItems.map(function(item) {
                var itemTotal = parseFloat(item.total) || 0;
                var itemDescPct = parseFloat(item.descuento_pct) || 0;
                var itemDescMonto = itemTotal * itemDescPct / 100;
                return {
                    id_articulo: item.id_articulo,
                    cantidad: parseFloat(item.cantidad) || 0,
                    precio: parseFloat(item.precio) || 0,
                    total: itemTotal,
                    descuento: itemDescMonto
                };
            })
        };

        var metodo = id ? 'PUT' : 'POST';
        var url = OrdenesCompra.API_URL + OrdenesCompra.endpoint + (id ? '/' + id : '') + '?id_empresa=' + (body.id_empresa || '');

        fetch(url, {
            method: metodo,
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(body)
        })
        .then(function(r) { return r.json(); })
        .then(function(res) {
            if (res.ok) {
                Mensaje.exito({ titulo: 'Guardado', texto: res.mensaje });
                Modal.cerrar();
                OrdenesCompra.paginaActual = 1;
                OrdenesCompra.cargarTabla();
            } else {
                Mensaje.error({ titulo: 'Error', texto: res.mensaje });
            }
        })
        .catch(function() {
            Mensaje.error({ titulo: 'Error', texto: 'Error al guardar' });
        });
    },
    onCargarFormulario: function(data) {
        if (!data) {
            var hoy = new Date().toLocaleDateString('en-CA');
            document.getElementById('ocFormFecha').value = hoy;
            document.getElementById('ocFormEjercicio').value = String(new Date().getFullYear());
            document.getElementById('ocFormNum').value = 'Auto-generado';
            OrdenesCompra.iniciarAutocompleteProveedor();
            OrdenesCompra.iniciarAutocompleteEmpleado();
            OrdenesCompra.iniciarAutocompleteArticulo();
            OrdenesCompra.cargarCondicionesPago();
            if (OrdenesCompra.sesion) {
                fetch(OrdenesCompra.API_URL + '/configuracion/igv/' + OrdenesCompra.sesion.id_empresa)
                    .then(function(r) { return r.json(); })
                    .then(function(res) {
                        if (res.ok) OrdenesCompra.porcentajeIgv = parseFloat(res.data.porcentaje) || 18;
                        OrdenesCompra.calcularTotales();
                    });
            }
            OrdenesCompra.calcularTotales();
            document.getElementById('ocBtnAddItem').addEventListener('click', function() { OrdenesCompra.agregarItemDesdeForm(); });
            document.getElementById('ocAddPrecio').addEventListener('keydown', function(e) {
                if (e.key === 'Enter') { e.preventDefault(); OrdenesCompra.agregarItemDesdeForm(); }
            });
            document.getElementById('ocBtnPrintDetalle').addEventListener('click', function() { OrdenesCompra.imprimirDetalle(); });
            document.getElementById('ocBtnExcelDetalle').addEventListener('click', function() { OrdenesCompra.exportarExcelDetalle(); });
        } else {
            document.getElementById('ocFormEjercicio').value = data.ejercicio || '';
            document.getElementById('ocFormNum').value = data.num_oc || '';
            document.getElementById('ocFormFecha').value = data.fecha_oc ? data.fecha_oc.substring(0, 10) : '';
            document.getElementById('ocFormProveedor').value = data.proveedor_razon_social || '';
            document.getElementById('ocFormIdProveedor').value = data.id_proveedor || '';
            document.getElementById('ocFormTipo').value = data.tipo || 'M';
            document.getElementById('ocFormMoneda').value = data.moneda || 'MN';
            document.getElementById('ocFormTipoCambio').value = data.tipo_cambio || '';
            OrdenesCompra.porcentajeIgv = parseFloat(data.porcentaje_igv) || 18;
            document.getElementById('ocFormContacto').value = data.contacto || '';
            document.getElementById('ocFormSolicitadoPor').value = data.solicitado_por || '';
            document.getElementById('ocFormFechaEntrega').value = data.fecha_entrega ? data.fecha_entrega.substring(0, 10) : '';
            document.getElementById('ocFormObs').value = data.observaciones || '';
            var npRef = document.getElementById('ocFormNumPedRef');
            if (npRef && data.num_ped) npRef.value = data.num_ped;

            var descTipo = data.descuento_tipo || '%';
            var descValor = parseFloat(data.descuento_valor) || 0;
            OrdenesCompra.descuentoGlobalTipo = descTipo;
            var btnTipo = document.getElementById('ocBtnDescTipo');
            if (btnTipo) {
                btnTipo.textContent = descTipo === '%' ? '%' : 'S/';
                btnTipo.style.background = descTipo === '%' ? '#1A4480' : '#059669';
            }
            var elDescGlobal = document.getElementById('ocFormDescGlobal');
            if (elDescGlobal) elDescGlobal.value = descValor > 0 ? descValor : '';

            OrdenesCompra.iniciarAutocompleteProveedor();
            OrdenesCompra.iniciarAutocompleteEmpleado();
            OrdenesCompra.iniciarAutocompleteArticulo();
            OrdenesCompra.cargarCondicionesPago(data.id_condicion);

            if (data.detalle) {
                OrdenesCompra.detalleItems = data.detalle.map(function(d) {
                    var itemTotal = parseFloat(d.total) || 0;
                    var itemDesc = parseFloat(d.descuento) || 0;
                    var itemDescPct = itemTotal > 0 && itemDesc > 0 ? (itemDesc * 100 / itemTotal) : 0;
                    return {
                        id_articulo: d.id_articulo,
                        cod_articulo: d.cod_articulo || '',
                        nombre: d.nombre || '',
                        cod_unidad: d.cod_unidad || '',
                        cantidad: parseFloat(d.cantidad) || 0,
                        precio: parseFloat(d.precio) || 0,
                        total: itemTotal,
                        descuento_pct: itemDescPct,
                        descuento: itemDesc
                    };
                });
                OrdenesCompra.renderDetalle();
                OrdenesCompra.calcularTotales();
            }

            document.getElementById('ocBtnAddItem').addEventListener('click', function() { OrdenesCompra.agregarItemDesdeForm(); });
            document.getElementById('ocAddPrecio').addEventListener('keydown', function(e) {
                if (e.key === 'Enter') { e.preventDefault(); OrdenesCompra.agregarItemDesdeForm(); }
            });
            document.getElementById('ocBtnPrintDetalle').addEventListener('click', function() { OrdenesCompra.imprimirDetalle(); });
            document.getElementById('ocBtnExcelDetalle').addEventListener('click', function() { OrdenesCompra.exportarExcelDetalle(); });
        }
    }
});

OrdenesCompra._poblarDesdePedido = function(pedidoData) {
    var self = this;
    self.detalleItems = [];
    if (pedidoData.detalle) {
        pedidoData.detalle.forEach(function(d) {
            self.detalleItems.push({
                id_articulo: d.id_articulo,
                cod_articulo: d.cod_articulo || '',
                nombre: d.nombre || '',
                cod_unidad: d.cod_unidad || '',
                cantidad: parseFloat(d.cantidad) || 0,
                precio: 0,
                total: 0
            });
        });
    }

    var hoy = new Date().toLocaleDateString('en-CA');
    document.getElementById('ocFormEjercicio').value = String(new Date().getFullYear());
    document.getElementById('ocFormNum').value = 'Auto-generado';
    document.getElementById('ocFormFecha').value = hoy;
    document.getElementById('ocFormProveedor').value = pedidoData.proveedor_razon_social || '';
    document.getElementById('ocFormIdProveedor').value = pedidoData.id_proveedor || '';
    document.getElementById('ocFormTipo').value = pedidoData.tipo || 'M';
    document.getElementById('ocFormObs').value = pedidoData.observaciones || '';
    document.getElementById('ocFormCondicion').value = '';
    document.getElementById('ocFormMoneda').value = 'MN';
    document.getElementById('ocFormTipoCambio').value = '';
    document.getElementById('ocFormContacto').value = '';
    document.getElementById('ocFormSolicitadoPor').value = '';
    document.getElementById('ocFormFechaEntrega').value = '';

    OrdenesCompra.iniciarAutocompleteProveedor();
    OrdenesCompra.iniciarAutocompleteEmpleado();
    OrdenesCompra.iniciarAutocompleteArticulo();
    OrdenesCompra.cargarCondicionesPago();
    OrdenesCompra.renderDetalle();
    OrdenesCompra.calcularTotales();

    if (OrdenesCompra.sesion) {
        fetch(OrdenesCompra.API_URL + '/configuracion/igv/' + OrdenesCompra.sesion.id_empresa)
            .then(function(r) { return r.json(); })
            .then(function(res) {
                if (res.ok) OrdenesCompra.porcentajeIgv = parseFloat(res.data.porcentaje) || 18;
                OrdenesCompra.calcularTotales();
            });
    }

    document.getElementById('ocBtnAddItem').addEventListener('click', function() { OrdenesCompra.agregarItemDesdeForm(); });
    document.getElementById('ocAddPrecio').addEventListener('keydown', function(e) {
        if (e.key === 'Enter') { e.preventDefault(); OrdenesCompra.agregarItemDesdeForm(); }
    });
    document.getElementById('ocBtnPrintDetalle').addEventListener('click', function() { OrdenesCompra.imprimirDetalle(); });
    document.getElementById('ocBtnExcelDetalle').addEventListener('click', function() { OrdenesCompra.exportarExcelDetalle(); });
};

OrdenesCompra.cambiarEstado = function(numOc, nuevoEstado, ejercicio) {
    var self = this;
    var ejerc = ejercicio || new Date().getFullYear();
    var textos = { A: 'aprobar', C: 'cerrar', N: 'anular' };
    var confirmar = nuevoEstado === 'N' ? 'Esta seguro de anular la OC ' + numOc + '?' : 'Confirmar ' + textos[nuevoEstado] + ' OC ' + numOc + '?';
    Mensaje.confirmacion({ titulo: 'Cambiar estado', texto: confirmar, onAceptar: function() {
        fetch(self.API_URL + self.endpoint + '/' + numOc + '/estado?ejercicio=' + ejerc + '&id_empresa=' + (self.sesion ? self.sesion.id_empresa : ''), {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ estado: nuevoEstado })
        })
        .then(function(r) { return r.json(); })
        .then(function(res) {
            if (res.ok) {
                Mensaje.exito({ titulo: 'Estado cambiado', texto: res.mensaje });
                Modal.cerrar();
                self.paginaActual = 1;
                self.cargarTabla();
            } else {
                Mensaje.error({ titulo: 'Error', texto: res.mensaje });
            }
        })
        .catch(function(err) { console.error('[ESTADO]', err); Mensaje.error({ titulo: 'Error', texto: 'Error al cambiar estado: ' + (err.message || err) }); });
    } });
};

OrdenesCompra.verDetalle = async function(numOc, ejercicio) {
    var self = this;
    try {
        var params = '?id_empresa=' + (self.sesion ? self.sesion.id_empresa : '') + '&ejercicio=' + (ejercicio || new Date().getFullYear());
        var res = await fetch(self.API_URL + self.endpoint + '/' + numOc + params);
        var data = await res.json();
        if (!data.ok) { Mensaje.error({ titulo: 'Error', texto: data.mensaje }); return; }
        var row = data.data;
        var estados = { P: 'Pendiente', A: 'Aprobado', C: 'Cerrado', N: 'Anulado' };
        var html = '<div class="ped-detalle-view">';

        html += '<div class="ped-section"><div class="ped-section-title"><i class="fas fa-file-invoice"></i> Orden de Compra<button class="ped-detalle-print-btn oc-excel-btn" id="ocViewExcelBtn" title="Exportar Excel" style="color:#059669"><i class="fas fa-file-excel" style="color:#059669"></i></button><button class="ped-detalle-print-btn" id="ocViewPrintBtn" title="Imprimir" style="color:#1A4480"><i class="fas fa-print" style="color:#1A4480"></i></button></div>';
        html += '<div class="ped-detalle-grid oc-detalle-grid">';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">N° OC:</span><span class="ped-detalle-valor">' + ((row.ejercicio || '') ? row.ejercicio + '-' + row.num_oc : (row.num_oc || '')) + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">Pedido Origen:</span><span class="ped-detalle-valor">' + ((row.ped_ejercicio ? row.ped_ejercicio + '-' : '') + (row.num_ped || '')) + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">Fecha:</span><span class="ped-detalle-valor">' + (row.fecha_oc ? row.fecha_oc.split('T')[0].split('-').reverse().join('/') : '') + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">Proveedor:</span><span class="ped-detalle-valor">' + (row.proveedor_razon_social || '') + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">Tipo:</span><span class="ped-detalle-valor">' + (row.tipo === 'M' ? 'Materiales' : 'Gastos') + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">Moneda:</span><span class="ped-detalle-valor">' + (row.moneda === 'ME' ? 'Dolares' : 'Soles') + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">T.Cambio:</span><span class="ped-detalle-valor">' + (row.tipo_cambio ? parseFloat(row.tipo_cambio).toFixed(3) : '') + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">Contacto:</span><span class="ped-detalle-valor">' + ((row.contacto || '').toUpperCase()) + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">Solicitado por:</span><span class="ped-detalle-valor">' + ((row.solicitado_por || '').toUpperCase()) + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">Fecha Entrega:</span><span class="ped-detalle-valor">' + (row.fecha_entrega ? row.fecha_entrega.split('T')[0].split('-').reverse().join('/') : '') + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">Estado:</span><span class="ped-detalle-valor">' + (estados[row.estado] || row.estado) + '</span></div>';
        html += '<div class="ped-detalle-row"><span class="ped-detalle-label">Observaciones:</span><span class="ped-detalle-valor">' + (row.observaciones || '') + '</span></div>';
        html += '</div></div>';

        html += '<div class="ped-section"><div class="ped-section-title"><i class="fas fa-list"></i> Detalle</div>';
        html += '<table class="ped-detalle-table"><thead><tr><th style="width:80px">Codigo</th><th>Articulo</th><th style="width:50px">Und</th><th style="width:90px;text-align:right">Cantidad</th><th style="width:100px;text-align:right">Precio</th><th style="width:70px;text-align:right">Desc %</th><th style="width:100px;text-align:right">Total</th></tr></thead><tbody>';
        if (row.detalle && row.detalle.length > 0) {
            row.detalle.forEach(function(d) {
                var dTotal = parseFloat(d.total) || 0;
                var dDesc = parseFloat(d.descuento) || 0;
                var dDescPct = dTotal > 0 && dDesc > 0 ? (dDesc * 100 / dTotal) : 0;
                html += '<tr><td>' + (d.cod_articulo || '') + '</td><td>' + (d.nombre || '') + '</td><td>' + (d.cod_unidad || '') + '</td><td style="text-align:right">' + (parseFloat(d.cantidad) || 0).toFixed(3) + '</td><td style="text-align:right">' + (parseFloat(d.precio) || 0).toFixed(3) + '</td><td style="text-align:right">' + (dDescPct > 0 ? dDescPct.toFixed(2) + '%' : '') + '</td><td style="text-align:right">' + dTotal.toFixed(2) + '</td></tr>';
            });
        } else {
            html += '<tr><td colspan="7" style="text-align:center;color:#94a3b8">Sin detalle</td></tr>';
        }
        html += '</tbody></table>';
        var descFromDetail = 0;
        if (row.detalle) {
            row.detalle.forEach(function(d) { descFromDetail += parseFloat(d.descuento) || 0; });
        }
        var descGlobalMonto = 0;
        var descGlobalTipo = row.descuento_tipo || '%';
        var descGlobalValor = parseFloat(row.descuento_valor) || 0;
        var igvRate = (parseFloat(row.porcentaje_igv) || 18) / 100;
        var netoBeforeIgv = (parseFloat(row.total) || 0) / (1 + igvRate);
        descGlobalMonto = (parseFloat(row.subtotal) || 0) - descFromDetail - netoBeforeIgv;
        if (descGlobalMonto < 0) descGlobalMonto = 0;
        html += '<div style="display:flex;justify-content:flex-end;padding:8px 0;margin-top:4px"><table style="border-collapse:collapse;font-size:0.75rem"><tbody>';
        html += '<tr><td style="padding:4px 12px;text-align:right;color:#475569;font-weight:500;border:none">Subtotal</td><td style="padding:4px 12px;text-align:right;font-weight:600;color:#334155;min-width:100px;border:none">' + (parseFloat(row.subtotal) || 0).toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '</td></tr>';
        if (descFromDetail > 0) {
            html += '<tr><td style="padding:4px 12px;text-align:right;color:#c2410c;font-weight:500;border:none">Descuento por línea</td><td style="padding:4px 12px;text-align:right;font-weight:600;color:#c2410c;border:1px solid #d1d5db;border-radius:4px;background:#FFF7ED">-' + descFromDetail.toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '</td></tr>';
        }
        if (descGlobalMonto > 0) {
            var descLabel = descGlobalTipo === '%' ? 'Descuento global (' + descGlobalValor.toFixed(2) + '%)' : 'Descuento global';
            html += '<tr><td style="padding:4px 12px;text-align:right;color:#c2410c;font-weight:500;border:none">' + descLabel + '</td><td style="padding:4px 12px;text-align:right;font-weight:600;color:#c2410c;border:1px solid #d1d5db;border-radius:4px;background:#FFF7ED">-' + descGlobalMonto.toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '</td></tr>';
        }
        html += '<tr><td style="padding:4px 12px;text-align:right;color:#475569;font-weight:500;border:none">IGV</td><td style="padding:4px 12px;text-align:right;font-weight:600;color:#334155;border:none">' + (parseFloat(row.igv) || 0).toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '</td></tr>';
        html += '<tr><td style="padding:6px 12px;text-align:right;color:#1A4480;font-weight:700;font-size:0.85rem;border:none">TOTAL</td><td style="padding:6px 12px;text-align:right;font-weight:700;color:#1A4480;font-size:0.85rem;border:none">' + (parseFloat(row.total) || 0).toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '</td></tr>';
        html += '</tbody></table></div></div>';

        var btnAprobar = row.estado === 'P' ? '<button class="btn-prov btn-prov-primario" id="ocBtnAprobar" style="font-size:0.78rem"><i class="fas fa-check"></i> Aprobar</button>' : '';
        var btnCerrar = row.estado === 'A' ? '<button class="btn-prov btn-prov-primario" id="ocBtnCerrar" style="font-size:0.78rem"><i class="fas fa-lock"></i> Cerrar</button>' : '';
        var btnAnular = (row.estado === 'P' || row.estado === 'A') ? '<button class="btn-prov" id="ocBtnAnular" style="font-size:0.78rem;background:#f1f5f9;color:#ef4444;border:1px solid #fecaca;border-radius:8px;padding:8px 16px;cursor:pointer;font-weight:600"><i class="fas fa-ban"></i> Anular</button>' : '';
        var accionesHtml = '';
        if (btnAprobar || btnCerrar || btnAnular) {
            accionesHtml = '<div class="ped-section" style="text-align:center;padding:12px 20px;display:flex;gap:10px;justify-content:center">' + btnAprobar + btnCerrar + btnAnular + '</div>';
        }
        html += accionesHtml;
        html += '</div>';

        Modal.abrir({
            titulo: 'Detalle de OC ' + numOc,
            ancho: '780px',
            contenido: html,
            botones: [
                { texto: 'Cerrar', tipo: 'primario', accion: function() { Modal.cerrar(); } }
            ],
            onAbierto: function() {
                var btn = document.getElementById('ocViewPrintBtn');
                if (btn) {
                    btn.onclick = function() { self.imprimirDetalleVer(numOc, ejercicio); };
                }
                var btnExcel = document.getElementById('ocViewExcelBtn');
                if (btnExcel) {
                    btnExcel.onclick = function() { self.exportarExcelVer(numOc, ejercicio); };
                }
                var elAprobar = document.getElementById('ocBtnAprobar');
                if (elAprobar) elAprobar.onclick = function() { self.cambiarEstado(numOc, 'A', ejercicio); };
                var elCerrar = document.getElementById('ocBtnCerrar');
                if (elCerrar) elCerrar.onclick = function() { self.cambiarEstado(numOc, 'C', ejercicio); };
                var elAnular = document.getElementById('ocBtnAnular');
                if (elAnular) elAnular.onclick = function() { self.cambiarEstado(numOc, 'N', ejercicio); };
            }
        });
    } catch (error) {
        Mensaje.error({ titulo: 'Error', texto: 'Error al cargar detalle de OC' });
    }
};

OrdenesCompra._fechaHoraStr = function() {
    var a = new Date();
    return a.toLocaleDateString('es-PE', { day: '2-digit', month: '2-digit', year: 'numeric' }) + ' ' + a.toLocaleTimeString('es-PE', { hour: '2-digit', minute: '2-digit' });
};

OrdenesCompra._imprimirSrcdoc = function(html, titulo) {
    var fullHtml = '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>' + (titulo || 'Reporte') + '</title>' +
        '<link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">' +
        '<style>' +
        '*{margin:0;padding:0;box-sizing:border-box}' +
        'body{font-family:"Plus Jakarta Sans",sans-serif;padding:30px 40px;color:#1E293B}' +
        '.prov-print-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:16px;padding-bottom:12px;border-bottom:2px solid #1A4480}' +
        '.prov-print-titulo{font-size:1.2rem;font-weight:800;color:#1A4480;text-transform:uppercase;letter-spacing:0.5px}' +
        '.prov-print-filtros{font-size:0.72rem;color:#475569;background:#F1F5F9;padding:5px 10px;border-radius:6px;margin-bottom:14px}' +
        'thead{display:table-header-group}tr{page-break-inside:avoid}' +
        'table{width:100%;border-collapse:separate;border-spacing:0;font-size:0.72rem}' +
        'thead th{background:#1A4480;color:#FFF;padding:7px 8px;text-align:center;font-weight:700;text-transform:uppercase;font-size:0.6rem;letter-spacing:0.5px;border-bottom:2px solid #0F2847;white-space:nowrap}' +
        'thead th.numeric,td.numeric{text-align:right}' +
        'td{padding:5px 8px;border-bottom:1px solid #E2E8F0}' +
        '.oc-det-tbl td.numeric{text-align:right}' +
        'tbody tr:nth-child(even){background:#F8FAFC}' +
        '.prov-print-total{font-size:0.75rem;color:#1A4480;font-weight:600;margin-top:12px}' +
        '.prov-print-fecha{font-size:0.65rem;color:#64748B;text-align:right;margin-bottom:4px}' +
        '.prov-print-footer{text-align:center;font-size:0.65rem;color:#94A3B8;margin-top:20px;border-top:1px solid #E2E8F0;padding-top:8px}' +
        '@page{margin:12mm;@bottom-center{content:counter(page);font-family:"Plus Jakarta Sans",sans-serif;font-size:0.65rem;color:#94A3B8}}' +
        '<' + 'script' + '>window.onload=function(){setTimeout(function(){window.print()},800)};<' + '/' + 'script' + '>' +
        '</style></head><body>' + html + '<div class="prov-print-footer">NexusERP</div></body></html>';

    var oldIframe = document.getElementById('oc-print-frame');
    if (oldIframe) document.body.removeChild(oldIframe);

    var iframe = document.createElement('iframe');
    iframe.id = 'oc-print-frame';
    iframe.style.cssText = 'position:absolute;width:1px;height:1px;opacity:0.01;top:-9999px;left:-9999px';
    iframe.srcdoc = fullHtml;
    document.body.appendChild(iframe);
    iframe.onload = function() {
        setTimeout(function() {
            try { iframe.contentWindow.print(); } catch(e) {}
        }, 1500);
    };
};

OrdenesCompra.imprimirDetalle = function() {
    if (!this.detalleItems || this.detalleItems.length === 0) {
        Mensaje.error({ titulo: 'Imprimir', texto: 'No hay items en el detalle para imprimir' });
        return;
    }
    var ocEj = document.getElementById('ocFormEjercicio')?.value || '';
    var numOc = document.getElementById('ocFormNum')?.value || '';
    var proveedor = document.getElementById('ocFormProveedor')?.value || '';
    var fecha = document.getElementById('ocFormFecha')?.value || '';
    var contacto = document.getElementById('ocFormContacto')?.value || '';
    var solicitadoPor = document.getElementById('ocFormSolicitadoPor')?.value || '';
    var fechaEntrega = document.getElementById('ocFormFechaEntrega')?.value || '';
    var numPedRef = document.getElementById('ocFormNumPedRef')?.value || '';
    var empresa = this.sesion?.empresa_razon || '';
    var filas = '';
    var descuentoLineas = 0;
    this.detalleItems.forEach(function(item) {
        var itemTotal = parseFloat(item.total) || 0;
        var itemDescPct = parseFloat(item.descuento_pct) || 0;
        var itemDescMonto = itemTotal * itemDescPct / 100;
        descuentoLineas += itemDescMonto;
        filas += '<tr><td>' + (item.cod_articulo || '') + '</td><td>' + (item.nombre || '') + '</td><td>' + (item.cod_unidad || '') + '</td><td style="text-align:right">' + (parseFloat(item.cantidad) || 0).toFixed(3) + '</td><td style="text-align:right">' + (parseFloat(item.precio) || 0).toFixed(3) + '</td><td style="text-align:right">' + (itemDescPct > 0 ? itemDescPct.toFixed(2) + '%' : '') + '</td><td style="text-align:right">' + itemTotal.toFixed(2) + '</td></tr>';
    });
    var total = this.detalleItems.reduce(function(sum, item) { return sum + (parseFloat(item.total) || 0); }, 0);
    var subtotalNeto = total - descuentoLineas;
    var descGlobalTipo = OrdenesCompra.descuentoGlobalTipo || '%';
    var descGlobalVal = parseFloat(document.getElementById('ocFormDescGlobal')?.value) || 0;
    var descGlobalMonto = 0;
    if (descGlobalTipo === '%') {
        descGlobalMonto = subtotalNeto * descGlobalVal / 100;
    } else {
        descGlobalMonto = descGlobalVal;
    }
    subtotalNeto = subtotalNeto - descGlobalMonto;
    var igvCalc = subtotalNeto * (parseFloat(OrdenesCompra.porcentajeIgv) || 18) / 100;
    var totalFinal = subtotalNeto + igvCalc;
    var ph = this._fechaHoraStr();
    var ocDisplay = ocEj ? ocEj + '-' + numOc : (numOc || 'Auto-generado');
    var pedDisplay = numPedRef ? (ocEj ? ocEj + '-' + numPedRef : numPedRef) : '';
    var tituloHtml = '<div class="prov-print-header"><div><div class="prov-print-titulo">Orden de Compra</div>' + (empresa ? '<div style="font-size:0.8rem;color:#1A4480;font-weight:600;margin-top:4px">' + empresa + '</div>' : '') + '</div><div class="prov-print-fecha">' + ph + '</div></div>';
    function _ocFmtFechaInput(v) { if (!v) return ''; var p = v.split('-'); return p.length === 3 ? p[2] + '/' + p[1] + '/' + p[0] : v; }
    var infoHtml = '<div style="margin:12px 0;font-size:0.72rem;display:grid;grid-template-columns:auto 1fr;gap:2px 12px;align-items:start"><strong style="color:#475569;white-space:nowrap">N\u00B0:</strong><span>' + ocDisplay + '</span><strong style="color:#475569;white-space:nowrap">Proveedor:</strong><span>' + proveedor + '</span>' + (pedDisplay ? '<strong style="color:#475569;white-space:nowrap">Pedido:</strong><span>' + pedDisplay + '</span>' : '') + '<strong style="color:#475569;white-space:nowrap">Fecha:</strong><span>' + _ocFmtFechaInput(fecha) + '</span><strong style="color:#475569;white-space:nowrap">Contacto:</strong><span>' + ((contacto || '').toUpperCase()) + '</span><strong style="color:#475569;white-space:nowrap">Solicitado por:</strong><span>' + ((solicitadoPor || '').toUpperCase()) + '</span><strong style="color:#475569;white-space:nowrap">Fecha Entrega:</strong><span>' + (_ocFmtFechaInput(fechaEntrega) || '') + '</span></div>';
    var tb = ' style="border-bottom:1px solid #E2E8F0"';
    var tn = ' style="border-bottom:none"';
    filas += '<tr><td colspan="4" style="border-top:2px solid #94A3B8;border-bottom:1px solid #E2E8F0"></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:600;color:#475569;border-top:2px solid #94A3B8;border-bottom:1px solid #E2E8F0">Subtotal</td><td style="border-top:2px solid #94A3B8;border-bottom:1px solid #E2E8F0"></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:600;color:#334155;border-top:2px solid #94A3B8;border-bottom:1px solid #E2E8F0">' + total.toFixed(2) + '</td></tr>';
    if (descuentoLineas > 0) {
        filas += '<tr><td colspan="4"' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:500;color:#c2410c;border-bottom:1px solid #E2E8F0">Descuento por línea</td><td' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:600;color:#c2410c;border-bottom:1px solid #E2E8F0">-' + descuentoLineas.toFixed(2) + '</td></tr>';
    }
    if (descGlobalMonto > 0) {
        var gLabel = descGlobalTipo === '%' ? 'Descuento global (' + descGlobalVal.toFixed(2) + '%)' : 'Descuento global';
        filas += '<tr><td colspan="4"' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:500;color:#c2410c;border-bottom:1px solid #E2E8F0">' + gLabel + '</td><td' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:600;color:#c2410c;border-bottom:1px solid #E2E8F0">-' + descGlobalMonto.toFixed(2) + '</td></tr>';
    }
    filas += '<tr><td colspan="4"' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:500;color:#475569;border-bottom:1px solid #E2E8F0">IGV</td><td' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:600;color:#334155;border-bottom:1px solid #E2E8F0">' + igvCalc.toFixed(2) + '</td></tr>' +
        '<tr><td colspan="4"' + tn + '></td><td style="text-align:right;padding:6px 8px;font-size:0.78rem;font-weight:700;color:#1A4480;border-bottom:none">TOTAL</td><td' + tn + '></td><td style="text-align:right;padding:6px 8px;font-size:0.78rem;font-weight:700;color:#1A4480;border-bottom:none">' + totalFinal.toFixed(2) + '</td></tr>';
    var tablaHtml = '<div style="border-radius:8px;overflow:hidden"><table class="oc-det-tbl"><thead><tr style="clip-path:inset(0 round 6px 6px 0 0)"><th>Codigo</th><th>Articulo</th><th>Und</th><th style="text-align:right">Cantidad</th><th style="text-align:right">Precio</th><th style="text-align:right">Desc %</th><th style="text-align:right">Total</th></tr></thead><tbody>' + filas + '</tbody></table></div>';
    this._imprimirSrcdoc(tituloHtml + infoHtml + tablaHtml + '<div class="prov-print-total">Total items: ' + this.detalleItems.length + '</div>', 'OC ' + ocDisplay);
};

OrdenesCompra._ocLoadExceljs = function(cb) {
    if (typeof ExcelJS !== 'undefined') return cb();
    var s = document.createElement('script');
    s.src = 'https://cdn.jsdelivr.net/npm/exceljs@4.4.0/dist/exceljs.min.js';
    s.onload = cb;
    s.onerror = function() { Mensaje.error({ titulo: 'Excel', texto: 'Error al cargar la librería de Excel' }); };
    document.head.appendChild(s);
};

OrdenesCompra._ocFmtFechaInput = function(v) { if (!v) return ''; var p = v.split('-'); return p.length === 3 ? p[2] + '/' + p[1] + '/' + p[0] : v; };

OrdenesCompra._ocStyleTitle = { font: { bold: true, size: 14, color: { argb: 'FF1A4480' } } };
OrdenesCompra._ocStyleEmpresa = { font: { bold: true, size: 11, color: { argb: 'FF1A4480' } } };
OrdenesCompra._ocStyleLabel = { font: { bold: true, size: 10, color: { argb: 'FF475569' } } };
OrdenesCompra._ocStyleValue = { font: { size: 10 }, alignment: { horizontal: 'left' } };
OrdenesCompra._ocStyleHeader = { font: { bold: true, size: 10, color: { argb: 'FFFFFFFF' } }, fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF1A4480' } }, alignment: { horizontal: 'center', vertical: 'middle' }, border: { top: { style: 'thin' }, bottom: { style: 'thin' }, left: { style: 'thin' }, right: { style: 'thin' } } };
OrdenesCompra._ocStyleCell = { font: { size: 10 }, border: { top: { style: 'thin', color: { argb: 'FFE2E8F0' } }, bottom: { style: 'thin', color: { argb: 'FFE2E8F0' } } } };
OrdenesCompra._ocStyleNum = { font: { size: 10 }, numFmt: '#,##0.000', alignment: { horizontal: 'right' }, border: { top: { style: 'thin', color: { argb: 'FFE2E8F0' } }, bottom: { style: 'thin', color: { argb: 'FFE2E8F0' } } } };
OrdenesCompra._ocStyleNum2 = { font: { size: 10 }, numFmt: '#,##0.00', alignment: { horizontal: 'right' }, border: { top: { style: 'thin', color: { argb: 'FFE2E8F0' } }, bottom: { style: 'thin', color: { argb: 'FFE2E8F0' } } } };
OrdenesCompra._ocStyleDescLabel = { font: { bold: true, size: 10, color: { argb: 'FFC2410C' } }, alignment: { horizontal: 'right' } };
OrdenesCompra._ocStyleDescVal = { font: { bold: true, size: 10, color: { argb: 'FFC2410C' } }, numFmt: '#,##0.00', alignment: { horizontal: 'right' }, border: { top: { style: 'thin', color: { argb: 'FFD1D5DB' } }, bottom: { style: 'thin', color: { argb: 'FFD1D5DB' } }, left: { style: 'thin', color: { argb: 'FFD1D5DB' } }, right: { style: 'thin', color: { argb: 'FFD1D5DB' } } }, fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFFFF7ED' } } };
OrdenesCompra._ocStyleTotalLabel = { font: { bold: true, size: 10, color: { argb: 'FF475569' } }, alignment: { horizontal: 'right' } };
OrdenesCompra._ocStyleTotalVal = { font: { bold: true, size: 10, color: { argb: 'FF334155' } }, numFmt: '#,##0.00', alignment: { horizontal: 'right' } };
OrdenesCompra._ocStyleGrandTotal = { font: { bold: true, size: 11, color: { argb: 'FF1A4480' } }, numFmt: '#,##0.00', alignment: { horizontal: 'right' } };

OrdenesCompra._ocBuildExcel = function(wb, ocDisplay, empresa, proveedor, pedDisplay, fecha, contacto, solicitadoPor, fechaEntrega, items, totalBruto, descLineas, descGlobalTipo, descGlobalValor, descGlobalMonto, igvCalc, totalFinal) {
    var ws = wb.addWorksheet('OC', { pageSetup: { orientation: 'landscape', fitToPage: true, fitToWidth: 1 } });
    ws.columns = [
        { width: 14 }, { width: 38 }, { width: 7 }, { width: 12 }, { width: 12 }, { width: 10 }, { width: 14 }
    ];
    var r = 1;
    ws.mergeCells(r, 1, r, 7);
    ws.getCell(r, 1).value = empresa;
    ws.getCell(r, 1).style = OrdenesCompra._ocStyleEmpresa;
    r++;
    ws.mergeCells(r, 1, r, 7);
    ws.getCell(r, 1).value = 'ORDEN DE COMPRA';
    ws.getCell(r, 1).style = OrdenesCompra._ocStyleTitle;
    r += 2;

    function addInfoRow(label, val) {
        ws.getCell(r, 1).value = label;
        ws.getCell(r, 1).style = OrdenesCompra._ocStyleLabel;
        ws.getCell(r, 2).value = val || '';
        ws.getCell(r, 2).style = OrdenesCompra._ocStyleValue;
        r++;
    }
    addInfoRow('N°:', ocDisplay);
    if (pedDisplay) addInfoRow('Pedido:', pedDisplay);
    addInfoRow('Proveedor:', proveedor);
    addInfoRow('Fecha:', fecha);
    addInfoRow('Contacto:', (contacto || '').toUpperCase());
    addInfoRow('Solicitado por:', (solicitadoPor || '').toUpperCase());
    addInfoRow('Fecha Entrega:', fechaEntrega || '');
    r++;

    var headers = ['CÓDIGO', 'ARTÍCULO', 'UND', 'CANTIDAD', 'PRECIO', 'DESC %', 'TOTAL'];
    headers.forEach(function(h, ci) {
        ws.getCell(r, ci + 1).value = h;
        ws.getCell(r, ci + 1).style = OrdenesCompra._ocStyleHeader;
    });
    ws.getRow(r).height = 22;
    r++;

    items.forEach(function(item) {
        ws.getCell(r, 1).value = item.cod;
        ws.getCell(r, 1).style = OrdenesCompra._ocStyleCell;
        ws.getCell(r, 2).value = item.nombre;
        ws.getCell(r, 2).style = OrdenesCompra._ocStyleCell;
        ws.getCell(r, 3).value = item.unidad;
        ws.getCell(r, 3).style = OrdenesCompra._ocStyleCell;
        ws.getCell(r, 3).alignment = { horizontal: 'center' };
        ws.getCell(r, 4).value = item.cantidad;
        ws.getCell(r, 4).style = OrdenesCompra._ocStyleNum;
        ws.getCell(r, 5).value = item.precio;
        ws.getCell(r, 5).style = OrdenesCompra._ocStyleNum;
        ws.getCell(r, 6).value = item.descPct > 0 ? item.descPct.toFixed(2) + '%' : '';
        ws.getCell(r, 6).style = { font: { size: 10 }, alignment: { horizontal: 'right' }, border: { top: { style: 'thin', color: { argb: 'FFE2E8F0' } }, bottom: { style: 'thin', color: { argb: 'FFE2E8F0' } } } };
        ws.getCell(r, 7).value = item.total;
        ws.getCell(r, 7).style = OrdenesCompra._ocStyleNum2;
        r++;
    });
    r++;

    function addTotRow(label, val, labelS, valS) {
        ws.mergeCells(r, 1, r, 5);
        ws.getCell(r, 6).value = label;
        ws.getCell(r, 6).style = labelS;
        ws.getCell(r, 7).value = val;
        ws.getCell(r, 7).style = valS;
        r++;
    }
    addTotRow('Subtotal', totalBruto, OrdenesCompra._ocStyleTotalLabel, OrdenesCompra._ocStyleTotalVal);
    if (descLineas > 0) addTotRow('Descuento por línea', -descLineas, OrdenesCompra._ocStyleDescLabel, OrdenesCompra._ocStyleDescVal);
    if (descGlobalMonto > 0) {
        var gLabel = descGlobalTipo === '%' ? 'Descuento global (' + descGlobalValor.toFixed(2) + '%)' : 'Descuento global';
        addTotRow(gLabel, -descGlobalMonto, OrdenesCompra._ocStyleDescLabel, OrdenesCompra._ocStyleDescVal);
    }
    addTotRow('IGV', igvCalc, OrdenesCompra._ocStyleTotalLabel, OrdenesCompra._ocStyleTotalVal);
    addTotRow('TOTAL', totalFinal, OrdenesCompra._ocStyleGrandTotal, OrdenesCompra._ocStyleGrandTotal);

    r += 2;
    ws.mergeCells(r, 1, r, 7);
    ws.getCell(r, 1).value = 'NexusERP';
    ws.getCell(r, 1).style = { font: { size: 8, color: { argb: 'FF94A3B8' } }, alignment: { horizontal: 'center' } };
};

OrdenesCompra.exportarExcelDetalle = function() {
    var self = this;
    if (!this.detalleItems || this.detalleItems.length === 0) {
        Mensaje.error({ titulo: 'Excel', texto: 'No hay items en el detalle para exportar' }); return;
    }
    this._ocLoadExceljs(function() { self._ocGenerarExcelDetalle(); });
};

OrdenesCompra._ocGenerarExcelDetalle = function() {
    var ocEj = document.getElementById('ocFormEjercicio')?.value || '';
    var numOc = document.getElementById('ocFormNum')?.value || '';
    var proveedor = document.getElementById('ocFormProveedor')?.value || '';
    var fecha = document.getElementById('ocFormFecha')?.value || '';
    var contacto = document.getElementById('ocFormContacto')?.value || '';
    var solicitadoPor = document.getElementById('ocFormSolicitadoPor')?.value || '';
    var fechaEntrega = document.getElementById('ocFormFechaEntrega')?.value || '';
    var numPedRef = document.getElementById('ocFormNumPedRef')?.value || '';
    var empresa = this.sesion?.empresa_razon || '';

    var totalBruto = 0, descuentoLineas = 0;
    var items = [];
    this.detalleItems.forEach(function(item) {
        var itemTotal = parseFloat(item.total) || 0;
        var itemDescPct = parseFloat(item.descuento_pct) || 0;
        var itemDescMonto = itemTotal * itemDescPct / 100;
        descuentoLineas += itemDescMonto;
        totalBruto += itemTotal;
        items.push({ cod: item.cod_articulo, nombre: item.nombre, unidad: item.cod_unidad, cantidad: parseFloat(item.cantidad) || 0, precio: parseFloat(item.precio) || 0, descPct: itemDescPct, total: itemTotal });
    });

    var subtotalNeto = totalBruto - descuentoLineas;
    var descGlobalTipo = OrdenesCompra.descuentoGlobalTipo || '%';
    var descGlobalVal = parseFloat(document.getElementById('ocFormDescGlobal')?.value) || 0;
    var descGlobalMonto = descGlobalTipo === '%' ? subtotalNeto * descGlobalVal / 100 : descGlobalVal;
    subtotalNeto -= descGlobalMonto;
    var igvCalc = subtotalNeto * (parseFloat(OrdenesCompra.porcentajeIgv) || 18) / 100;
    var totalFinal = subtotalNeto + igvCalc;
    var ocDisplay = ocEj ? ocEj + '-' + numOc : (numOc || '');
    var pedDisplay = numPedRef ? (ocEj ? ocEj + '-' + numPedRef : numPedRef) : '';

    var wb = new ExcelJS.Workbook();
    this._ocBuildExcel(wb, ocDisplay, empresa, proveedor, pedDisplay, this._ocFmtFechaInput(fecha), contacto, solicitadoPor, this._ocFmtFechaInput(fechaEntrega), items, totalBruto, descuentoLineas, descGlobalTipo, descGlobalVal, descGlobalMonto, igvCalc, totalFinal);
    wb.xlsx.writeBuffer().then(function(buf) {
        var blob = new Blob([buf], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
        var a = document.createElement('a');
        a.href = URL.createObjectURL(blob);
        a.download = 'OC_' + ocDisplay.replace(/[^a-zA-Z0-9-]/g, '_') + '.xlsx';
        a.click();
    });
};

OrdenesCompra.exportarExcelVer = function(numOc, ejercicio) {
    var self = this;
    this._ocLoadExceljs(function() {
        fetch(OrdenesCompra.API_URL + '/ordenes-compra/' + numOc + '?id_empresa=' + (OrdenesCompra.sesion ? OrdenesCompra.sesion.id_empresa : '') + '&ejercicio=' + ejercicio)
            .then(function(r) { return r.json(); })
            .then(function(data) {
                if (!data.ok) { Mensaje.error({ titulo: 'Excel', texto: 'Error al obtener datos' }); return; }
                self._ocGenerarExcelVer(data.data);
            }).catch(function() { Mensaje.error({ titulo: 'Excel', texto: 'Error al obtener datos' }); });
    });
};

OrdenesCompra._ocGenerarExcelVer = function(row) {
    var empresa = this.sesion?.empresa_razon || '';
    var ocDisplay = row.ejercicio ? row.ejercicio + '-' + row.num_oc : row.num_oc;
    var pedDisplay = row.ped_ejercicio ? row.ped_ejercicio + '-' + (row.num_ped || '') : (row.num_ped || '');
    var fecha = row.fecha_oc ? row.fecha_oc.split('T')[0].split('-').reverse().join('/') : '-';
    var fechaEntrega = row.fecha_entrega ? row.fecha_entrega.split('T')[0].split('-').reverse().join('/') : '-';

    var totalBruto = 0, descuentoLineas = 0;
    var items = [];
    (row.detalle || []).forEach(function(d) {
        var itemTotal = parseFloat(d.total) || 0;
        var itemDesc = parseFloat(d.descuento) || 0;
        descuentoLineas += itemDesc;
        totalBruto += itemTotal;
        var descPct = itemTotal > 0 ? (itemDesc / itemTotal * 100) : 0;
        items.push({ cod: d.cod_articulo, nombre: d.nombre, unidad: d.cod_unidad, cantidad: parseFloat(d.cantidad) || 0, precio: parseFloat(d.precio) || 0, descPct: descPct, total: itemTotal });
    });

    var subtotalNeto = totalBruto - descuentoLineas;
    var descGlobalTipo = row.descuento_tipo || '%';
    var descGlobalValor = parseFloat(row.descuento_valor) || 0;
    var igvRate2 = (parseFloat(row.porcentaje_igv) || 18) / 100;
    var netoBeforeIgv2 = (parseFloat(row.total) || 0) / (1 + igvRate2);
    var descGlobalMonto = (parseFloat(row.subtotal) || 0) - descuentoLineas - netoBeforeIgv2;
    if (descGlobalMonto < 0) descGlobalMonto = 0;
    subtotalNeto -= descGlobalMonto;
    var igvCalc = subtotalNeto * (parseFloat(row.porcentaje_igv) || 18) / 100;
    var totalFinal = subtotalNeto + igvCalc;

    var wb = new ExcelJS.Workbook();
    this._ocBuildExcel(wb, ocDisplay, empresa, row.proveedor_razon_social || '', pedDisplay, fecha, row.contacto || '', row.solicitado_por || '', fechaEntrega, items, totalBruto, descuentoLineas, descGlobalTipo, descGlobalValor, descGlobalMonto, igvCalc, totalFinal);
    wb.xlsx.writeBuffer().then(function(buf) {
        var blob = new Blob([buf], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
        var a = document.createElement('a');
        a.href = URL.createObjectURL(blob);
        a.download = 'OC_' + ocDisplay.replace(/[^a-zA-Z0-9-]/g, '_') + '.xlsx';
        a.click();
    });
};

OrdenesCompra.imprimirDetalleVer = function(numOc, ejercicio) {
    var self = this;
    var empresa = this.sesion?.empresa_razon || '';
    var params = '?id_empresa=' + (self.sesion ? self.sesion.id_empresa : '') + '&ejercicio=' + (ejercicio || new Date().getFullYear());
    fetch(self.API_URL + self.endpoint + '/' + numOc + params)
        .then(function(r) { return r.json(); })
        .then(function(res) {
            if (!res.ok || !res.data) return;
            var row = res.data;
            var estados = { P: 'Pendiente', A: 'Aprobado', C: 'Cerrado', N: 'Anulado' };
            var ahora = new Date();
            var fechaHora = ahora.toLocaleDateString('es-PE', { day: '2-digit', month: '2-digit', year: 'numeric' }) + ' ' + ahora.toLocaleTimeString('es-PE', { hour: '2-digit', minute: '2-digit' });
            var filas = '';
            var descFromDetail = 0;
            if (row.detalle) {
                row.detalle.forEach(function(d) {
                    var dTotal = parseFloat(d.total) || 0;
                    var dDesc = parseFloat(d.descuento) || 0;
                    var dDescPct = dTotal > 0 && dDesc > 0 ? (dDesc * 100 / dTotal) : 0;
                    descFromDetail += dDesc;
                    filas += '<tr><td>' + (d.cod_articulo || '') + '</td><td>' + (d.nombre || '') + '</td><td>' + (d.cod_unidad || '') + '</td><td style="text-align:right">' + (parseFloat(d.cantidad) || 0).toFixed(3) + '</td><td style="text-align:right">' + (parseFloat(d.precio) || 0).toFixed(3) + '</td><td style="text-align:right">' + (dDescPct > 0 ? dDescPct.toFixed(2) + '%' : '') + '</td><td style="text-align:right">' + dTotal.toFixed(2) + '</td></tr>';
                });
            }
            var ph = self._fechaHoraStr();
            var tituloHtml = '<div class="prov-print-header"><div><div class="prov-print-titulo">Orden de Compra</div>' + (empresa ? '<div style="font-size:0.8rem;color:#1A4480;font-weight:600;margin-top:4px">' + empresa + '</div>' : '') + '</div><div class="prov-print-fecha">' + ph + '</div></div>';
            var numOcDisplay = (row.ejercicio || '') ? (row.ejercicio + '-' + row.num_oc) : (row.num_oc || '');
            var pedDisplay = (row.ped_ejercicio ? row.ped_ejercicio + '-' : '') + (row.num_ped || '');
            function _ocFmtFecha(iso) { if (!iso) return ''; var p = iso.split('T')[0].split('-'); return p[2] + '/' + p[1] + '/' + p[0]; }
            var infoHtml = '<div style="margin:12px 0;font-size:0.72rem;display:grid;grid-template-columns:auto 1fr;gap:2px 12px;align-items:start"><strong style="color:#475569;white-space:nowrap">N\u00B0:</strong><span>' + numOcDisplay + '</span><strong style="color:#475569;white-space:nowrap">Proveedor:</strong><span>' + (row.proveedor_razon_social || '') + '</span><strong style="color:#475569;white-space:nowrap">Pedido Origen:</strong><span>' + pedDisplay + '</span><strong style="color:#475569;white-space:nowrap">Fecha:</strong><span>' + _ocFmtFecha(row.fecha_oc) + '</span><strong style="color:#475569;white-space:nowrap">Fecha Entrega:</strong><span>' + (_ocFmtFecha(row.fecha_entrega) || '') + '</span><strong style="color:#475569;white-space:nowrap">Tipo:</strong><span>' + (row.tipo === 'M' ? 'Materiales' : 'Gastos') + '</span><strong style="color:#475569;white-space:nowrap">Moneda:</strong><span>' + (row.moneda === 'ME' ? 'Dolares' : 'Soles') + '</span><strong style="color:#475569;white-space:nowrap">Contacto:</strong><span>' + ((row.contacto || '').toUpperCase()) + '</span><strong style="color:#475569;white-space:nowrap">Solicitado por:</strong><span>' + ((row.solicitado_por || '').toUpperCase()) + '</span><strong style="color:#475569;white-space:nowrap">Estado:</strong><span>' + (estados[row.estado] || row.estado) + '</span><strong style="color:#475569;white-space:nowrap">Obs:</strong><span>' + (row.observaciones || '') + '</span></div>';
    var tb = ' style="border-bottom:1px solid #E2E8F0"';
            var tn = ' style="border-bottom:none"';
            filas += '<tr><td colspan="4" style="border-top:2px solid #94A3B8;border-bottom:1px solid #E2E8F0"></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:600;color:#475569;border-top:2px solid #94A3B8;border-bottom:1px solid #E2E8F0">Subtotal</td><td style="border-top:2px solid #94A3B8;border-bottom:1px solid #E2E8F0"></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:600;color:#334155;border-top:2px solid #94A3B8;border-bottom:1px solid #E2E8F0">' + (parseFloat(row.subtotal) || 0).toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '</td></tr>';
            if (descFromDetail > 0) {
                filas += '<tr><td colspan="4"' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:500;color:#c2410c;border-bottom:1px solid #E2E8F0">Descuento por línea</td><td' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:600;color:#c2410c;border-bottom:1px solid #E2E8F0">-' + descFromDetail.toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '</td></tr>';
            }
            var igvRate3 = (parseFloat(row.porcentaje_igv) || 18) / 100;
            var netoBeforeIgv3 = (parseFloat(row.total) || 0) / (1 + igvRate3);
            var descGM = (parseFloat(row.subtotal) || 0) - descFromDetail - netoBeforeIgv3;
            if (descGM < 0) descGM = 0;
            if (descGM > 0.01) {
                var dgTipo = row.descuento_tipo || '%';
                var dgValor = parseFloat(row.descuento_valor) || 0;
                var dgLabel = dgTipo === '%' ? 'Descuento global (' + dgValor.toFixed(2) + '%)' : 'Descuento global';
                filas += '<tr><td colspan="4"' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:500;color:#c2410c;border-bottom:1px solid #E2E8F0">' + dgLabel + '</td><td' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:600;color:#c2410c;border-bottom:1px solid #E2E8F0">-' + descGM.toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '</td></tr>';
            }
            filas += '<tr><td colspan="4"' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:500;color:#475569;border-bottom:1px solid #E2E8F0">IGV</td><td' + tb + '></td><td style="text-align:right;padding:4px 8px;font-size:0.72rem;font-weight:600;color:#334155;border-bottom:1px solid #E2E8F0">' + (parseFloat(row.igv) || 0).toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '</td></tr>' +
                '<tr><td colspan="4"' + tn + '></td><td style="text-align:right;padding:6px 8px;font-size:0.78rem;font-weight:700;color:#1A4480;border-bottom:none">TOTAL</td><td' + tn + '></td><td style="text-align:right;padding:6px 8px;font-size:0.78rem;font-weight:700;color:#1A4480;border-bottom:none">' + (parseFloat(row.total) || 0).toLocaleString('es-PE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + '</td></tr>';
            var tablaHtml = '<div style="border-radius:8px;overflow:hidden"><table class="oc-det-tbl"><thead><tr style="clip-path:inset(0 round 6px 6px 0 0)"><th>Codigo</th><th>Articulo</th><th>Und</th><th style="text-align:right">Cantidad</th><th style="text-align:right">Precio</th><th style="text-align:right">Desc %</th><th style="text-align:right">Total</th></tr></thead><tbody>' + filas + '</tbody></table></div>';
            self._imprimirSrcdoc(tituloHtml + infoHtml + tablaHtml + '<div class="prov-print-total">Total items: ' + (row.detalle ? row.detalle.length : 0) + '</div>', 'OC ' + numOc);
        })
        .catch(function() { Mensaje.error({ titulo: 'Error', texto: 'Error al obtener datos para imprimir' }); });
};
