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

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

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

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

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

    var toolbar = document.querySelector('#' + self.elementId + ' .prov-toolbar');
    if (toolbar) {
        var bar = document.createElement('div');
        bar.id = 'kvExtraBar';
        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';

        bar.innerHTML =
            '<label style="display:flex;align-items:center;gap:4px;font-weight:600;color:#475569;font-size:0.78rem">' +
            'Desde: <input type="date" id="kvFechaDesde" 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="kvFechaHasta" style="padding:4px 8px;border:1px solid #cbd5e1;border-radius:4px;font-size:0.78rem"></label>';
        toolbar.parentNode.insertBefore(bar, toolbar.nextSibling);

        var hoy = new Date();
        var primerDia = new Date(hoy.getFullYear(), hoy.getMonth(), 1);
        var ultimoDia = new Date(hoy.getFullYear(), hoy.getMonth() + 1, 0);
        var desdeEl = document.getElementById('kvFechaDesde');
        var hastaEl = document.getElementById('kvFechaHasta');
        if (desdeEl) desdeEl.value = primerDia.toISOString().slice(0, 10);
        if (hastaEl) hastaEl.value = ultimoDia.toISOString().slice(0, 10);

        document.getElementById('kvFechaDesde').addEventListener('change', function() {
            self.paginaActual = 1;
            self.cargarTabla();
        });
        document.getElementById('kvFechaHasta').addEventListener('change', function() {
            self.paginaActual = 1;
            self.cargarTabla();
        });
    }

    self.cargarTabla();
};

KardexValorizado.obtenerParamsExtra = function() {
    var self = this;
    var desdeEl = document.getElementById('kvFechaDesde');
    var hastaEl = document.getElementById('kvFechaHasta');
    var s = '';
    if (self.sesion && self.sesion.id_sucursal) s += '&id_sucursal=' + self.sesion.id_sucursal;
    if (desdeEl && desdeEl.value) s += '&fecha_desde=' + desdeEl.value;
    if (hastaEl && hastaEl.value) s += '&fecha_hasta=' + hastaEl.value;
    return s;
};

KardexValorizado._lastTotales = {
    total_movimientos: 0, total_entradas_cant: 0, total_entradas_valor: 0,
    total_salidas_cant: 0, total_salidas_valor: 0, total_articulos: 0
};

var _kvCargarTabla = KardexValorizado.cargarTabla;
KardexValorizado.cargarTabla = function() {
    var self = this;
    self._cargarTotales().then(function() {
        return _kvCargarTabla.call(self);
    }).then(function() {
        self._agregarTotales();
        self._pintarThead();
    }).catch(function() {});
};

KardexValorizado._pintarThead = function() {
    var self = this;
    var wrap = document.getElementById(self.elementId + 'TablaWrap');
    if (!wrap) return;
    var thead = wrap.querySelector('table thead');
    if (!thead) return;
    var trs = thead.querySelectorAll('tr');
    if (trs.length === 0) return;
    var lastTr = trs[trs.length - 1];
    var ths = lastTr.querySelectorAll('th');
    ths.forEach(function(th, i) {
        th.style.background = '#1A4480';
        th.style.color = '#fff';
        th.style.border = 'none';
        if (i === 0) {
            th.style.borderRadius = '6px 0 0 0';
        } else if (i === ths.length - 1) {
            th.style.borderRadius = '0 6px 0 0';
        } else {
            th.style.borderRadius = '0';
        }
    });
};

KardexValorizado._cargarTotales = function() {
    var self = this;
    self.ensureSesion();
    if (!self.sesion || !self.sesion.id_empresa) return Promise.resolve();
    var url = self.API_URL + '/kardex-valorizado/totales?id_empresa=' + self.sesion.id_empresa;
    var buscarVal = document.getElementById(self.elementId + 'Buscar');
    if (buscarVal && buscarVal.value.trim()) url += '&buscar=' + encodeURIComponent(buscarVal.value.trim());
    if (typeof self.obtenerParamsExtra === 'function') url += self.obtenerParamsExtra();
    if (Object.keys(self.filtrosColumna || {}).length > 0) {
        url += '&filtros=' + encodeURIComponent(JSON.stringify(self.filtrosColumna));
    }
    return fetch(url).then(function(r) { return r.json(); }).then(function(res) {
        if (res.ok) {
            self._lastTotales = {
                total_movimientos: res.total_movimientos || 0,
                total_entradas_cant: res.total_entradas_cant || 0,
                total_entradas_valor: res.total_entradas_valor || 0,
                total_salidas_cant: res.total_salidas_cant || 0,
                total_salidas_valor: res.total_salidas_valor || 0,
                total_articulos: res.total_articulos || 0
            };
        }
    }).catch(function() {});
};

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

    wrap.querySelectorAll('.kv-total-row').forEach(function(el) { el.remove(); });
    var oldResumen = document.getElementById('kvResumen');
    if (oldResumen) oldResumen.remove();

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

    var t = self._lastTotales;

    var totBg = 'background:#1A4480;border:none';
    var totTd = 'padding:8px 10px;font-weight:700;font-size:0.7rem;color:#fff';

    var trs = tbody.querySelectorAll('tr');
    var lastTr = trs.length > 0 ? trs[trs.length - 1] : null;
    if (lastTr) {
        var totalTr = document.createElement('tr');
        totalTr.className = 'kv-total-row';
        totalTr.innerHTML =
            '<td colspan="5" style="' + totTd + ';' + totBg + ';text-align:right;padding-right:8px;border-radius:0 0 0 6px">TOTALES</td>' +
            '<td style="' + totTd + ';' + totBg + ';border:none"></td>' +
            '<td style="' + totTd + ';' + totBg + ';text-align:right">' + KardexValorizado._fmtMiles(t.total_entradas_cant) + '</td>' +
            '<td style="' + totTd + ';' + totBg + ';border:none"></td>' +
            '<td style="' + totTd + ';' + totBg + ';text-align:right">' + KardexValorizado._fmtMiles(t.total_entradas_valor) + '</td>' +
            '<td style="' + totTd + ';' + totBg + ';text-align:right">' + KardexValorizado._fmtMiles(t.total_salidas_cant) + '</td>' +
            '<td style="' + totTd + ';' + totBg + ';text-align:right;border-radius:0 0 6px 0">' + KardexValorizado._fmtMiles(t.total_salidas_valor) + '</td>';
        lastTr.parentNode.insertBefore(totalTr, lastTr.nextSibling);
    }

    var pag = document.getElementById(self.elementId + 'Paginacion');
    if (pag) {
        var resumen = document.createElement('div');
        resumen.id = 'kvResumen';
        resumen.className = 'sv-resumen';
        resumen.innerHTML =
            '<div class="sv-resumen-item"><span class="sv-resumen-label">Movimientos:</span> <span class="sv-resumen-value">' + KardexValorizado._fmtMiles(t.total_movimientos) + '</span></div>' +
            '<div class="sv-resumen-item"><span class="sv-resumen-label">Artículos:</span> <span class="sv-resumen-value" style="color:#1A4480">' + KardexValorizado._fmtMiles(t.total_articulos) + '</span></div>' +
            '<div class="sv-resumen-item"><span class="sv-resumen-label">Entradas:</span> <span class="sv-resumen-value" style="color:#16a34a">' + KardexValorizado._fmtMiles(t.total_entradas_cant) + ' u.</span></div>' +
            '<div class="sv-resumen-item"><span class="sv-resumen-label">Salidas:</span> <span class="sv-resumen-value" style="color:#dc2626">' + KardexValorizado._fmtMiles(t.total_salidas_cant) + ' u.</span></div>';
        pag.parentNode.insertBefore(resumen, pag);
    }

    self._attatchRowEvents();
};

KardexValorizado._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(.kv-total-row)');
    rows.forEach(function(tr, idx) {
        var rowData = self.currentData[idx];
        if (!rowData) return;

        tr.style.cursor = 'pointer';
        tr.setAttribute('data-idx', idx);

        tr.addEventListener('dblclick', function(e) {
            if (e.target.closest('.prov-btn-accion, .prov-btn-eliminar, .prov-btn-filtro')) return;
            self._verDetalleArticulo(rowData);
        });

        var tds = tr.querySelectorAll('td');
        var docColIdx = self.columns.findIndex(function(c) { return c.field === 'documento'; });
        if (docColIdx >= 0 && 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);
            });
        }
    });
};

KardexValorizado._verDetalleArticulo = function(row) {
    var self = this;
    self.ensureSesion();
    if (!row.id_articulo || !self.sesion) return;
    fetch(self.API_URL + '/articulos/' + row.id_articulo + '?id_empresa=' + self.sesion.id_empresa)
        .then(function(r) { return r.json(); })
        .then(function(res) {
            if (!res.ok) { Mensaje.error({ titulo: 'Error', texto: 'Artículo no encontrado' }); return; }
            var a = res.data;
            var html = '<div style="padding:4px 0">';
            html += '<div style="display:grid;grid-template-columns:auto 1fr;gap:4px 16px;font-size:0.82rem">';
            html += '<span style="font-weight:600;color:#475569">Código:</span><span>' + (a.cod_articulo || '-') + '</span>';
            html += '<span style="font-weight:600;color:#475569">Cód. Venta:</span><span>' + (a.cod_vta || '-') + '</span>';
            html += '<span style="font-weight:600;color:#475569">Nombre:</span><span>' + (a.nombre || '-') + '</span>';
            html += '<span style="font-weight:600;color:#475569">Nombre Alterno:</span><span>' + (a.nombre_alterno || '-') + '</span>';
            html += '<span style="font-weight:600;color:#475569">Familia:</span><span>' + (a.familia_nombre || '-') + '</span>';
            html += '<span style="font-weight:600;color:#475569">Subfamilia:</span><span>' + (a.subfamilia_nombre || '-') + '</span>';
            html += '<span style="font-weight:600;color:#475569">Unidad:</span><span>' + (a.unidad_nombre || '-') + ' (' + (a.unidad_codigo || '') + ')</span>';
            html += '<span style="font-weight:600;color:#475569">Proveedor:</span><span>' + (a.proveedor_razon_social || '-') + '</span>';
            html += '<span style="font-weight:600;color:#475569">Peso:</span><span>' + (a.peso || '-') + '</span>';
            html += '<span style="font-weight:600;color:#475569">Moneda:</span><span>' + (a.moneda || '-') + '</span>';
            html += '<span style="font-weight:600;color:#475569">Stock Actual:</span><span style="font-weight:700">' + KardexValorizado._fmtMiles(a.stock_actual) + '</span>';
            html += '<span style="font-weight:600;color:#475569">Stock Mínimo:</span><span>' + KardexValorizado._fmtMiles(a.stock_minimo) + '</span>';
            html += '<span style="font-weight:600;color:#475569">Stock Máximo:</span><span>' + KardexValorizado._fmtMiles(a.stock_maximo) + '</span>';
            html += '<span style="font-weight:600;color:#475569">Precio Venta:</span><span>S/ ' + KardexValorizado._fmtMiles(a.precio_venta) + '</span>';
            html += '<span style="font-weight:600;color:#475569">Precio Compra:</span><span>S/ ' + KardexValorizado._fmtMiles(a.precio_compra) + '</span>';
            if (a.descripcion) html += '<span style="font-weight:600;color:#475569">Descripción:</span><span>' + a.descripcion + '</span>';
            html += '</div></div>';

            Modal.abrir({
                titulo: 'Detalle de Artículo — ' + (a.cod_articulo || ''),
                ancho: '600px',
                contenido: html,
                botones: [
                    { texto: 'Cerrar', tipo: 'primario', accion: function() { Modal.cerrar(); } }
                ]
            });
        }).catch(function() {
            Mensaje.error({ titulo: 'Error', texto: 'Error al cargar artículo' });
        });
};

KardexValorizado._mostrarMenuGuia = function(e, row) {
    var self = this;
    var ctxId = 'kvGuiaCtxMenu';
    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';
            var endpoint = row.tipo === 'E' ? '/guias-remision' : '/guias-remision';
            if (this.dataset.action === 'ver') {
                ConsultaGuias.verDetalle(row.id_documento);
            } else if (this.dataset.action === 'imprimir') {
                ConsultaGuias.imprimirDetalleVer(row.id_documento);
            }
        });
    });
};

KardexValorizado.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 filtros = [];
    var desdeEl = document.getElementById('kvFechaDesde');
    if (desdeEl && desdeEl.value) filtros.push('Desde: ' + desdeEl.value);
    var hastaEl = document.getElementById('kvFechaHasta');
    if (hastaEl && hastaEl.value) filtros.push('Hasta: ' + hastaEl.value);
    var buscarVal = document.getElementById(self.elementId + 'Buscar');
    if (buscarVal && buscarVal.value.trim()) filtros.push('Búsqueda: ' + buscarVal.value.trim());

    var datos = await self.obtenerTodosDatos();
    if (!datos || datos.length === 0) { Mensaje.error({ titulo: 'Imprimir', texto: 'No hay datos' }); return; }

    var t = self._lastTotales || {};

    var html = '<!DOCTYPE html><html><head><meta charset="UTF-8"><style>';
    html += 'body{font-family:Arial,sans-serif;font-size:11px;margin:20px;color:#1E293B}';
    html += '*{margin:0;padding:0;border:0;outline:none}';
    html += 'table{width:100%;border-collapse:collapse;font-size:10px}';
    html += 'thead{display:table-header-group}';
    html += 'th{background:#1A4480;color:#fff;padding:8px 10px;text-align:center;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}.center{text-align:center}.bold{font-weight:700}';
    html += '.tipo-e{color:#16a34a;font-weight:700}.tipo-s{color:#dc2626;font-weight:700}';
    html += '@page{margin:10mm;@bottom-center{content:counter(page);font-size:9px;color:#94A3B8}}';
    html += '</style></head><body>';
    html += '<div style="border-radius:8px;overflow:hidden">';
    html += '<table>';
    html += '<thead>';
    html += '<tr><th colspan="11" style="text-align:left;padding:0 10px 10px 10px;border:0;background:none;color:#1E293B;font-size:14px;text-transform:uppercase"><div style="display:flex;justify-content:space-between;align-items:flex-start;width:100%"><div>' + di.logoHtml + '<span style="display:inline-block;vertical-align:middle"><span style="font-weight:800;color:#1A4480">Kardex Valorizado General</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><span style="font-size:0.65rem;color:#64748B;text-transform:none">' + fechaStr + '</span></div></th></tr>';
        if (filtros.length > 0) html += '<tr><th colspan="11" style="text-align:left;padding:4px 0;border:0;background:none"><span style="font-size:9px;color:#475569;padding:4px 8px">' + filtros.join(' | ') + '</span></th></tr>';
        html += '<tr><th style="width:9%;border-radius:6px 0 0 0">Fecha</th><th style="width:7%">Código</th><th style="width:17%">Artículo</th><th style="width:10%">Familia</th><th class="center" style="width:5%">Tipo</th><th style="width:10%">Documento</th><th class="right" style="width:7%">Cant.</th><th class="right" style="width:8%">Costo Unit.</th><th class="right" style="width:9%">Costo Total</th><th class="right" style="width:7%">Saldo Cant.</th><th class="right" style="width:11%;border-radius:0 6px 0 0">Saldo Valor</th></tr>';
        html += '</thead><tbody>';

        var lastArt = '';
        datos.forEach(function(m) {
            var fecha = m.fecha_movimiento ? new Date(m.fecha_movimiento).toLocaleDateString('es-PE') : '';
            var tipoLabel = m.tipo === 'E' ? 'E' : 'S';
            var tipoClass = m.tipo === 'E' ? 'tipo-e' : 'tipo-s';
            if (m.cod_articulo !== lastArt && lastArt !== '') {
                html += '<tr style="border-top:2px solid #1A4480"><td colspan="11" style="border:none;padding:2px"></td></tr>';
            }
            lastArt = m.cod_articulo;
            html += '<tr><td>' + fecha + '</td><td>' + (m.cod_articulo || '') + '</td><td>' + (m.nom_art || '') + '</td><td>' + (m.nom_fam || '') + '</td><td class="center"><span class="' + tipoClass + '">' + tipoLabel + '</span></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><td class="right">' + KardexValorizado._fmtMiles(m.cantidad) + '</td><td class="right">' + KardexValorizado._fmtMiles(m.costo_unitario, 4) + '</td><td class="right bold">' + KardexValorizado._fmtMiles(m.costo_total) + '</td><td class="right bold">' + KardexValorizado._fmtMiles(m.saldo_cantidad) + '</td><td class="right bold">' + KardexValorizado._fmtMiles(m.saldo_valor) + '</td></tr>';
        });

        html += '<tr>';
        html += '<td colspan="5" style="background:#1A4480;color:#fff;padding:8px 10px;font-weight:700;font-size:0.7rem;text-align:right;border:0;border-radius:0 0 0 6px">TOTALES</td>';
        html += '<td style="background:#1A4480;border:0"></td>';
        html += '<td style="background:#1A4480;color:#fff;padding:8px 10px;font-weight:700;font-size:0.7rem;text-align:right;border:0">' + KardexValorizado._fmtMiles(t.total_entradas_cant) + '</td>';
        html += '<td style="background:#1A4480;border:0"></td>';
        html += '<td style="background:#1A4480;color:#fff;padding:8px 10px;font-weight:700;font-size:0.7rem;text-align:right;border:0">' + KardexValorizado._fmtMiles(t.total_entradas_valor) + '</td>';
        html += '<td style="background:#1A4480;color:#fff;padding:8px 10px;font-weight:700;font-size:0.7rem;text-align:right;border:0">' + KardexValorizado._fmtMiles(t.total_salidas_cant) + '</td>';
        html += '<td style="background:#1A4480;color:#fff;padding:8px 10px;font-weight:700;font-size:0.7rem;text-align:right;border:0;border-radius:0 0 6px 0">' + KardexValorizado._fmtMiles(t.total_salidas_valor) + '</td>';
        html += '</tr>';
        html += '</tbody></table>';
        html += '</div>';
        html += '<div style="display:flex;gap:16px;margin-top:14px;padding:8px 12px;background:#F8FAFC;border-radius:6px;font-size:9px;flex-wrap:wrap;border:1px solid #E2E8F0">';
        html += '<span style="font-weight:700;color:#334155">Movimientos: <span style="color:#1A4480">' + KardexValorizado._fmtMiles(t.total_movimientos) + '</span></span>';
        html += '<span style="font-weight:700;color:#334155">Artículos: <span style="color:#1A4480">' + KardexValorizado._fmtMiles(t.total_articulos) + '</span></span>';
        html += '<span style="font-weight:700;color:#334155">Entradas: <span style="color:#16a34a">' + KardexValorizado._fmtMiles(t.total_entradas_cant) + ' u. / S/ ' + KardexValorizado._fmtMiles(t.total_entradas_valor) + '</span></span>';
        html += '<span style="font-weight:700;color:#334155">Salidas: <span style="color:#dc2626">' + KardexValorizado._fmtMiles(t.total_salidas_cant) + ' u. / S/ ' + KardexValorizado._fmtMiles(t.total_salidas_valor) + '</span></span>';
        html += '<span style="font-weight:700;color:#334155;margin-left:auto">Total: <span style="color:#1A4480">' + KardexValorizado._fmtMiles(datos.length) + ' registro(s)</span></span>';
        html += '</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);
};

KardexValorizado.exportarExcel = function() {
    var self = this;
    self.cerrarExportDD();
    self.obtenerTodosDatos().then(function(datos) {
        if (!datos || datos.length === 0) { Mensaje.error({ titulo: 'Excel', texto: 'No hay datos para exportar' }); return; }
        function go() {
            var wb = new ExcelJS.Workbook();
            var ws = wb.addWorksheet('Kardex Valorizado');
            ws.columns = [
                { header: 'Fecha', key: 'fecha', width: 12 }, { header: 'Código', key: 'cod', width: 10 },
                { header: 'Artículo', key: 'nombre', width: 30 }, { header: 'Familia', key: 'familia', width: 16 },
                { header: 'Tipo', key: 'tipo', width: 8 }, { header: 'Documento', key: 'documento', width: 16 },
                { header: 'Cantidad', key: 'cantidad', width: 10 }, { header: 'Costo Unit.', key: 'costo_unit', width: 12 },
                { header: 'Costo Total', key: 'costo_total', width: 14 }, { header: 'Saldo Cant.', key: 'saldo_cant', width: 12 },
                { header: 'Saldo Valor', key: 'saldo_valor', 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' };
            datos.forEach(function(m) {
                var fecha = m.fecha_movimiento ? new Date(m.fecha_movimiento).toLocaleDateString('es-PE') : '';
                ws.addRow({ fecha: fecha, cod: m.cod_articulo || '', nombre: m.nom_art || '', familia: m.nom_fam || '', tipo: m.tipo === 'E' ? 'Entrada' : 'Salida', documento: m.documento || '', cantidad: parseFloat(m.cantidad) || 0, costo_unit: parseFloat(m.costo_unitario) || 0, costo_total: parseFloat(m.costo_total) || 0, saldo_cant: parseFloat(m.saldo_cantidad) || 0, saldo_valor: parseFloat(m.saldo_valor) || 0 });
            });
            ws.getColumn('cantidad').numFmt = '#,##0.00';
            ws.getColumn('costo_unit').numFmt = '#,##0.0000';
            ws.getColumn('costo_total').numFmt = '#,##0.00';
            ws.getColumn('saldo_cant').numFmt = '#,##0.00';
            ws.getColumn('saldo_valor').numFmt = '#,##0.00';
            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_valorizado_' + 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(); }
    });
};

KardexValorizado.exportarCSV = function() {
    var self = this;
    self.cerrarExportDD();
    self.obtenerTodosDatos().then(function(datos) {
        if (!datos || datos.length === 0) { Mensaje.error({ titulo: 'CSV', texto: 'No hay datos para exportar' }); return; }
        var bom = '\uFEFF', rows = [];
        rows.push(['Fecha', 'Codigo', 'Articulo', 'Familia', 'Tipo', 'Documento', 'Cantidad', 'Costo Unit.', 'Costo Total', 'Saldo Cant.', 'Saldo Valor'].join(';'));
        datos.forEach(function(m) {
            var fecha = m.fecha_movimiento ? new Date(m.fecha_movimiento).toLocaleDateString('es-PE') : '';
            rows.push(['"'+fecha+'"','"'+(m.cod_articulo||'')+'"','"'+(m.nom_art||'').replace(/"/g,'""')+'"','"'+(m.nom_fam||'').replace(/"/g,'""')+'"',m.tipo==='E'?'Entrada':'Salida','"'+(m.documento||'')+'"',(parseFloat(m.cantidad)||0).toFixed(2).replace('.',','),(parseFloat(m.costo_unitario)||0).toFixed(4).replace('.',','),(parseFloat(m.costo_total)||0).toFixed(2).replace('.',','),(parseFloat(m.saldo_cantidad)||0).toFixed(2).replace('.',','),(parseFloat(m.saldo_valor)||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_valorizado_' + new Date().toISOString().slice(0, 10) + '.csv';
        a.click();
    });
};

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

KardexValorizado.exportarTXT = function() {
    var self = this;
    self.cerrarExportDD();
    self.obtenerTodosDatos().then(function(datos) {
        if (!datos || datos.length === 0) { Mensaje.error({ titulo: 'TXT', texto: 'No hay datos para exportar' }); return; }
        var rows = [];
        rows.push(['Fecha', 'Codigo', 'Articulo', 'Familia', 'Tipo', 'Documento', 'Cantidad', 'Costo Unit.', 'Costo Total', 'Saldo Cant.', 'Saldo Valor'].join('\t'));
        datos.forEach(function(m) {
            var fecha = m.fecha_movimiento ? new Date(m.fecha_movimiento).toLocaleDateString('es-PE') : '';
            rows.push([fecha,m.cod_articulo||'',m.nom_art||'',m.nom_fam||'',m.tipo==='E'?'Entrada':'Salida',m.documento||'',(parseFloat(m.cantidad)||0).toFixed(2),(parseFloat(m.costo_unitario)||0).toFixed(4),(parseFloat(m.costo_total)||0).toFixed(2),(parseFloat(m.saldo_cantidad)||0).toFixed(2),(parseFloat(m.saldo_valor)||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_valorizado_' + new Date().toISOString().slice(0, 10) + '.txt';
        a.click();
    });
};

KardexValorizado.init({
    title: 'Kardex Valorizado General',
    icon: 'fa-book',
    idSingular: 'Movimiento',
    idField: 'id_movimiento',
    endpoint: '/kardex-valorizado',
    sortDefault: 'fecha_movimiento',
    limite: 50,
    searchPlaceholder: 'Buscar por codigo, articulo...',
    filtroEstado: false,
    showEstado: false,
    showAcciones: false,
    showCrear: false,
    exportFileName: 'KardexValorizado',
    elementId: 'pageKardexValorizado',
    menuPage: 'KardexValorizado',
    columnFilters: {},
    columns: [
        { field: 'fecha_movimiento', label: 'Fecha', sortable: true, filterable: false, width: '9%',
            render: function(row) {
                if (!row.fecha_movimiento) return '';
                var d = new Date(row.fecha_movimiento);
                return '<span style="display:block;white-space:nowrap">' + d.toLocaleDateString('es-PE') + '</span>';
            }
        },
        { field: 'cod_articulo', label: 'Código', sortable: true, filterable: true, width: '7%' },
        { field: 'nom_art', label: 'Artículo', sortable: true, filterable: true, width: '17%' },
        { field: 'nom_fam', label: 'Familia', sortable: true, filterable: true, width: '11%',
            render: function(row) { return '<span style="color:#64748b">' + (row.nom_fam || '') + '</span>'; }
        },
        { field: 'tipo', label: 'Tipo', sortable: true, filterable: true, width: '5%',
            filterOptions: [
                { valor: 'E', texto: 'Entrada' },
                { valor: 'S', texto: 'Salida' }
            ],
            render: function(row) {
                var isE = row.tipo === 'E';
                return '<span style="display:block;text-align:center;padding:2px 6px;border-radius:4px;font-weight:700;font-size:0.72rem;' + (isE ? 'color:#16a34a;background:#F0FDF4' : 'color:#dc2626;background:#FEF2F2') + '">' + (isE ? 'E' : 'S') + '</span>';
            }
        },
        { field: 'documento', label: 'Documento', sortable: true, filterable: false, width: '10%',
            render: function(row) {
                var html = '<span style="white-space:nowrap">' + (row.documento || '');
                if (row.num_ocs) html += '<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>';
                return html + '</span>';
            }
        },
        { field: 'cantidad', label: 'Cant.', sortable: true, filterable: false, width: '7%',
            render: function(row) {
                return '<span style="display:block;text-align:right">' + KardexValorizado._fmtMiles(row.cantidad) + '</span>';
            }
        },
        { field: 'costo_unitario', label: 'Costo Unit.', sortable: true, filterable: false, width: '8%',
            render: function(row) {
                return '<span style="display:block;text-align:right">' + KardexValorizado._fmtMiles(row.costo_unitario, 4) + '</span>';
            }
        },
        { field: 'costo_total', label: 'Costo Total', sortable: true, filterable: false, width: '9%',
            render: function(row) {
                return '<span style="display:block;text-align:right;font-weight:700">' + KardexValorizado._fmtMiles(row.costo_total) + '</span>';
            }
        },
        { field: 'saldo_cantidad', label: 'Saldo Cant.', sortable: false, filterable: false, width: '7%',
            render: function(row) {
                var val = parseFloat(row.saldo_cantidad) || 0;
                var color = val > 0 ? '#1A4480' : val < 0 ? '#dc2626' : '#64748b';
                return '<span style="display:block;text-align:right;font-weight:700;color:' + color + '">' + KardexValorizado._fmtMiles(val) + '</span>';
            }
        },
        { field: 'saldo_valor', label: 'Saldo Valor', sortable: false, filterable: false, width: '10%',
            render: function(row) {
                var val = parseFloat(row.saldo_valor) || 0;
                var color = val > 0 ? '#1A4480' : val < 0 ? '#dc2626' : '#64748b';
                return '<span style="display:block;text-align:right;font-weight:700;color:' + color + '">' + KardexValorizado._fmtMiles(val) + '</span>';
            }
        }
    ],
    onEliminar: null
});
