const express = require('express');
const router = express.Router();
const db = require('../config/db');
const dh = require('./distinctHelper');


// ...

async function generarCodigoArticulo(idEmpresa) {
    var rows = await db.query(
        "SELECT cod_articulo FROM articulos WHERE id_empresa = @emp AND cod_articulo LIKE 'A%'",
        { emp: { type: db.sql.Int, value: idEmpresa } }
    );
    var maxNum = 0;
    for (var i = 0; i < rows.length; i++) {
        var num = parseInt(rows[i].cod_articulo.substring(1), 10);
        if (!isNaN(num) && num > maxNum) maxNum = num;
    }
    return 'A' + String(maxNum + 1).padStart(5, '0');
}

router.get('/articulos', async function(req, res) {
    try {
        var buscar = req.query.buscar || '';
        var page = req.query.page !== undefined ? parseInt(req.query.page) : 1;
        var limit = req.query.limit !== undefined ? parseInt(req.query.limit) : 50;
        var sinPaginacion = limit <= 0;
        var sort = req.query.sort || 'a.nombre';
        var order = req.query.order === 'DESC' ? 'DESC' : 'ASC';
        var estado = req.query.estado;

        var where = 'WHERE 1=1';
        var params = {};

        if (!req.query.id_empresa) {
            return res.status(400).json({ ok: false, mensaje: 'id_empresa es requerido' });
        }
        where += ' AND a.id_empresa = @id_empresa';
        params.id_empresa = { type: db.sql.Int, value: parseInt(req.query.id_empresa) };

        if (req.query.id_sucursal) {
            where += ' AND a.id_sucursal = @id_sucursal';
            params.id_sucursal = { type: db.sql.Int, value: parseInt(req.query.id_sucursal) };
        }

        if (buscar) {
            where += ' AND (a.cod_articulo LIKE @buscar OR a.nombre LIKE @buscar OR a.cod_vta LIKE @buscar OR f.nombre LIKE @buscar OR p.razon_social LIKE @buscar)';
            params.buscar = { type: db.sql.NVarChar(100), value: '%' + buscar + '%' };
        }

        if (estado !== undefined && estado !== '') {
            where += ' AND a.estado = @estado';
            params.estado = { type: db.sql.Bit, value: parseInt(estado) };
        }

        // Filtros por columna (checkboxes)
        var filtros = req.query.filtros ? JSON.parse(req.query.filtros) : null;
        var fMap = {
            cod_articulo: 'a.cod_articulo',
            cod_vta: 'a.cod_vta',
            nombre: 'a.nombre',
            familia_nombre: 'f.nombre',
            proveedor_razon_social: 'p.razon_social',
            estado: 'a.estado'
        };
        if (filtros) {
            var fIdx = 0;
            for (var col in filtros) {
                var dbCol = fMap[col] || col;
                var vals = Array.isArray(filtros[col]) ? filtros[col] : String(filtros[col]).split('\x01');
                var conds = vals.map(function(v) {
                    var paramName = 'f' + fIdx;
                    fIdx++;
                    params[paramName] = { type: db.sql.NVarChar(200), value: '%' + v.trim() + '%' };
                    return dbCol + ' LIKE @' + paramName;
                });
                where += ' AND (' + conds.join(' OR ') + ')';
            }

        }

        var joinsArticulos = 'LEFT JOIN familias f ON a.id_empresa = f.id_empresa AND a.id_familia = f.id_familia LEFT JOIN subfamilias s ON a.id_empresa = s.id_empresa AND a.id_subfamilia = s.id_subfamilia LEFT JOIN proveedores p ON a.id_empresa = p.id_empresa AND a.id_proveedor = p.id_proveedor LEFT JOIN unidad_medida u ON a.id_empresa = u.id_empresa AND a.id_unidad = u.id_unidad';
        if (await dh.tryDistinct(req, res, { db, table: 'articulos', alias: 'a', joins: joinsArticulos, colMap: fMap, where, params, bitColumns: ['estado'] })) return;

        var joins = ' FROM articulos a ' + joinsArticulos;

        var sqlCount = 'SELECT COUNT(*) as total' + joins + ' ' + where;
        var countResult = await db.query(sqlCount, params);
        var total = countResult[0].total;
        var totalPaginas = total > 0 ? Math.ceil(total / Math.abs(limit)) : 0;

        var allowedSort = {
            cod_articulo: 'a.cod_articulo',
            cod_vta: 'a.cod_vta',
            nombre: 'a.nombre',
            familia_nombre: 'f.nombre',
            proveedor_razon_social: 'p.razon_social',
            precio_venta: 'a.precio_venta',
            precio_compra: 'a.precio_compra',
            precio_n02: 'a.precio_n02',
            precio_n03: 'a.precio_n03',
            precio_n04: 'a.precio_n04',
            precio_n05: 'a.precio_n05',
            stock_actual: 'a.stock_actual',
            estado: 'a.estado',
            fecha_creacion: 'a.fecha_creacion'
        };
        var sortCol = allowedSort[sort] || 'a.nombre';

        var selectCols = 'a.id_articulo, a.cod_articulo, a.cod_vta, a.nombre, a.nombre_alterno, a.id_familia, f.nombre AS familia_nombre, f.cod_familia AS familia_codigo, a.id_subfamilia, s.nombre AS subfamilia_nombre, a.id_proveedor, p.razon_social AS proveedor_razon_social, a.id_unidad, u.nombre AS unidad_nombre, u.cod_sunat AS unidad_codigo, a.precio_venta, a.precio_compra, a.precio_n02, a.precio_n03, a.precio_n04, a.precio_n05, a.stock_actual, a.stock_minimo, a.stock_maximo, a.peso, a.moneda, a.descripcion, a.estado, a.fecha_creacion, a.id_sucursal';

        var sqlData;
        if (sinPaginacion) {
            sqlData = 'SELECT ' + selectCols + joins + ' ' + where + ' ORDER BY ' + sortCol + ' ' + order;
        } else {
            var offset = (page - 1) * limit;
            sqlData = 'SELECT ' + selectCols + joins + ' ' + where + ' ORDER BY ' + sortCol + ' ' + order + ' OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY';
            params.offset = { type: db.sql.Int, value: offset };
            params.limit = { type: db.sql.Int, value: limit };
        }

        var data = await db.query(sqlData, params);
        res.json({ ok: true, data: data, total: total, totalPaginas: totalPaginas, page: page });
    } catch (error) {
        console.error('[ARTICULOS] Error al listar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al listar artículos' });
    }
});

router.get('/articulos/:id', async function(req, res) {
    try {
        var idEmpresa = req.query.id_empresa;
        if (!idEmpresa) {
            return res.status(400).json({ ok: false, mensaje: 'id_empresa es requerido' });
        }
        var data = await db.query(
            'SELECT a.id_articulo, a.id_empresa, a.cod_articulo, a.cod_vta, a.nombre, a.nombre_alterno, a.id_familia, f.nombre AS familia_nombre, a.id_subfamilia, s.nombre AS subfamilia_nombre, a.id_proveedor, p.razon_social AS proveedor_razon_social, p.cod_proveedor AS proveedor_codigo, a.id_unidad, u.nombre AS unidad_nombre, u.cod_sunat AS unidad_codigo, a.precio_venta, a.precio_compra, a.precio_n02, a.precio_n03, a.precio_n04, a.precio_n05, a.stock_actual, a.stock_minimo, a.stock_maximo, a.peso, a.moneda, a.descripcion, a.estado, a.id_sucursal FROM articulos a LEFT JOIN familias f ON a.id_empresa = f.id_empresa AND a.id_familia = f.id_familia LEFT JOIN subfamilias s ON a.id_empresa = s.id_empresa AND a.id_subfamilia = s.id_subfamilia LEFT JOIN proveedores p ON a.id_empresa = p.id_empresa AND a.id_proveedor = p.id_proveedor LEFT JOIN unidad_medida u ON a.id_empresa = u.id_empresa AND a.id_unidad = u.id_unidad WHERE a.id_articulo = @id AND a.id_empresa = @id_empresa',
            { id: { type: db.sql.Int, value: parseInt(req.params.id) }, id_empresa: { type: db.sql.Int, value: parseInt(idEmpresa) } }
        );
        if (data.length === 0) return res.status(404).json({ ok: false, mensaje: 'Artículo no encontrado' });
        res.json({ ok: true, data: data[0] });
    } catch (error) {
        console.error('[ARTICULOS] Error al obtener:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al obtener artículo' });
    }
});

router.post('/articulos', async function(req, res) {
    try {
        var nombre = (req.body.nombre || '').toString().trim().toUpperCase();
        var nombreAlterno = (req.body.nombre_alterno || '').toString().trim().toUpperCase();
        var codVta = (req.body.cod_vta || '').toString().trim().toUpperCase();
        var idFamilia = req.body.id_familia ? parseInt(req.body.id_familia) : null;
        var idSubfamilia = req.body.id_subfamilia ? parseInt(req.body.id_subfamilia) : null;
        var idProveedor = req.body.id_proveedor ? parseInt(req.body.id_proveedor) : null;
        var idUnidad = req.body.id_unidad ? parseInt(req.body.id_unidad) : null;
        var precioVenta = parseFloat(req.body.precio_venta) || 0;
        var precioCompra = parseFloat(req.body.precio_compra) || 0;
        var precioN02 = parseFloat(req.body.precio_n02) || 0;
        var precioN03 = parseFloat(req.body.precio_n03) || 0;
        var precioN04 = parseFloat(req.body.precio_n04) || 0;
        var precioN05 = parseFloat(req.body.precio_n05) || 0;
        var stockActual = parseFloat(req.body.stock_actual) || 0;
        var stockMinimo = parseFloat(req.body.stock_minimo) || 0;
        var stockMaximo = parseFloat(req.body.stock_maximo) || 0;
        var peso = parseFloat(req.body.peso) || 0;
        var moneda = (req.body.moneda || 'PEN').toString().trim().toUpperCase();
        var descripcion = (req.body.descripcion || '').toString().trim().toUpperCase();
        var estado = req.body.estado !== undefined ? (req.body.estado ? 1 : 0) : 1;
        var idEmpresa = parseInt(req.body.id_empresa);
        var idSucursal = req.body.id_sucursal ? parseInt(req.body.id_sucursal) : null;

        if (!nombre) { return res.status(400).json({ ok: false, mensaje: 'El nombre del artículo es requerido' }); }
        if (!idEmpresa) { return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' }); }

        if (codVta) {
            var dupVta = await db.query('SELECT COUNT(*) as cnt FROM articulos WHERE cod_vta = @cod_vta AND id_empresa = @emp AND cod_vta IS NOT NULL AND cod_vta != \'\'', {
                cod_vta: { type: db.sql.NVarChar(12), value: codVta },
                emp: { type: db.sql.Int, value: idEmpresa }
            });
            if (dupVta[0].cnt > 0) {
                return res.status(400).json({ ok: false, mensaje: 'El código de venta ya existe' });
            }
        }

        var cod = await generarCodigoArticulo(idEmpresa);

        var result = await db.query(
            'INSERT INTO articulos (id_empresa, id_sucursal, cod_articulo, cod_vta, nombre, nombre_alterno, id_familia, id_subfamilia, id_proveedor, id_unidad, precio_venta, precio_compra, precio_n02, precio_n03, precio_n04, precio_n05, stock_actual, stock_minimo, stock_maximo, peso, moneda, descripcion, estado) VALUES (@id_empresa, @id_sucursal, @cod, @cod_vta, @nombre, @nombre_alterno, @id_familia, @id_subfamilia, @id_proveedor, @id_unidad, @precio_venta, @precio_compra, @precio_n02, @precio_n03, @precio_n04, @precio_n05, @stock_actual, @stock_minimo, @stock_maximo, @peso, @moneda, @descripcion, @estado); SELECT SCOPE_IDENTITY() as id',
            {
                id_empresa: { type: db.sql.Int, value: idEmpresa },
                id_sucursal: { type: db.sql.Int, value: idSucursal },
                cod: { type: db.sql.NVarChar(6), value: cod },
                cod_vta: { type: db.sql.NVarChar(12), value: codVta || null },
                nombre: { type: db.sql.NVarChar(200), value: nombre },
                nombre_alterno: { type: db.sql.NVarChar(200), value: nombreAlterno || null },
                id_familia: { type: db.sql.Int, value: idFamilia },
                id_subfamilia: { type: db.sql.Int, value: idSubfamilia },
                id_proveedor: { type: db.sql.Int, value: idProveedor },
                id_unidad: { type: db.sql.Int, value: idUnidad },
                precio_venta: { type: db.sql.Decimal(12,2), value: precioVenta },
                precio_compra: { type: db.sql.Decimal(12,2), value: precioCompra },
                precio_n02: { type: db.sql.Decimal(12,2), value: precioN02 },
                precio_n03: { type: db.sql.Decimal(12,2), value: precioN03 },
                precio_n04: { type: db.sql.Decimal(12,2), value: precioN04 },
                precio_n05: { type: db.sql.Decimal(12,2), value: precioN05 },
                stock_actual: { type: db.sql.Decimal(12,2), value: stockActual },
                stock_minimo: { type: db.sql.Decimal(12,2), value: stockMinimo },
                stock_maximo: { type: db.sql.Decimal(12,2), value: stockMaximo },
                peso: { type: db.sql.Decimal(12,3), value: peso },
                moneda: { type: db.sql.NVarChar(3), value: moneda },
                descripcion: { type: db.sql.NVarChar(500), value: descripcion || null },
                estado: { type: db.sql.Bit, value: estado }
            }
        );
        res.json({ ok: true, mensaje: 'Artículo creado', data: { id_articulo: result[0].id, cod_articulo: cod } });
    } catch (error) {
        console.error('[ARTICULOS] Error al crear:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al crear artículo' });
    }
});

router.put('/articulos/:id', async function(req, res) {
    try {
        var id = parseInt(req.params.id);
        var idEmpresa = req.query.id_empresa || req.body.id_empresa;
        if (!idEmpresa) {
            return res.status(400).json({ ok: false, mensaje: 'id_empresa es requerido' });
        }
        idEmpresa = parseInt(idEmpresa);
        var nombre = (req.body.nombre || '').toString().trim().toUpperCase();
        var nombreAlterno = (req.body.nombre_alterno || '').toString().trim().toUpperCase();
        var codVta = (req.body.cod_vta || '').toString().trim().toUpperCase();
        var idFamilia = req.body.id_familia ? parseInt(req.body.id_familia) : null;
        var idSubfamilia = req.body.id_subfamilia ? parseInt(req.body.id_subfamilia) : null;
        var idProveedor = req.body.id_proveedor ? parseInt(req.body.id_proveedor) : null;
        var idUnidad = req.body.id_unidad ? parseInt(req.body.id_unidad) : null;
        var precioVenta = parseFloat(req.body.precio_venta) || 0;
        var precioCompra = parseFloat(req.body.precio_compra) || 0;
        var precioN02 = parseFloat(req.body.precio_n02) || 0;
        var precioN03 = parseFloat(req.body.precio_n03) || 0;
        var precioN04 = parseFloat(req.body.precio_n04) || 0;
        var precioN05 = parseFloat(req.body.precio_n05) || 0;
        var stockActual = parseFloat(req.body.stock_actual) || 0;
        var stockMinimo = parseFloat(req.body.stock_minimo) || 0;
        var stockMaximo = parseFloat(req.body.stock_maximo) || 0;
        var peso = parseFloat(req.body.peso) || 0;
        var moneda = (req.body.moneda || 'PEN').toString().trim().toUpperCase();
        var descripcion = (req.body.descripcion || '').toString().trim().toUpperCase();
        var estado = req.body.estado !== undefined ? (req.body.estado ? 1 : 0) : 1;
        var idSucursal = req.body.id_sucursal ? parseInt(req.body.id_sucursal) : null;

        if (!nombre) { return res.status(400).json({ ok: false, mensaje: 'El nombre del artículo es requerido' }); }

        if (codVta) {
            var dupVta = await db.query('SELECT COUNT(*) as cnt FROM articulos WHERE cod_vta = @cod_vta AND id_empresa = @emp AND cod_vta IS NOT NULL AND cod_vta != \'\' AND id_articulo != @id', {
                cod_vta: { type: db.sql.NVarChar(12), value: codVta },
                emp: { type: db.sql.Int, value: idEmpresa },
                id: { type: db.sql.Int, value: id }
            });
            if (dupVta[0].cnt > 0) {
                return res.status(400).json({ ok: false, mensaje: 'El código de venta ya existe en otro artículo' });
            }
        }

        await db.execute(
            'UPDATE articulos SET cod_vta = @cod_vta, nombre = @nombre, nombre_alterno = @nombre_alterno, id_familia = @id_familia, id_subfamilia = @id_subfamilia, id_proveedor = @id_proveedor, id_unidad = @id_unidad, precio_venta = @precio_venta, precio_compra = @precio_compra, precio_n02 = @precio_n02, precio_n03 = @precio_n03, precio_n04 = @precio_n04, precio_n05 = @precio_n05, stock_actual = @stock_actual, stock_minimo = @stock_minimo, stock_maximo = @stock_maximo, peso = @peso, moneda = @moneda, descripcion = @descripcion, estado = @estado, id_sucursal = @id_sucursal WHERE id_articulo = @id AND id_empresa = @id_empresa',
            {
                cod_vta: { type: db.sql.NVarChar(12), value: codVta || null },
                nombre: { type: db.sql.NVarChar(200), value: nombre },
                nombre_alterno: { type: db.sql.NVarChar(200), value: nombreAlterno || null },
                id_familia: { type: db.sql.Int, value: idFamilia },
                id_subfamilia: { type: db.sql.Int, value: idSubfamilia },
                id_proveedor: { type: db.sql.Int, value: idProveedor },
                id_unidad: { type: db.sql.Int, value: idUnidad },
                precio_venta: { type: db.sql.Decimal(12,2), value: precioVenta },
                precio_compra: { type: db.sql.Decimal(12,2), value: precioCompra },
                precio_n02: { type: db.sql.Decimal(12,2), value: precioN02 },
                precio_n03: { type: db.sql.Decimal(12,2), value: precioN03 },
                precio_n04: { type: db.sql.Decimal(12,2), value: precioN04 },
                precio_n05: { type: db.sql.Decimal(12,2), value: precioN05 },
                stock_actual: { type: db.sql.Decimal(12,2), value: stockActual },
                stock_minimo: { type: db.sql.Decimal(12,2), value: stockMinimo },
                stock_maximo: { type: db.sql.Decimal(12,2), value: stockMaximo },
                peso: { type: db.sql.Decimal(12,3), value: peso },
                moneda: { type: db.sql.NVarChar(3), value: moneda },
                descripcion: { type: db.sql.NVarChar(500), value: descripcion || null },
                estado: { type: db.sql.Bit, value: estado },
                id_sucursal: { type: db.sql.Int, value: idSucursal },
                id: { type: db.sql.Int, value: id },
                id_empresa: { type: db.sql.Int, value: idEmpresa }
            }
        );
        res.json({ ok: true, mensaje: 'Artículo actualizado' });
    } catch (error) {
        console.error('[ARTICULOS] Error al actualizar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al actualizar artículo' });
    }
});

router.delete('/articulos/:id', async function(req, res) {
    try {
        var id = parseInt(req.params.id);
        var idEmpresa = req.query.id_empresa;
        if (!idEmpresa) {
            return res.status(400).json({ ok: false, mensaje: 'id_empresa es requerido' });
        }

        // Verificar si el artículo tiene movimientos en Guías, Pedidos u O/C
        var refs;
        try {
            refs = await db.query(
                `SELECT (
                    ISNULL((SELECT COUNT(*) FROM guias_remision_det WHERE id_articulo = @id), 0) +
                    ISNULL((SELECT COUNT(*) FROM guias_compras_det WHERE id_articulo = @id), 0) +
                    ISNULL((SELECT COUNT(*) FROM det_pedido WHERE id_articulo = @id), 0) +
                    ISNULL((SELECT COUNT(*) FROM det_orden_compra WHERE id_articulo = @id), 0)
                ) as cnt`,
                { id: { type: db.sql.Int, value: id } }
            );
        } catch (e) {
            if (String(e.message || e).indexOf('Invalid object name') >= 0) {
                refs = [{ cnt: 0 }];
            } else {
                throw e;
            }
        }

        if (refs && refs[0] && refs[0].cnt > 0) {
            // Tiene movimientos → solo desactivar
            await db.execute('UPDATE articulos SET estado = 0 WHERE id_articulo = @id AND id_empresa = @id_empresa', {
                id: { type: db.sql.Int, value: id },
                id_empresa: { type: db.sql.Int, value: parseInt(idEmpresa) }
            });
            res.json({ ok: true, mensaje: 'Artículo desactivado (tiene movimientos asociados)' });
        } else {
            // Sin movimientos → eliminar físicamente
            await db.execute('DELETE FROM articulos WHERE id_articulo = @id AND id_empresa = @id_empresa', {
                id: { type: db.sql.Int, value: id },
                id_empresa: { type: db.sql.Int, value: parseInt(idEmpresa) }
            });
            res.json({ ok: true, mensaje: 'Artículo eliminado permanentemente' });
        }
    } catch (error) {
        console.error('[ARTICULOS] Error al eliminar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al eliminar artículo' });
    }
});

module.exports = router;
