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

KardexArticulo._fmtMiles = function(val, dec) {
    dec = dec !== undefined ? dec : 2;
    var num = parseFloat(val) || 0;
    return num.toLocaleString('es-PE', { minimumFractionDigits: dec, maximumFractionDigits: dec });
};

KardexArticulo._fmtDate = function(dateStr) {
    if (!dateStr) return '';
    var d = dateStr.split('T')[0].split('-');
    if (d.length !== 3) return dateStr;
    return d[2] + '/' + d[1] + '/' + d[0];
};

KardexArticulo._articuloInfo = null;

var _kaMostrarVista = KardexArticulo.mostrarVista;
KardexArticulo.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);
    };
    _kaMostrarVista.call(this);
    this.cargarTabla = _origCargar;

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

    if (!wrap.querySelector('table')) {
        wrap.innerHTML = '<table class="prov-tabla"><thead></thead><tbody></tbody></table>';
    }

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

    var toolbar = document.querySelector('#' + self.elementId + ' .prov-toolbar');
    if (toolbar) {
        var bar = document.createElement('div');
        bar.id = 'kaExtraBar';
        bar.style.cssText = 'display:flex;align-items:center;gap:12px;padding:8px 20px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:0.82rem;flex-wrap:wrap';

        var now = new Date();
        var firstDay = new Date(now.getFullYear(), now.getMonth(), 1).toISOString().slice(0, 10);
        var lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0).toISOString().slice(0, 10);

        bar.innerHTML =
            '<div style="display:flex;align-items:center;gap:4px;font-weight:600;color:#475569;font-size:0.78rem">Artículo:' +
            '<div style="position:relative;min-width:350px">' +
            '<input id="kaArticulo" autocomplete="off" placeholder="Buscar..." style="width:100%;padding:8px 12px;border:1px solid #cbd5e1;border-radius:4px;font-size:0.85rem;box-sizing:border-box">' +
            '<input id="kaArticuloId" type="hidden" value="">' +
            '<div id="kaArticuloDropdown" style="position:absolute;top:100%;left:0;right:0;background:#fff;border:1px solid #cbd5e1;border-radius:4px;max-height:350px;overflow-y:auto;display:none;z-index:1000;box-shadow:0 4px 8px rgba(0,0,0,0.1)"></div>' +
            '</div></div>' +
            '<label style="display:flex;align-items:center;gap:4px;font-weight:600;color:#475569;font-size:0.78rem">' +
            'Desde: <input type="date" id="kaFechaDesde" value="' + firstDay + '" style="padding:4px 8px;border:1px solid #cbd5e1;border-radius:4px;font-size:0.78rem"></label>' +
            '<label style="display:flex;align-items:center;gap:4px;font-weight:600;color:#475569;font-size:0.78rem">' +
            'Hasta: <input type="date" id="kaFechaHasta" value="' + lastDay + '" style="padding:4px 8px;border:1px solid #cbd5e1;border-radius:4px;font-size:0.78rem"></label>';
        toolbar.parentNode.insertBefore(bar, toolbar.nextSibling);

        self._cargarArticulos();

        document.getElementById('kaFechaDesde').addEventListener('change', function() {
            self.cargarKardex();
        });
        document.getElementById('kaFechaHasta').addEventListener('change', function() {
            self.cargarKardex();
        });
    }

    self.cargarKardex();
};

KardexArticulo.cargarTabla = function() {
    var self = this;
    if (!self._fullData) return self.cargarKardex() || Promise.resolve();
    var buscarVal = document.getElementById(self.elementId + 'Buscar');
    var term = (buscarVal ? buscarVal.value : '').toLowerCase().trim();
    if (term === '') {
        self._renderKardex(self._fullData);
    } else {
        var filtered = self._fullData.filter(function(m) {
            return (m.documento && m.documento.toLowerCase().indexOf(term) !== -1) ||
                   (m.fecha_movimiento && m.fecha_movimiento.indexOf(term) !== -1) ||
                   (String(m.ent_cant || '').indexOf(term) !== -1) ||
                   (String(m.sal_cant || '').indexOf(term) !== -1) ||
                   (String(m.saldo_cant || '').indexOf(term) !== -1) ||
                   (String(m.ent_total || '').indexOf(term) !== -1) ||
                   (String(m.sal_total || '').indexOf(term) !== -1) ||
                   (String(m.saldo_total || '').indexOf(term) !== -1) ||
                   (m.num_ocs && m.num_ocs.toLowerCase().indexOf(term) !== -1);
        });
        self._renderKardex(filtered);
    }
    return Promise.resolve();
};

KardexArticulo._cargarArticulos = function() {
    var self = this;
    self.ensureSesion();
    if (!self.sesion || !self.sesion.id_empresa) return;
    var url = self.API_URL + '/kardex-articulo/articulos?id_empresa=' + self.sesion.id_empresa;
    if (self.sesion && self.sesion.id_sucursal) url += '&id_sucursal=' + self.sesion.id_sucursal;
    fetch(url)
        .then(function(r) { return r.json(); })
        .then(function(res) {
            if (res.ok && res.data) {
                var input = document.getElementById('kaArticulo');
                var hidden = document.getElementById('kaArticuloId');
                var dropdown = document.getElementById('kaArticuloDropdown');
                if (!input || !hidden || !dropdown) return;
                var articles = res.data.map(function(a) {
                    return { id: a.id_articulo, text: a.cod_articulo + ' - ' + a.nom_art, cod: a.cod_articulo, nom: a.nom_art };
                });
                function filtrar() {
                    var term = input.value.toLowerCase().trim();
                    if (term === '') { dropdown.style.display = 'none'; return; }
                    var filt = articles.filter(function(a) {
                        return a.text.toLowerCase().indexOf(term) !== -1;
                    });
                    if (filt.length === 0) { dropdown.style.display = 'none'; return; }
                    dropdown.innerHTML = filt.map(function(a) {
                        return '<div data-id="' + a.id + '" style="padding:5px 12px;cursor:pointer;font-size:0.85rem;border-bottom:1px solid #f1f5f9">' + a.text + '</div>';
                    }).join('');
                    dropdown.style.display = 'block';
                }
                input.addEventListener('input', filtrar);
                input.addEventListener('focus', function() {
                    if (this.value.trim()) filtrar();
                });
                input.addEventListener('blur', function() {
                    setTimeout(function() { dropdown.style.display = 'none'; }, 200);
                });
                dropdown.addEventListener('click', function(e) {
                    var item = e.target.closest('[data-id]');
                    if (!item) return;
                    hidden.value = item.dataset.id;
                    input.value = item.textContent;
                    dropdown.style.display = 'none';
                    self.cargarKardex();
                });
                document.addEventListener('click', function(e) {
                    if (!e.target.closest('#kaArticulo, #kaArticuloDropdown')) {
                        dropdown.style.display = 'none';
                    }
                });
            }
        }).catch(function() {});
};

KardexArticulo.cargarKardex = function() {
    var self = this;
    var artEl = document.getElementById('kaArticuloId');
    var desdeEl = document.getElementById('kaFechaDesde');
    var hastaEl = document.getElementById('kaFechaHasta');
    var idArticulo = artEl ? artEl.value : '';

    if (!idArticulo) {
        self._fullData = null;
        self._limpiarTabla();
        return;
    }

    self.ensureSesion();
    if (!self.sesion || !self.sesion.id_empresa) return;

    var url = self.API_URL + '/kardex-articulo?id_empresa=' + self.sesion.id_empresa + '&id_articulo=' + idArticulo;
    if (desdeEl && desdeEl.value) url += '&fecha_desde=' + desdeEl.value;
    if (hastaEl && hastaEl.value) url += '&fecha_hasta=' + hastaEl.value;
    if (self.sesion && self.sesion.id_sucursal) url += '&id_sucursal=' + self.sesion.id_sucursal;

    fetch(url)
        .then(function(r) { return r.json(); })
        .then(function(res) {
            if (!res.ok) return;
            KardexArticulo._articuloInfo = res.articulo;
            self._fullData = res.data || [];
            self._renderKardex(self._fullData);
        }).catch(function() {});
};

KardexArticulo._limpiarTabla = function() {
    var self = this;
    var wrap = document.getElementById(self.elementId + 'TablaWrap');
    if (!wrap) return;
    var tbody = wrap.querySelector('table tbody');
    if (tbody) tbody.innerHTML = '';
    var infoBar = document.getElementById('kaArticuloInfo');
    if (infoBar) infoBar.remove();
};

KardexArticulo._renderKardex = function(datos) {
    var self = this;
    var wrap = document.getElementById(self.elementId + 'TablaWrap');
    if (!wrap) return;

    var tbody = wrap.querySelector('table tbody');
    if (!tbody) return;

    var thead = wrap.querySelector('table thead');
    if (thead) {
        thead.innerHTML = '<tr><th style="width:7%;border-radius:6px 0 0 0">Fecha</th><th style="width:10%">Documento</th><th class="center" style="width:5%">Tipo</th><th class="right" style="width:8%">Ent. Cant.</th><th class="right" style="width:10%">Ent. P.U.(S/)</th><th class="right" style="width:10%">Ent. Total(S/)</th><th class="right" style="width:8%">Sal. Cant.</th><th class="right" style="width:10%">Sal. P.U.(S/)</th><th class="right" style="width:10%">Sal. Total(S/)</th><th class="right" style="width:8%">Saldo Cant.</th><th class="right" style="width:14%;border-radius:0 6px 0 0">Saldo Total(S/)</th></tr>';
    }

    var html = '';
    self.currentData = datos;
    var tEntCant = 0, tEntTotal = 0, tSalCant = 0, tSalTotal = 0, tSaldoCant = 0, tSaldoTotal = 0;
    datos.forEach(function(m) {
        var fecha = m.fecha_movimiento ? KardexArticulo._fmtDate(m.fecha_movimiento) : '';
        var tipoLabel = m.tipo === 'E' ? 'E' : 'S';
        var tipoClass = m.tipo === 'E' ? 'tipo-e' : 'tipo-s';
        tEntCant += parseFloat(m.ent_cant) || 0;
        tEntTotal += parseFloat(m.ent_total) || 0;
        tSalCant += parseFloat(m.sal_cant) || 0;
        tSalTotal += parseFloat(m.sal_total) || 0;
        html += '<tr>';
        html += '<td>' + fecha + '</td>';
html += '<td>' + (m.documento || '') + (m.num_ocs ? '<span style="display:inline-block;padding:1px 6px;border-radius:3px;background:#059669;color:#fff;font-size:0.55rem;font-weight:700;margin-left:4px;vertical-align:middle">OC</span>' : '') + '</td>';



        html += '<td class="center"><span class="' + tipoClass + '">' + tipoLabel + '</span></td>';
        html += '<td class="right">' + (m.ent_cant > 0 ? KardexArticulo._fmtMiles(m.ent_cant) : '') + '</td>';
        html += '<td class="right">' + (m.ent_pu > 0 ? KardexArticulo._fmtMiles(m.ent_pu, 4) : '') + '</td>';
        html += '<td class="right bold">' + (m.ent_total > 0 ? KardexArticulo._fmtMiles(m.ent_total) : '') + '</td>';
        html += '<td class="right">' + (m.sal_cant > 0 ? KardexArticulo._fmtMiles(m.sal_cant) : '') + '</td>';
        html += '<td class="right">' + (m.sal_pu > 0 ? KardexArticulo._fmtMiles(m.sal_pu, 4) : '') + '</td>';
        html += '<td class="right bold">' + (m.sal_total > 0 ? KardexArticulo._fmtMiles(m.sal_total) : '') + '</td>';
        html += '<td class="right bold">' + KardexArticulo._fmtMiles(m.saldo_cant) + '</td>';
        html += '<td class="right bold">' + KardexArticulo._fmtMiles(m.saldo_total) + '</td>';
        html += '</tr>';
        tSaldoCant = parseFloat(m.saldo_cant) || 0;
        tSaldoTotal = parseFloat(m.saldo_total) || 0;
    });
    html += '<tr class="ka-total-bar">';
    html += '<td colspan="3" style="text-align:right;padding-right:8px;border-radius:0 0 0 6px">TOTALES</td>';
    html += '<td class="right">' + KardexArticulo._fmtMiles(tEntCant) + '</td><td></td>';
    html += '<td class="right">S/ ' + KardexArticulo._fmtMiles(tEntTotal) + '</td>';
    html += '<td class="right">' + KardexArticulo._fmtMiles(tSalCant) + '</td><td></td>';
    html += '<td class="right">S/ ' + KardexArticulo._fmtMiles(tSalTotal) + '</td>';
    html += '<td class="right">' + KardexArticulo._fmtMiles(tSaldoCant) + '</td>';
    html += '<td class="right" style="border-radius:0 0 6px 0">S/ ' + KardexArticulo._fmtMiles(tSaldoTotal) + '</td></tr>';
    tbody.innerHTML = html;

    self._attatchRowEvents();

    var oldLegend = document.getElementById('kaLegend');
    if (oldLegend) oldLegend.remove();

    var art = KardexArticulo._articuloInfo;
    if (art) {
        var pag = document.getElementById(self.elementId + 'Paginacion');
        if (pag) {
            var leg = document.createElement('div');
            leg.id = 'kaLegend';
            leg.style.cssText = 'margin-top:10px;padding:10px 14px;background:#F8FAFC;border:1px solid #E2E8F0;border-radius:6px;font-size:9px;color:#475569;line-height:1.6';
            var empresa = '';
            try { var s = JSON.parse(localStorage.getItem('erp_session') || sessionStorage.getItem('erp_session')); empresa = s.empresa_razon || ''; } catch(e) {}
            leg.innerHTML = 'Artículo: ' + (art.cod_articulo || '') + ' - ' + (art.nom_art || '') + ' | ' +
                'Familia: ' + (art.nom_fam || '-') + ' | ' +
                'Stock Actual: ' + KardexArticulo._fmtMiles(art.stock_actual) + ' | ' +
                'Costo Prom.: S/ ' + KardexArticulo._fmtMiles(art.costo_promedio, 4) + ' | ' +
                'Movimientos: ' + datos.length;
            pag.parentNode.insertBefore(leg, pag);
        }
    }
};

KardexArticulo._attatchRowEvents = function() {
    var self = this;
    var wrap = document.getElementById(self.elementId + 'TablaWrap');
    if (!wrap || !self.currentData || self.currentData.length === 0) return;

    var rows = wrap.querySelectorAll('table tbody tr:not(.ka-total-bar)');
    rows.forEach(function(tr, idx) {
        var rowData = self.currentData[idx];
        if (!rowData) return;

        var tds = tr.querySelectorAll('td');
        var docColIdx = 1;
        if (tds[docColIdx] && rowData.id_documento) {
            var td = tds[docColIdx];
            td.style.cursor = 'context-menu';
            td.addEventListener('contextmenu', function(e) {
                e.preventDefault();
                e.stopPropagation();
                self._mostrarMenuGuia(e, rowData);
            });
        }
    });
};

KardexArticulo._mostrarMenuGuia = function(e, row) {
    var self = this;
    var ctxId = 'kaGuiaCtxMenu';
    var ctx = document.getElementById(ctxId);
    if (!ctx) {
        ctx = document.createElement('div');
        ctx.id = ctxId;
        ctx.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:200px';
        document.body.appendChild(ctx);
        document.addEventListener('click', function() { ctx.style.display = 'none'; });
        document.addEventListener('contextmenu', function(ev) {
            if (!ctx.contains(ev.target)) ctx.style.display = 'none';
        });
    }

    var tipoLabel = row.tipo === 'E' ? 'Guía de Ingreso' : 'Guía de Salida';
    var html = '';
    html += '<div class="kv-ctx-item" 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 ' + tipoLabel + '</div>';
    html += '<div class="kv-ctx-item" 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 ' + tipoLabel + '</div>';

    ctx.innerHTML = html;
    ctx.style.left = e.clientX + 'px';
    ctx.style.top = e.clientY + 'px';
    ctx.style.display = 'block';

    requestAnimationFrame(function() {
        var r = ctx.getBoundingClientRect();
        if (r.right > window.innerWidth) ctx.style.left = Math.max(0, e.clientX - r.width) + 'px';
        if (r.bottom > window.innerHeight) ctx.style.top = Math.max(0, e.clientY - r.height) + 'px';
    });

    ctx.querySelectorAll('.kv-ctx-item').forEach(function(item) {
        item.addEventListener('mouseenter', function() { this.style.background = '#f1f5f9'; });
        item.addEventListener('mouseleave', function() { this.style.background = ''; });
        item.addEventListener('click', function(ev) {
            ev.stopPropagation();
            ctx.style.display = 'none';
            if (this.dataset.action === 'ver') {
                ConsultaGuias.verDetalle(row.id_documento);
            } else if (this.dataset.action === 'imprimir') {
                ConsultaGuias.imprimirDetalleVer(row.id_documento);
            }
        });
    });
};

KardexArticulo.obtenerParamsExtra = function() {
    return '';
};

KardexArticulo.imprimir = async function() {
    var self = this;
    var di = await TablaGenerica._obtenerDatosImpresion();
    var ahora = new Date();
    var fechaStr = ahora.toLocaleDateString('es-PE', { day: '2-digit', month: '2-digit', year: 'numeric' }) + ' ' + ahora.toLocaleTimeString('es-PE', { hour: '2-digit', minute: '2-digit' });

    var artEl = document.getElementById('kaArticuloId');
    var idArticulo = artEl ? artEl.value : '';
    if (!idArticulo) { Mensaje.error({ titulo: 'Imprimir', texto: 'Seleccione un artículo' }); return; }

    var desdeEl = document.getElementById('kaFechaDesde');
    var hastaEl = document.getElementById('kaFechaHasta');
    var filtros = [];
    var displayEl = document.getElementById('kaArticulo');
    if (displayEl && displayEl.value) filtros.push('Artículo: ' + displayEl.value);
    if (desdeEl && desdeEl.value) filtros.push('Desde: ' + desdeEl.value);
    if (hastaEl && hastaEl.value) filtros.push('Hasta: ' + hastaEl.value);

    var url = self.API_URL + '/kardex-articulo?id_empresa=' + self.sesion.id_empresa + '&id_articulo=' + idArticulo;
    if (desdeEl && desdeEl.value) url += '&fecha_desde=' + desdeEl.value;
    if (hastaEl && hastaEl.value) url += '&fecha_hasta=' + hastaEl.value;
    if (self.sesion && self.sesion.id_sucursal) url += '&id_sucursal=' + self.sesion.id_sucursal;

    var r = await fetch(url);
    var res = await r.json();
            if (!res.ok || !res.data || res.data.length === 0) { Mensaje.error({ titulo: 'Imprimir', texto: 'No hay datos' }); return; }
            var datos = res.data;
            var art = res.articulo || {};

            var html = '<!DOCTYPE html><html><head><meta charset="UTF-8"><style>';
            html += '*{margin:0;padding:0;border:0;outline:none}';
            html += 'body{font-family:Arial,sans-serif;font-size:11px;margin:20px;color:#1E293B}';
            html += 'table{width:100%;border-collapse:collapse;font-size:10px}';
            html += 'th{background:#1A4480;color:#fff;padding:8px 10px;text-align:left;font-weight:700;text-transform:uppercase;font-size:9px;border:0;white-space:nowrap}';
            html += 'td{padding:6px 10px;border:0;border-bottom:1px solid #E2E8F0;color:#334155}';
            html += '.right{text-align:right}.bold{font-weight:700}';
            html += '.total-bar{background:#1A4480;color:#fff;font-weight:700}';
            html += '.total-bar td{padding:8px 10px;border:0;color:#fff;font-weight:700;border-bottom:0}';
            html += '.total-bar td:first-child{border-radius:0 0 0 6px}';
            html += '.total-bar td:last-child{border-radius:0 0 6px 0}';
            html += '.legend{margin-top:10px;padding:10px 14px;background:#F8FAFC;border:1px solid #E2E8F0;border-radius:6px;font-size:9px;color:#475569;line-height:1.6}';
            html += '@page{margin:10mm}';
            html += '</style></head><body>';
            html += '<div style="border-radius:8px;overflow:hidden">';
            html += '<table>';
            html += '<thead>';
html += '<tr><th colspan="9" style="text-align:left;padding:0 0 10px 10px;border:0;background:none;color:#1E293B;font-size:14px;text-transform:uppercase"><div style="padding:0 0 10px 0">' + di.logoHtml + '<span style="display:inline-block;vertical-align:middle"><span style="font-weight:800;color:#1A4480">Kardex por Artículo</span>' + (di.empresa ? '<br><span style="font-size:0.8rem;color:#1A4480;font-weight:600">' + di.empresa + '</span>' : '') + (di.sucursal ? '<br><span style="font-size:0.7rem;color:#64748B;font-weight:400">' + di.sucursal + '</span>' : '') + '</span></div></th><th style="text-align:right;padding:0 10px 10px 0;border:0;background:none;color:#1E293B;font-size:0.65rem;text-transform:none;font-weight:400;width:10%">' + fechaStr + '</th></tr>';
if (filtros.length > 0) html += '<tr><th colspan="10" style="text-align:left;padding:4px 10px;border:0;background:none;font-size:9px;color:#475569">' + filtros.join(' | ') + '</th></tr>';
            html += '<tr><th rowspan="2" style="width:8%;border-radius:6px 0 0 0;padding-left:6px">Fecha</th><th rowspan="2" style="width:12%">Documento</th><th colspan="3" style="text-align:center;border-bottom:1px solid rgba(255,255,255,0.3)">ENTRADAS</th><th colspan="3" style="text-align:center;border-bottom:1px solid rgba(255,255,255,0.3)">SALIDAS</th><th colspan="2" style="text-align:center;border-bottom:1px solid rgba(255,255,255,0.3);border-radius:0 6px 0 0">SALDO</th></tr>';
            html += '<tr><th class="right" style="width:9%">Cant.</th><th class="right" style="width:9%">P.U.(S/)</th><th class="right" style="width:10%">Total(S/)</th><th class="right" style="width:9%">Cant.</th><th class="right" style="width:9%">P.U.(S/)</th><th class="right" style="width:10%">Total(S/)</th><th class="right" style="width:9%">Cant.</th><th class="right" style="width:10%">Total(S/)</th></tr>';
            html += '</thead><tbody>';

            var tEntCant = 0, tEntTotal = 0, tSalCant = 0, tSalTotal = 0, tSaldoCant = 0, tSaldoTotal = 0;
            datos.forEach(function(m) {
                tEntCant += parseFloat(m.ent_cant) || 0;
                tEntTotal += parseFloat(m.ent_total) || 0;
                tSalCant += parseFloat(m.sal_cant) || 0;
                tSalTotal += parseFloat(m.sal_total) || 0;
                var fecha = m.fecha_movimiento ? KardexArticulo._fmtDate(m.fecha_movimiento) : '';
                html += '<tr><td>' + fecha + '</td><td>' + (m.documento || '') + (m.num_ocs ? '<span style="display:inline-block;padding:1px 6px;border-radius:3px;background:#059669;color:#fff;font-size:0.55rem;font-weight:700;margin-left:4px;vertical-align:middle">OC</span>' : '') + '</td>';
                html += '<td class="right">' + (m.ent_cant > 0 ? KardexArticulo._fmtMiles(m.ent_cant) : '') + '</td>';
                html += '<td class="right">' + (m.ent_pu > 0 ? KardexArticulo._fmtMiles(m.ent_pu, 4) : '') + '</td>';
                html += '<td class="right bold">' + (m.ent_total > 0 ? KardexArticulo._fmtMiles(m.ent_total) : '') + '</td>';
                html += '<td class="right">' + (m.sal_cant > 0 ? KardexArticulo._fmtMiles(m.sal_cant) : '') + '</td>';
                html += '<td class="right">' + (m.sal_pu > 0 ? KardexArticulo._fmtMiles(m.sal_pu, 4) : '') + '</td>';
                html += '<td class="right bold">' + (m.sal_total > 0 ? KardexArticulo._fmtMiles(m.sal_total) : '') + '</td>';
                html += '<td class="right bold">' + KardexArticulo._fmtMiles(m.saldo_cant) + '</td>';
                html += '<td class="right bold">' + KardexArticulo._fmtMiles(m.saldo_total) + '</td></tr>';
                tSaldoCant = parseFloat(m.saldo_cant) || 0;
                tSaldoTotal = parseFloat(m.saldo_total) || 0;
            });

            html += '<tr class="total-bar"><td colspan="2">TOTALES</td>';
            html += '<td class="right">' + KardexArticulo._fmtMiles(tEntCant) + '</td><td></td>';
            html += '<td class="right">S/ ' + KardexArticulo._fmtMiles(tEntTotal) + '</td>';
            html += '<td class="right">' + KardexArticulo._fmtMiles(tSalCant) + '</td><td></td>';
            html += '<td class="right">S/ ' + KardexArticulo._fmtMiles(tSalTotal) + '</td>';
            html += '<td class="right">' + KardexArticulo._fmtMiles(tSaldoCant) + '</td>';
            html += '<td class="right">S/ ' + KardexArticulo._fmtMiles(tSaldoTotal) + '</td></tr>';

            html += '</tbody></table>';
            html += '</div>';
            html += '<div class="legend">Artículo: ' + (art.cod_articulo || '') + ' - ' + (art.nom_art || '') + ' | Familia: ' + (art.nom_fam || '-') + ' | Stock Actual: ' + KardexArticulo._fmtMiles(art.stock_actual) + ' | Costo Prom.: S/ ' + KardexArticulo._fmtMiles(art.costo_promedio, 4) + ' | Movimientos: ' + datos.length + '</div>';
            html += '</body></html>';

            var iframe = document.createElement('iframe');
            iframe.style.cssText = 'position:fixed;top:-9999px;width:1px;height:1px';
            document.body.appendChild(iframe);
            var win = iframe.contentWindow;
            win.document.open();
            win.document.write(html);
            win.document.close();
            setTimeout(function() { win.print(); }, 300);
            setTimeout(function() { document.body.removeChild(iframe); }, 1500);
};

KardexArticulo.exportarExcel = function() {
    var self = this;
    self.cerrarExportDD();
    var artEl = document.getElementById('kaArticuloId');
    var idArticulo = artEl ? artEl.value : '';
    if (!idArticulo) { Mensaje.error({ titulo: 'Excel', texto: 'Seleccione un artículo' }); return; }
    var desdeEl = document.getElementById('kaFechaDesde');
    var hastaEl = document.getElementById('kaFechaHasta');
    var url = self.API_URL + '/kardex-articulo?id_empresa=' + self.sesion.id_empresa + '&id_articulo=' + idArticulo;
    if (desdeEl && desdeEl.value) url += '&fecha_desde=' + desdeEl.value;
    if (hastaEl && hastaEl.value) url += '&fecha_hasta=' + hastaEl.value;
    fetch(url).then(function(r) { return r.json(); }).then(function(res) {
        if (!res.ok || !res.data || res.data.length === 0) { Mensaje.error({ titulo: 'Excel', texto: 'No hay datos' }); return; }
        function go() {
            var wb = new ExcelJS.Workbook();
            var ws = wb.addWorksheet('Kardex Artículo');
            ws.columns = [
                { header: 'Fecha', key: 'fecha', width: 12 }, { header: 'Documento', key: 'doc', width: 16 },
                { header: 'Ent. Cant.', key: 'ent_cant', width: 10 }, { header: 'Ent. P.U.', key: 'ent_pu', width: 12 },
                { header: 'Ent. Total', key: 'ent_total', width: 14 },
                { header: 'Sal. Cant.', key: 'sal_cant', width: 10 }, { header: 'Sal. P.U.', key: 'sal_pu', width: 12 },
                { header: 'Sal. Total', key: 'sal_total', width: 14 },
                { header: 'Saldo Cant.', key: 'saldo_cant', width: 12 }, { header: 'Saldo Total', key: 'saldo_total', width: 14 }
            ];
            ws.getRow(1).font = { bold: true, color: { argb: 'FFFFFFFF' } };
            ws.getRow(1).fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF1A4480' } };
            ws.getRow(1).alignment = { horizontal: 'center' };
            res.data.forEach(function(m) {
                var fecha = m.fecha_movimiento ? KardexArticulo._fmtDate(m.fecha_movimiento) : '';
                ws.addRow({ fecha: fecha, doc: m.documento || '', ent_cant: parseFloat(m.ent_cant) || 0, ent_pu: parseFloat(m.ent_pu) || 0, ent_total: parseFloat(m.ent_total) || 0, sal_cant: parseFloat(m.sal_cant) || 0, sal_pu: parseFloat(m.sal_pu) || 0, sal_total: parseFloat(m.sal_total) || 0, saldo_cant: parseFloat(m.saldo_cant) || 0, saldo_total: parseFloat(m.saldo_total) || 0 });
            });
            wb.xlsx.writeBuffer().then(function(buf) {
                var a = document.createElement('a');
                a.href = URL.createObjectURL(new Blob([buf], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }));
                a.download = 'kardex_articulo_' + new Date().toISOString().slice(0, 10) + '.xlsx';
                a.click();
            });
        }
        if (typeof ExcelJS === 'undefined') { var s = document.createElement('script'); s.src = 'https://cdn.jsdelivr.net/npm/exceljs@4.4.0/dist/exceljs.min.js'; s.onload = go; document.head.appendChild(s); } else { go(); }
    });
};

KardexArticulo.exportarCSV = function() {
    var self = this;
    self.cerrarExportDD();
    var artEl = document.getElementById('kaArticuloId');
    var idArticulo = artEl ? artEl.value : '';
    if (!idArticulo) { Mensaje.error({ titulo: 'CSV', texto: 'Seleccione un artículo' }); return; }
    var desdeEl = document.getElementById('kaFechaDesde');
    var hastaEl = document.getElementById('kaFechaHasta');
    var url = self.API_URL + '/kardex-articulo?id_empresa=' + self.sesion.id_empresa + '&id_articulo=' + idArticulo;
    if (desdeEl && desdeEl.value) url += '&fecha_desde=' + desdeEl.value;
    if (hastaEl && hastaEl.value) url += '&fecha_hasta=' + hastaEl.value;
    fetch(url).then(function(r) { return r.json(); }).then(function(res) {
        if (!res.ok || !res.data || res.data.length === 0) { Mensaje.error({ titulo: 'CSV', texto: 'No hay datos' }); return; }
        var bom = '\uFEFF', rows = [];
        rows.push(['Fecha', 'Documento', 'Ent. Cant.', 'Ent. P.U.', 'Ent. Total', 'Sal. Cant.', 'Sal. P.U.', 'Sal. Total', 'Saldo Cant.', 'Saldo Total'].join(';'));
        res.data.forEach(function(m) {
            var fecha = m.fecha_movimiento ? KardexArticulo._fmtDate(m.fecha_movimiento) : '';
            rows.push(['"'+fecha+'"','"'+(m.documento||'')+'"',(parseFloat(m.ent_cant)||0).toFixed(2).replace('.',','),(parseFloat(m.ent_pu)||0).toFixed(4).replace('.',','),(parseFloat(m.ent_total)||0).toFixed(2).replace('.',','),(parseFloat(m.sal_cant)||0).toFixed(2).replace('.',','),(parseFloat(m.sal_pu)||0).toFixed(4).replace('.',','),(parseFloat(m.sal_total)||0).toFixed(2).replace('.',','),(parseFloat(m.saldo_cant)||0).toFixed(2).replace('.',','),(parseFloat(m.saldo_total)||0).toFixed(2).replace('.',',')].join(';'));
        });
        var a = document.createElement('a');
        a.href = URL.createObjectURL(new Blob([bom + rows.join('\n')], { type: 'text/csv;charset=utf-8' }));
        a.download = 'kardex_articulo_' + new Date().toISOString().slice(0, 10) + '.csv';
        a.click();
    });
};

KardexArticulo.exportarPDF = function() { this.cerrarExportDD(); this.imprimir(); };

KardexArticulo.exportarTXT = function() {
    var self = this;
    self.cerrarExportDD();
    var artEl = document.getElementById('kaArticuloId');
    var idArticulo = artEl ? artEl.value : '';
    if (!idArticulo) { Mensaje.error({ titulo: 'TXT', texto: 'Seleccione un artículo' }); return; }
    var desdeEl = document.getElementById('kaFechaDesde');
    var hastaEl = document.getElementById('kaFechaHasta');
    var url = self.API_URL + '/kardex-articulo?id_empresa=' + self.sesion.id_empresa + '&id_articulo=' + idArticulo;
    if (desdeEl && desdeEl.value) url += '&fecha_desde=' + desdeEl.value;
    if (hastaEl && hastaEl.value) url += '&fecha_hasta=' + hastaEl.value;
    fetch(url).then(function(r) { return r.json(); }).then(function(res) {
        if (!res.ok || !res.data || res.data.length === 0) { Mensaje.error({ titulo: 'TXT', texto: 'No hay datos' }); return; }
        var rows = [];
        rows.push(['Fecha', 'Documento', 'Ent. Cant.', 'Ent. P.U.', 'Ent. Total', 'Sal. Cant.', 'Sal. P.U.', 'Sal. Total', 'Saldo Cant.', 'Saldo Total'].join('\t'));
        res.data.forEach(function(m) {
            var fecha = m.fecha_movimiento ? KardexArticulo._fmtDate(m.fecha_movimiento) : '';
            rows.push([fecha,m.documento||'',(parseFloat(m.ent_cant)||0).toFixed(2),(parseFloat(m.ent_pu)||0).toFixed(4),(parseFloat(m.ent_total)||0).toFixed(2),(parseFloat(m.sal_cant)||0).toFixed(2),(parseFloat(m.sal_pu)||0).toFixed(4),(parseFloat(m.sal_total)||0).toFixed(2),(parseFloat(m.saldo_cant)||0).toFixed(2),(parseFloat(m.saldo_total)||0).toFixed(2)].join('\t'));
        });
        var a = document.createElement('a');
        a.href = URL.createObjectURL(new Blob([rows.join('\n')], { type: 'text/plain;charset=utf-8' }));
        a.download = 'kardex_articulo_' + new Date().toISOString().slice(0, 10) + '.txt';
        a.click();
    });
};

KardexArticulo.init({
    title: 'Kardex por Artículo',
    icon: 'fa-file-lines',
    idSingular: 'Movimiento',
    idField: 'id_movimiento',
    endpoint: '/kardex-articulo',
    sortDefault: 'fecha_movimiento',
    limite: 50,
    searchPlaceholder: '',
    filtroEstado: false,
    showEstado: false,
    showAcciones: false,
    showCrear: false,
    showBuscar: false,
    exportFileName: 'KardexArticulo',
    elementId: 'pageKardexArticulo',
    menuPage: 'KardexArticulo',
    columnFilters: {},
    columns: [
        { field: 'fecha_movimiento', label: 'Fecha', sortable: true, filterable: false, width: '8%',
            render: function(row) {
                return '<span style="display:block;white-space:nowrap">' + KardexArticulo._fmtDate(row.fecha_movimiento) + '</span>';
            }
        },
        { field: 'documento', label: 'Documento', sortable: true, filterable: false, width: '12%',
            render: function(row) { return '<span style="white-space:nowrap">' + (row.documento || '') + '</span>'; }
        },
        { field: 'ent_cant', label: 'Ent. Cant.', sortable: false, filterable: false, width: '9%',
            render: function(row) { return '<span style="display:block;text-align:right">' + (row.ent_cant > 0 ? KardexArticulo._fmtMiles(row.ent_cant) : '') + '</span>'; }
        },
        { field: 'ent_pu', label: 'Ent. P.U.', sortable: false, filterable: false, width: '9%',
            render: function(row) { return '<span style="display:block;text-align:right">' + (row.ent_pu > 0 ? KardexArticulo._fmtMiles(row.ent_pu, 4) : '') + '</span>'; }
        },
        { field: 'ent_total', label: 'Ent. Total', sortable: false, filterable: false, width: '10%',
            render: function(row) { return '<span style="display:block;text-align:right;font-weight:700">' + (row.ent_total > 0 ? KardexArticulo._fmtMiles(row.ent_total) : '') + '</span>'; }
        },
        { field: 'sal_cant', label: 'Sal. Cant.', sortable: false, filterable: false, width: '9%',
            render: function(row) { return '<span style="display:block;text-align:right">' + (row.sal_cant > 0 ? KardexArticulo._fmtMiles(row.sal_cant) : '') + '</span>'; }
        },
        { field: 'sal_pu', label: 'Sal. P.U.', sortable: false, filterable: false, width: '9%',
            render: function(row) { return '<span style="display:block;text-align:right">' + (row.sal_pu > 0 ? KardexArticulo._fmtMiles(row.sal_pu, 4) : '') + '</span>'; }
        },
        { field: 'sal_total', label: 'Sal. Total', sortable: false, filterable: false, width: '10%',
            render: function(row) { return '<span style="display:block;text-align:right;font-weight:700">' + (row.sal_total > 0 ? KardexArticulo._fmtMiles(row.sal_total) : '') + '</span>'; }
        },
        { field: 'saldo_cant', label: 'Saldo Cant.', sortable: false, filterable: false, width: '9%',
            render: function(row) {
                var val = parseFloat(row.saldo_cant) || 0;
                var color = val > 0 ? '#1A4480' : val < 0 ? '#dc2626' : '#64748b';
                return '<span style="display:block;text-align:right;font-weight:700;color:' + color + '">' + KardexArticulo._fmtMiles(val) + '</span>';
            }
        },
        { field: 'saldo_total', label: 'Saldo Total', sortable: false, filterable: false, width: '10%',
            render: function(row) {
                var val = parseFloat(row.saldo_total) || 0;
                var color = val > 0 ? '#1A4480' : val < 0 ? '#dc2626' : '#64748b';
                return '<span style="display:block;text-align:right;font-weight:700;color:' + color + '">' + KardexArticulo._fmtMiles(val) + '</span>';
            }
        }
    ],
    onEliminar: null
});
