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

function buildWhere(req) {
    var idEmpresa = parseInt(req.query.id_empresa);
    var buscar = req.query.buscar || '';
    var soloDiferencias = req.query.solo_diferencias === 'true';

    var conditions = ['a.id_empresa = @id_empresa', 'a.estado = 1'];
    var params = { id_empresa: { type: db.sql.Int, value: idEmpresa } };
    var idSucursal = req.query.id_sucursal ? parseInt(req.query.id_sucursal) : null;

    if (idSucursal) {
        conditions.push('a.id_sucursal = @id_sucursal');
        params.id_sucursal = { type: db.sql.Int, value: idSucursal };
    }

    if (buscar) {
        conditions.push("(a.cod_articulo LIKE @buscar OR a.nombre LIKE @buscar)");
        params.buscar = { type: db.sql.NVarChar, value: '%' + buscar + '%' };
    }

    var filtros = req.query.filtros ? JSON.parse(req.query.filtros) : null;
    if (filtros) {
        var fMap = {
            cod_articulo: 'a.cod_articulo',
            cod_vta: 'a.cod_vta',
            nom_art: 'a.nombre',
            nom_fam: 'f.nombre'
        };
        var fIdx = 0;
        for (var col in filtros) {
            var vals = Array.isArray(filtros[col]) ? filtros[col] : String(filtros[col]).split('\x01');
            var dbCol = fMap[col] || col;
            var conds = vals.map(function(v) {
                var pn = 'f' + fIdx;
                fIdx++;
                params[pn] = { type: db.sql.NVarChar(200), value: '%' + v.trim() + '%' };
                return dbCol + ' LIKE @' + pn;
            });
            conditions.push('(' + conds.join(' OR ') + ')');
        }
    }

    return { where: conditions.join(' AND '), params: params, soloDiferencias: soloDiferencias };
}

router.get('/conciliacion-fisica', function(req, res) {
    var limit = parseInt(req.query.limit);
    if (limit <= 0 || isNaN(limit)) limit = null;
    var page = parseInt(req.query.page) || 1;
    var built = buildWhere(req);

    var sort = req.query.sort || 'cod_articulo';
    var order = (req.query.order || 'ASC').toUpperCase();
    var orderMap = {
        'cod_articulo': 'sub.cod_articulo',
        'nom_art': 'sub.nom_art',
        'nom_fam': 'sub.nom_fam',
        'stock_sistema': 'sub.stock_sistema',
        'costo_promedio': 'sub.costo_promedio',
        'valor_stock': 'sub.valor_stock'
    };
    var sortCol = orderMap[sort] || 'sub.cod_articulo';
    var orderSql = sortCol + ' ' + (order === 'DESC' ? 'DESC' : 'ASC');

    var baseSql = `
        SELECT sub.* FROM (
            SELECT
                a.id_articulo,
                a.cod_articulo,
                a.cod_vta,
                a.nombre AS nom_art,
                ISNULL(f.nombre, '') AS nom_fam,
                a.id_familia,
                ISNULL(COALESCE(a.stock, a.stock_actual, 0), 0) AS stock_sistema,
                ISNULL(a.costo_promedio, 0) AS costo_promedio,
                ISNULL(COALESCE(a.stock, a.stock_actual, 0), 0) * ISNULL(a.costo_promedio, 0) AS valor_stock
            FROM articulos a
            LEFT JOIN familias f ON a.id_empresa = f.id_empresa AND a.id_familia = f.id_familia
            WHERE ${built.where}
        ) sub
        ORDER BY ${orderSql}
    `;

    var countSql = `
        SELECT COUNT(*) AS total
        FROM articulos a
        LEFT JOIN familias f ON a.id_empresa = f.id_empresa AND a.id_familia = f.id_familia
        WHERE ${built.where}
    `;

    var params = Object.assign({}, built.params);

    var conn = db.getPool();
    conn.then(function(pool) {
        if (limit !== null) {
            // Paginated query
            var offset = (page - 1) * limit;
            var dataSql = baseSql + ' OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY';
            var allParams = Object.assign({}, params);
            allParams.offset = { type: db.sql.Int, value: offset };
            allParams.limit = { type: db.sql.Int, value: limit };

            var countReq = new db.sql.Request(pool);
            Object.keys(params).forEach(function(k) {
                countReq.input(k, params[k].type, params[k].value);
            });
            countReq.query(countSql, function(err, countResult) {
                if (err) {
                    console.error('[CONCILIACION] Count error:', err.message);
                    return res.json({ ok: false, error: err.message });
                }
                var total = countResult.recordset[0].total;
                var totalPaginas = Math.ceil(total / limit);

                var dataReq = new db.sql.Request(pool);
                Object.keys(allParams).forEach(function(k) {
                    dataReq.input(k, allParams[k].type, allParams[k].value);
                });
                dataReq.query(dataSql, function(err2, result) {
                    if (err2) {
                        console.error('[CONCILIACION] Query error:', err2.message);
                        return res.json({ ok: false, error: err2.message });
                    }
                    res.json({
                        ok: true,
                        data: result.recordset || [],
                        total: total,
                        pagina: page,
                        totalPaginas: totalPaginas,
                        limit: limit
                    });
                });
            });
        } else {
            // All records (export)
            var dataReq = new db.sql.Request(pool);
            Object.keys(params).forEach(function(k) {
                dataReq.input(k, params[k].type, params[k].value);
            });
            dataReq.query(baseSql, function(err2, result) {
                if (err2) {
                    console.error('[CONCILIACION] Query error:', err2.message);
                    return res.json({ ok: false, error: err2.message });
                }
                res.json({
                    ok: true,
                    data: result.recordset || [],
                    total: 0,
                    pagina: 1,
                    totalPaginas: 1,
                    limit: 0
                });
            });
        }
    }).catch(function(err) {
        res.json({ ok: false, error: err.message });
    });
});

router.get('/conciliacion-fisica/totales', function(req, res) {
    var built = buildWhere(req);

    var sql = `
        SELECT
            COUNT(*) AS total_articulos,
            SUM(ISNULL(COALESCE(a.stock, a.stock_actual, 0), 0)) AS stock_sistema_total,
            SUM(ISNULL(COALESCE(a.stock, a.stock_actual, 0), 0) * ISNULL(a.costo_promedio, 0)) AS valor_stock_total
        FROM articulos a
        LEFT JOIN familias f ON a.id_empresa = f.id_empresa AND a.id_familia = f.id_familia
        WHERE ${built.where}
    `;

    var conn = db.getPool();
    conn.then(function(pool) {
        var req2 = new db.sql.Request(pool);
        Object.keys(built.params).forEach(function(k) {
            req2.input(k, built.params[k].type, built.params[k].value);
        });
        req2.query(sql, function(err, result) {
            if (err) return res.json({ ok: false, error: err.message });
            var r = result.recordset[0] || {};
            res.json({
                ok: true,
                total_articulos: r.total_articulos || 0,
                stock_sistema_total: r.stock_sistema_total || 0,
                valor_stock_total: r.valor_stock_total || 0
            });
        });
    }).catch(function(err) {
        res.json({ ok: false, error: err.message });
    });
});

router.post('/conciliacion-fisica/cerrar', async function(req, res) {
    try {
        var idEmpresa = parseInt(req.body.id_empresa);
        var items = req.body.items;
        var usuario = req.body.usuario || null;
        var idSucursal = req.body.id_sucursal ? parseInt(req.body.id_sucursal) : null;

        if (!idEmpresa || !items || !items.length) {
            return res.json({ ok: false, error: 'Faltan datos: id_empresa e items requeridos' });
        }

        var ajustes = items.filter(function(it) {
            var diff = (parseFloat(it.conteo_fisico) || 0) - (parseFloat(it.stock_sistema) || 0);
            return Math.abs(diff) > 0.001;
        });

        if (ajustes.length === 0) {
            return res.json({ ok: false, error: 'No hay diferencias que ajustar' });
        }

        var now = new Date();
        var fecha = now.toISOString().slice(0, 10).replace(/-/g, '');
        var fechaMov = now.toISOString().slice(0, 10);

        var pool = await db.getPool();

        var seqResult = await pool.request()
            .input('id_empresa', db.sql.Int, idEmpresa)
            .input('fecha', db.sql.VarChar(8), fecha)
            .query("SELECT ISNULL(MAX(CAST(SUBSTRING(documento, 14, 4) AS INT)), 0) + 1 AS next_seq FROM movimiento_almacen WHERE documento LIKE 'INV-' + @fecha + '-%' AND id_empresa = @id_empresa");

        var seq = ('000' + (seqResult.recordset[0].next_seq || 1)).slice(-4);
        var documento = 'INV-' + fecha + '-' + seq;

        var tx = pool.transaction();
        await tx.begin();

        try {
            for (var i = 0; i < ajustes.length; i++) {
                var it = ajustes[i];
                var diff = (parseFloat(it.conteo_fisico) || 0) - (parseFloat(it.stock_sistema) || 0);
                var cantidad = Math.abs(Math.round(diff * 1000) / 1000);
                var tipo = diff > 0 ? 'E' : 'S';
                var costo = parseFloat(it.costo_promedio) || 0;
                var costoTotal = Math.round(cantidad * costo * 100) / 100;

                var moveReq = tx.request()
                    .input('id_empresa', db.sql.Int, idEmpresa)
                    .input('id_articulo', db.sql.Int, it.id_articulo)
                    .input('tipo', db.sql.Char(1), tipo)
                    .input('documento', db.sql.VarChar(30), documento)
                    .input('cantidad', db.sql.Decimal(9, 3), cantidad)
                    .input('costo_unitario', db.sql.Decimal(10, 4), costo)
                    .input('costo_total', db.sql.Decimal(12, 2), costoTotal)
                    .input('fecha_movimiento', db.sql.Date, fechaMov)
                    .input('usuario_crea', db.sql.Int, usuario);
                var moveCols = 'id_empresa, id_articulo, tipo, documento, id_documento, cantidad, costo_unitario, costo_total, fecha_movimiento, usuario_crea';
                var moveVals = '@id_empresa, @id_articulo, @tipo, @documento, NULL, @cantidad, @costo_unitario, @costo_total, @fecha_movimiento, @usuario_crea';
                if (idSucursal) {
                    moveReq.input('id_sucursal', db.sql.Int, idSucursal);
                    moveCols += ', id_sucursal';
                    moveVals += ', @id_sucursal';
                }
                await moveReq.query('INSERT INTO movimiento_almacen (' + moveCols + ') VALUES (' + moveVals + ')');

                await tx.request()
                    .input('id_articulo', db.sql.Int, it.id_articulo)
                    .input('conteo', db.sql.Decimal(12, 2), parseFloat(it.conteo_fisico) || 0)
                    .query("UPDATE articulos SET stock_actual = @conteo WHERE id_articulo = @id_articulo");
            }

            await tx.commit();

            res.json({
                ok: true,
                message: 'Ajustes generados correctamente. Documento: ' + documento,
                documento: documento,
                items_ajustados: ajustes.length
            });
        } catch (errTx) {
            try { await tx.rollback(); } catch (e) {}
            console.error('[CF] Error en transacción:', errTx.message);
            res.json({ ok: false, error: errTx.message });
        }
    } catch (err) {
        console.error('[CF] Error en cerrar:', err.message);
        res.json({ ok: false, error: err.message });
    }
});

router.get('/conciliacion-fisica/ajustes', async function(req, res) {
    try {
        var idEmpresa = parseInt(req.query.id_empresa);
        if (!idEmpresa) return res.json({ ok: true, data: [] });
        var idSucursal = req.query.id_sucursal ? parseInt(req.query.id_sucursal) : null;

        var whereExtra = "documento LIKE 'INV-%' AND id_empresa = @id_empresa";
        var params = { id_empresa: { type: db.sql.Int, value: idEmpresa } };
        if (idSucursal) {
            whereExtra += ' AND id_sucursal = @id_sucursal';
            params.id_sucursal = { type: db.sql.Int, value: idSucursal };
        }

        var pool = await db.getPool();
        var reqAjustes = pool.request();
        Object.keys(params).forEach(function(k) {
            reqAjustes.input(k, params[k].type, params[k].value);
        });
        var result = await reqAjustes.query(`
                SELECT
                    documento,
                    MIN(fecha_movimiento) AS fecha,
                    COUNT(DISTINCT id_articulo) AS items,
                    SUM(CASE WHEN tipo='E' THEN cantidad ELSE 0 END) AS total_entradas,
                    SUM(CASE WHEN tipo='S' THEN cantidad ELSE 0 END) AS total_salidas,
                    MIN(fecha_crea) AS fecha_crea
                FROM movimiento_almacen
                WHERE ${whereExtra}
                GROUP BY documento
                ORDER BY MAX(fecha_movimiento) DESC, MAX(fecha_crea) DESC
            `);

        res.json({ ok: true, data: result.recordset || [] });
    } catch (err) {
        console.error('[CF] Error en ajustes:', err.message);
        res.json({ ok: false, error: err.message });
    }
});

router.get('/conciliacion-fisica/ajustes/:documento', async function(req, res) {
    try {
        var idEmpresa = parseInt(req.query.id_empresa);
        var documento = req.params.documento;
        if (!idEmpresa || !documento) return res.json({ ok: true, data: [] });
        var idSucursal = req.query.id_sucursal ? parseInt(req.query.id_sucursal) : null;

        var whereExtra = 'm.documento = @documento AND m.id_empresa = @id_empresa';
        var params = { id_empresa: { type: db.sql.Int, value: idEmpresa }, documento: { type: db.sql.VarChar(30), value: documento } };
        if (idSucursal) {
            whereExtra += ' AND m.id_sucursal = @id_sucursal';
            params.id_sucursal = { type: db.sql.Int, value: idSucursal };
        }

        var pool = await db.getPool();
        var reqDet = pool.request();
        Object.keys(params).forEach(function(k) {
            reqDet.input(k, params[k].type, params[k].value);
        });
        var result = await reqDet.query(`
                SELECT
                    m.id_movimiento,
                    m.id_articulo,
                    m.tipo,
                    m.cantidad,
                    m.costo_unitario,
                    m.costo_total,
                    m.fecha_movimiento,
                    m.usuario_crea,
                    m.fecha_crea,
                    a.cod_articulo,
                    a.nombre AS nom_art,
                    a.cod_vta
                FROM movimiento_almacen m
                LEFT JOIN articulos a ON m.id_empresa = a.id_empresa AND m.id_articulo = a.id_articulo
                WHERE ${whereExtra}
                ORDER BY a.cod_articulo
            `);

        res.json({ ok: true, data: result.recordset || [] });
    } catch (err) {
        console.error('[CF] Error en detalle ajuste:', err.message);
        res.json({ ok: false, error: err.message });
    }
});

router.get('/conciliacion-fisica/familias', function(req, res) {
    var idEmpresa = parseInt(req.query.id_empresa);
    if (!idEmpresa) return res.json({ ok: true, data: [] });
    var idSucursal = req.query.id_sucursal ? parseInt(req.query.id_sucursal) : null;

    var whereExtra = 'a.id_empresa = @id_empresa AND a.estado = 1 AND f.nombre IS NOT NULL';
    var params = { id_empresa: { type: db.sql.Int, value: idEmpresa } };
    if (idSucursal) {
        whereExtra += ' AND a.id_sucursal = @id_sucursal';
        params.id_sucursal = { type: db.sql.Int, value: idSucursal };
    }

    var sql = `
        SELECT DISTINCT f.id_familia, f.nombre AS nom_fam
        FROM articulos a
        LEFT JOIN familias f ON a.id_empresa = f.id_empresa AND a.id_familia = f.id_familia
        WHERE ${whereExtra}
        ORDER BY f.nombre
    `;

    var conn = db.getPool();
    conn.then(function(pool) {
        var req2 = new db.sql.Request(pool);
        Object.keys(params).forEach(function(k) {
            req2.input(k, params[k].type, params[k].value);
        });
        req2.query(sql, function(err, result) {
            if (err) return res.json({ ok: false, error: err.message });
            res.json({ ok: true, data: result.recordset || [] });
        });
    }).catch(function(err) {
        res.json({ ok: false, error: err.message });
    });
});

module.exports = router;
