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


// ...


function mapearEstado(estado) {
    var map = { P: 'Pendiente', A: 'Aprobado', C: 'Cerrado', N: 'Anulado' };
    return map[estado] || estado;
}

router.get('/ordenes-compra', async function(req, res) {
    try {
        if (!req.query.id_empresa) return res.status(400).json({ ok: false, mensaje: 'id_empresa requerido' });
        var idEmpresa = parseInt(req.query.id_empresa);
        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 || 'co.fecha_oc';
        var order = req.query.order === 'DESC' ? 'DESC' : 'ASC';
        var ejercicio = parseInt(req.query.ejercicio) || new Date().getFullYear();
        var idSucursal = req.query.id_sucursal ? parseInt(req.query.id_sucursal) : null;

        var where = 'WHERE co.id_empresa = @id_empresa AND co.ejercicio = @ejercicio';
        var params = {
            id_empresa: { type: db.sql.Int, value: idEmpresa },
            ejercicio: { type: db.sql.Int, value: ejercicio }
        };

        if (idSucursal) {
            where += ' AND co.id_sucursal = @id_sucursal';
            params.id_sucursal = { type: db.sql.Int, value: idSucursal };
        }

        if (buscar) {
            where += ' AND (co.num_oc LIKE @buscar OR p.razon_social LIKE @buscar OR CAST(co.ejercicio AS VARCHAR) + \'-\' + co.num_oc LIKE @buscar OR co.num_ped LIKE @buscar OR CAST(co.ped_ejercicio AS VARCHAR) + \'-\' + co.num_ped LIKE @buscar)';
            params.buscar = { type: db.sql.NVarChar(100), value: '%' + buscar + '%' };
        }

        var fechaDesde = req.query.fecha_desde;
        var fechaHasta = req.query.fecha_hasta;
        if (fechaDesde) {
            where += ' AND co.fecha_oc >= @fecha_desde';
            params.fecha_desde = { type: db.sql.Date, value: fechaDesde };
        }
        if (fechaHasta) {
            where += ' AND co.fecha_oc <= @fecha_hasta';
            params.fecha_hasta = { type: db.sql.Date, value: fechaHasta };
        }

        var filtros = req.query.filtros ? JSON.parse(req.query.filtros) : null;
        var ocFMap = { num_oc: 'co.num_oc', proveedor_razon_social: 'p.razon_social', estado: 'co.estado', tipo: 'co.tipo' };
        if (filtros) {
            var fIdx = 0;
            for (var col in filtros) {
                var dbCol = ocFMap[col] || col;
                var vals = Array.isArray(filtros[col]) ? filtros[col] : String(filtros[col]).split('\x01');
                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;
                });
                where += ' AND (' + conds.join(' OR ') + ')';
            }
        }

        var ocJoins = 'LEFT JOIN proveedores p ON co.id_empresa = p.id_empresa AND co.id_proveedor = p.id_proveedor LEFT JOIN condiciones_pago cp ON co.id_empresa = cp.id_empresa AND co.id_condicion = cp.id_condicion';
        if (await dh.tryDistinct(req, res, { db, table: 'cab_orden_compra', alias: 'co', joins: ocJoins, where, params, colMap: ocFMap })) return;

        var joins = ' FROM cab_orden_compra co ' + ocJoins;
        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 = { num_oc: 'co.num_oc', ejercicio: 'co.ejercicio', fecha_oc: 'co.fecha_oc', proveedor_razon_social: 'p.razon_social', estado: 'co.estado', tipo: 'co.tipo' };
        var sortCol = allowedSort[sort] || 'co.fecha_oc';

        var offset = sinPaginacion ? 0 : (page - 1) * limit;
        var fetchLimit = sinPaginacion ? 10000 : limit;

        var sql = 'SELECT co.ejercicio, co.id_sucursal, co.num_oc, co.fecha_oc, co.tipo, co.estado, co.total, co.moneda, co.subtotal, co.igv, co.con_igv, co.num_ped, co.ped_ejercicio, co.fecha_entrega, cp.nombre AS condicion_nombre, p.razon_social AS proveedor_razon_social' + joins + ' ' + where +
            ' ORDER BY ' + sortCol + ' ' + order +
            ' OFFSET ' + offset + ' ROWS FETCH NEXT ' + fetchLimit + ' ROWS ONLY';

        var data = await db.query(sql, params);
        var dataMap = data.map(function(r) {
            return {
                ejercicio: r.ejercicio,
                num_oc: r.num_oc,
                fecha_oc: r.fecha_oc,
                tipo: r.tipo,
                estado: r.estado,
                estado_texto: mapearEstado(r.estado),
                total: r.total,
                moneda: r.moneda,
                subtotal: r.subtotal,
                igv: r.igv,
                con_igv: r.con_igv,
                num_ped: r.num_ped,
                ped_ejercicio: r.ped_ejercicio,
                fecha_entrega: r.fecha_entrega,
                condicion_nombre: r.condicion_nombre,
                proveedor_razon_social: r.proveedor_razon_social
            };
        });

        res.json({ ok: true, data: dataMap, total: total, totalPaginas: totalPaginas });
    } catch (error) {
        console.error('[ORDENES_COMPRA] Error listar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al listar órdenes de compra' });
    }
});

router.get('/ordenes-compra/:num_oc', async function(req, res) {
    try {
        if (!req.query.id_empresa) return res.status(400).json({ ok: false, mensaje: 'id_empresa requerido' });
        var idEmpresa = parseInt(req.query.id_empresa);
        var ejercicio = parseInt(req.query.ejercicio) || new Date().getFullYear();
        var cab = await db.query(
            'SELECT co.*, p.razon_social AS proveedor_razon_social FROM cab_orden_compra co LEFT JOIN proveedores p ON co.id_empresa = p.id_empresa AND co.id_proveedor = p.id_proveedor WHERE co.id_empresa = @id_empresa AND co.ejercicio = @ejercicio AND co.num_oc = @num_oc',
            {
                id_empresa: { type: db.sql.Int, value: idEmpresa },
                ejercicio: { type: db.sql.Int, value: ejercicio },
                num_oc: { type: db.sql.VarChar(7), value: req.params.num_oc }
            }
        );
        if (cab.length === 0) return res.status(404).json({ ok: false, mensaje: 'OC no encontrada' });

        var det = await db.query(
            'SELECT d.ejercicio, d.num_oc, d.id_articulo, d.cantidad, d.precio, d.total, d.cantidad_atendida, d.descuento, a.cod_articulo, a.nombre, u.cod_sunat AS cod_unidad FROM det_orden_compra d INNER JOIN articulos a ON d.id_empresa = a.id_empresa AND d.id_articulo = a.id_articulo LEFT JOIN unidad_medida u ON a.id_empresa = u.id_empresa AND a.id_unidad = u.id_unidad WHERE d.id_empresa = @id_empresa AND d.ejercicio = @ejercicio AND d.num_oc = @num_oc ORDER BY d.id_articulo',
            {
                id_empresa: { type: db.sql.Int, value: idEmpresa },
                ejercicio: { type: db.sql.Int, value: ejercicio },
                num_oc: { type: db.sql.VarChar(7), value: req.params.num_oc }
            }
        );

        var guiasAtencion = await db.query(
            `SELECT g.cod_guia, d.id_articulo, SUM(d.cantidad) AS cantidad_guia, g.fecha_guia
             FROM guias_remision_det d
             INNER JOIN guias_remision g ON d.id_guia = g.id_guia AND d.id_empresa = g.id_empresa
             WHERE d.id_empresa = @id_empresa AND d.num_oc = @num_oc AND d.ejercicio = @ejercicio
             GROUP BY g.cod_guia, d.id_articulo, g.fecha_guia
             ORDER BY g.cod_guia, d.id_articulo`,
            {
                id_empresa: { type: db.sql.Int, value: idEmpresa },
                ejercicio: { type: db.sql.Int, value: ejercicio },
                num_oc: { type: db.sql.VarChar(7), value: req.params.num_oc }
            }
        );

        var row = cab[0];
        row.detalle = det;
        row.guias_atencion = guiasAtencion;
        res.json({ ok: true, data: row });
    } catch (error) {
        console.error('[ORDENES_COMPRA] Error obtener:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al obtener OC' });
    }
});

router.get('/ordenes-compra/correlativo/:id_empresa', async function(req, res) {
    try {
        var ejercicio = new Date().getFullYear();
        var result = await db.query(
            "SELECT ISNULL(MAX(CAST(num_oc AS INT)), 0) + 1 AS next FROM cab_orden_compra WHERE id_empresa = @id_empresa AND ejercicio = @ejercicio",
            {
                id_empresa: { type: db.sql.Int, value: parseInt(req.params.id_empresa) },
                ejercicio: { type: db.sql.Int, value: ejercicio }
            }
        );
        var codigo = String(result[0].next).padStart(7, '0');
        res.json({ ok: true, data: { num_oc: codigo, ejercicio: ejercicio } });
    } catch (error) {
        console.error('[ORDENES_COMPRA] Error correlativo:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al generar correlativo' });
    }
});

router.post('/ordenes-compra', async function(req, res) {
    try {
        var body = req.body;
        if (!body.id_empresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });
        if (!body.detalle || body.detalle.length === 0) return res.status(400).json({ ok: false, mensaje: 'Debe agregar al menos un artículo' });

        var ejercicio = body.ejercicio || new Date().getFullYear();

        var pool = await db.getPool();
        var transaction = pool.transaction();
        await transaction.begin();

        try {
            var nextReq = transaction.request();
            nextReq.input('id_empresa', db.sql.Int, body.id_empresa);
            nextReq.input('ejercicio', db.sql.Int, ejercicio);
            var nextResult = await nextReq.query(
                "SELECT ISNULL(MAX(CAST(num_oc AS INT)), 0) + 1 AS next FROM cab_orden_compra WITH (UPDLOCK, ROWLOCK) WHERE id_empresa = @id_empresa AND ejercicio = @ejercicio"
            );
            var codigo = String(nextResult.recordset[0].next).padStart(7, '0');

            var conIgv = body.con_igv !== undefined ? (body.con_igv ? 1 : 0) : 1;
            var porcIgv = parseFloat(body.porcentaje_igv) || 18.00;
            var subtotal = parseFloat(body.subtotal) || 0;
            var igv = parseFloat(body.igv) || 0;
            var total = parseFloat(body.total) || 0;

            var cabReq = transaction.request();
            cabReq.input('num_oc', db.sql.VarChar(7), codigo);
            cabReq.input('ejercicio', db.sql.Int, ejercicio);
            cabReq.input('id_empresa', db.sql.Int, body.id_empresa);
            cabReq.input('id_sucursal', db.sql.Int, body.id_sucursal || null);
            cabReq.input('id_proveedor', db.sql.Int, body.id_proveedor || null);
            cabReq.input('fecha_oc', db.sql.Date, body.fecha_oc || new Date().toISOString().split('T')[0]);
            cabReq.input('tipo', db.sql.VarChar(1), body.tipo || 'M');
            cabReq.input('estado', db.sql.VarChar(1), body.estado || 'P');
            cabReq.input('id_condicion', db.sql.Int, body.id_condicion || null);
            cabReq.input('dias', db.sql.Int, parseInt(body.dias) || 0);
            cabReq.input('fecha_vencimiento', db.sql.Date, body.fecha_vencimiento || null);
            cabReq.input('moneda', db.sql.VarChar(2), body.moneda || 'MN');
            cabReq.input('tipo_cambio', db.sql.Decimal(7,3), parseFloat(body.tipo_cambio) || null);
            cabReq.input('con_igv', db.sql.Bit, conIgv);
            cabReq.input('porcentaje_igv', db.sql.Decimal(6,2), porcIgv);
            cabReq.input('subtotal', db.sql.Decimal(12,2), subtotal);
            cabReq.input('igv', db.sql.Decimal(10,2), igv);
            cabReq.input('total', db.sql.Decimal(12,2), total);
            cabReq.input('contacto', db.sql.VarChar(100), body.contacto || null);
            cabReq.input('solicitado_por', db.sql.VarChar(100), body.solicitado_por || null);
            cabReq.input('fecha_entrega', db.sql.Date, body.fecha_entrega || null);
            cabReq.input('observaciones', db.sql.VarChar(500), body.observaciones || null);
            cabReq.input('glosa', db.sql.VarChar(300), body.glosa || null);
            cabReq.input('num_ped', db.sql.VarChar(6), body.num_ped || null);
            cabReq.input('ped_ejercicio', db.sql.Int, body.ped_ejercicio || null);
            cabReq.input('usuario_crea', db.sql.Int, body.usuario_crea || null);
            cabReq.input('descuento', db.sql.Decimal(6,2), parseFloat(body.descuento) || 0);
            cabReq.input('descuento_tipo', db.sql.Char(1), body.descuento_tipo || '%');
            cabReq.input('descuento_valor', db.sql.Decimal(10,2), parseFloat(body.descuento_valor) || 0);
            await cabReq.query(`INSERT INTO cab_orden_compra (num_oc, ejercicio, id_empresa, id_sucursal, id_proveedor, fecha_oc, tipo, estado, id_condicion, dias, fecha_vencimiento, contacto, solicitado_por, fecha_entrega, moneda, tipo_cambio, con_igv, porcentaje_igv, subtotal, igv, total, observaciones, glosa, num_ped, ped_ejercicio, usuario_crea, descuento, descuento_tipo, descuento_valor) VALUES (@num_oc, @ejercicio, @id_empresa, @id_sucursal, @id_proveedor, @fecha_oc, @tipo, @estado, @id_condicion, @dias, @fecha_vencimiento, @contacto, @solicitado_por, @fecha_entrega, @moneda, @tipo_cambio, @con_igv, @porcentaje_igv, @subtotal, @igv, @total, @observaciones, @glosa, @num_ped, @ped_ejercicio, @usuario_crea, @descuento, @descuento_tipo, @descuento_valor)`);

            for (var i = 0; i < body.detalle.length; i++) {
                var d = body.detalle[i];
                if (!d.id_articulo || !d.cantidad || d.cantidad <= 0) continue;
                var detReq = transaction.request();
                detReq.input('num_oc', db.sql.VarChar(7), codigo);
                detReq.input('ejercicio', db.sql.Int, ejercicio);
                detReq.input('id_empresa', db.sql.Int, body.id_empresa);
                detReq.input('id_sucursal', db.sql.Int, body.id_sucursal || null);
                detReq.input('id_articulo', db.sql.Int, d.id_articulo);
                detReq.input('cantidad', db.sql.Decimal(9,3), parseFloat(d.cantidad) || 0);
                detReq.input('precio', db.sql.Decimal(10,4), parseFloat(d.precio) || 0);
                detReq.input('total', db.sql.Decimal(12,2), parseFloat(d.total) || 0);
                detReq.input('cantidad_atendida', db.sql.Decimal(9,3), 0);
                detReq.input('descuento', db.sql.Decimal(6,2), parseFloat(d.descuento) || 0);
                await detReq.query('INSERT INTO det_orden_compra (num_oc, ejercicio, id_empresa, id_sucursal, id_articulo, cantidad, precio, total, cantidad_atendida, descuento) VALUES (@num_oc, @ejercicio, @id_empresa, @id_sucursal, @id_articulo, @cantidad, @precio, @total, @cantidad_atendida, @descuento)');
            }

            await transaction.commit();

            if (body.num_ped) {
                var pendientes = await db.query(`
                    SELECT p.id_articulo, p.cantidad - ISNULL(SUM(d.cantidad), 0) AS pendiente
                    FROM det_pedido p
                    LEFT JOIN cab_orden_compra c ON c.num_ped = p.num_ped AND c.id_empresa = @id_empresa
                    LEFT JOIN det_orden_compra d ON d.num_oc = c.num_oc AND d.ejercicio = c.ejercicio AND d.id_empresa = c.id_empresa AND d.id_articulo = p.id_articulo
                    WHERE p.num_ped = @num_ped AND p.id_empresa = @id_empresa
                    GROUP BY p.id_articulo, p.cantidad
                `, { num_ped: { type: db.sql.VarChar(6), value: body.num_ped }, id_empresa: { type: db.sql.Int, value: body.id_empresa } });
                var totalCubierto = pendientes.every(function(r) { return r.pendiente <= 0; });
                await db.execute('UPDATE cab_pedido SET estado = @estado WHERE num_ped = @num_ped AND id_empresa = @id_empresa', {
                    num_ped: { type: db.sql.VarChar(6), value: body.num_ped },
                    estado: { type: db.sql.VarChar(1), value: totalCubierto ? 'C' : 'A' },
                    id_empresa: { type: db.sql.Int, value: body.id_empresa }
                });
            }

            res.json({ ok: true, mensaje: 'OC ' + codigo + ' (' + ejercicio + ') creada', data: { num_oc: codigo, ejercicio: ejercicio } });
        } catch (error) {
            await transaction.rollback();
            throw error;
        }
    } catch (error) {
        console.error('[ORDENES_COMPRA] Error crear:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al crear OC: ' + error.message });
    }
});

router.put('/ordenes-compra/:num_oc', async function(req, res) {
    try {
        if (!req.query.id_empresa) return res.status(400).json({ ok: false, mensaje: 'id_empresa requerido' });
        var idEmpresa = parseInt(req.query.id_empresa);
        var body = req.body;
        var numOc = req.params.num_oc;
        var ejercicio = parseInt(req.query.ejercicio) || body.ejercicio || new Date().getFullYear();
        if (!body.detalle || body.detalle.length === 0) return res.status(400).json({ ok: false, mensaje: 'Debe agregar al menos un artículo' });

        var pool = await db.getPool();
        var transaction = pool.transaction();
        await transaction.begin();

        try {
            var cabReq = transaction.request();
            cabReq.input('num_oc', db.sql.VarChar(7), numOc);
            cabReq.input('ejercicio', db.sql.Int, ejercicio);
            cabReq.input('id_empresa', db.sql.Int, idEmpresa);
            cabReq.input('id_proveedor', db.sql.Int, body.id_proveedor || null);
            cabReq.input('fecha_oc', db.sql.Date, body.fecha_oc || new Date().toISOString().split('T')[0]);
            cabReq.input('tipo', db.sql.VarChar(1), body.tipo || 'M');
            cabReq.input('id_condicion', db.sql.Int, body.id_condicion || null);
            cabReq.input('dias', db.sql.Int, parseInt(body.dias) || 0);
            cabReq.input('fecha_vencimiento', db.sql.Date, body.fecha_vencimiento || null);
            cabReq.input('moneda', db.sql.VarChar(2), body.moneda || 'MN');
            cabReq.input('tipo_cambio', db.sql.Decimal(7,3), parseFloat(body.tipo_cambio) || null);
            cabReq.input('con_igv', db.sql.Bit, body.con_igv ? 1 : 0);
            cabReq.input('porcentaje_igv', db.sql.Decimal(6,2), parseFloat(body.porcentaje_igv) || 18.00);
            cabReq.input('subtotal', db.sql.Decimal(12,2), parseFloat(body.subtotal) || 0);
            cabReq.input('igv', db.sql.Decimal(10,2), parseFloat(body.igv) || 0);
            cabReq.input('total', db.sql.Decimal(12,2), parseFloat(body.total) || 0);
            cabReq.input('contacto', db.sql.VarChar(100), body.contacto || null);
            cabReq.input('solicitado_por', db.sql.VarChar(100), body.solicitado_por || null);
            cabReq.input('fecha_entrega', db.sql.Date, body.fecha_entrega || null);
            cabReq.input('observaciones', db.sql.VarChar(500), body.observaciones || null);
            cabReq.input('glosa', db.sql.VarChar(300), body.glosa || null);
            cabReq.input('num_ped', db.sql.VarChar(6), body.num_ped || null);
            cabReq.input('ped_ejercicio', db.sql.Int, body.ped_ejercicio || null);
            cabReq.input('descuento', db.sql.Decimal(6,2), parseFloat(body.descuento) || 0);
            cabReq.input('descuento_tipo', db.sql.Char(1), body.descuento_tipo || '%');
            cabReq.input('descuento_valor', db.sql.Decimal(10,2), parseFloat(body.descuento_valor) || 0);
            await cabReq.query(`UPDATE cab_orden_compra SET id_proveedor=@id_proveedor, fecha_oc=@fecha_oc, tipo=@tipo, id_condicion=@id_condicion, dias=@dias, fecha_vencimiento=@fecha_vencimiento, contacto=@contacto, solicitado_por=@solicitado_por, fecha_entrega=@fecha_entrega, moneda=@moneda, tipo_cambio=@tipo_cambio, con_igv=@con_igv, porcentaje_igv=@porcentaje_igv, subtotal=@subtotal, igv=@igv, total=@total, observaciones=@observaciones, glosa=@glosa, num_ped=@num_ped, ped_ejercicio=@ped_ejercicio, descuento=@descuento, descuento_tipo=@descuento_tipo, descuento_valor=@descuento_valor WHERE id_empresa=@id_empresa AND ejercicio=@ejercicio AND num_oc=@num_oc`);

            var delReq = transaction.request();
            delReq.input('num_oc', db.sql.VarChar(7), numOc);
            delReq.input('ejercicio', db.sql.Int, ejercicio);
            delReq.input('id_empresa', db.sql.Int, idEmpresa);
            await delReq.query('DELETE FROM det_orden_compra WHERE id_empresa = @id_empresa AND ejercicio = @ejercicio AND num_oc = @num_oc');

            for (var i = 0; i < body.detalle.length; i++) {
                var d = body.detalle[i];
                if (!d.id_articulo || !d.cantidad || d.cantidad <= 0) continue;
                var detReq = transaction.request();
                detReq.input('num_oc', db.sql.VarChar(7), numOc);
                detReq.input('ejercicio', db.sql.Int, ejercicio);
                detReq.input('id_empresa', db.sql.Int, idEmpresa);
                detReq.input('id_articulo', db.sql.Int, d.id_articulo);
                detReq.input('cantidad', db.sql.Decimal(9,3), parseFloat(d.cantidad) || 0);
                detReq.input('precio', db.sql.Decimal(10,4), parseFloat(d.precio) || 0);
                detReq.input('total', db.sql.Decimal(12,2), parseFloat(d.total) || 0);
                detReq.input('cantidad_atendida', db.sql.Decimal(9,3), parseFloat(d.cantidad_atendida) || 0);
                detReq.input('descuento', db.sql.Decimal(6,2), parseFloat(d.descuento) || 0);
                await detReq.query('INSERT INTO det_orden_compra (num_oc, ejercicio, id_empresa, id_articulo, cantidad, precio, total, cantidad_atendida, descuento) VALUES (@num_oc, @ejercicio, @id_empresa, @id_articulo, @cantidad, @precio, @total, @cantidad_atendida, @descuento)');
            }

            await transaction.commit();
            res.json({ ok: true, mensaje: 'OC ' + numOc + ' (' + ejercicio + ') actualizada' });
        } catch (error) {
            await transaction.rollback();
            throw error;
        }
    } catch (error) {
        console.error('[ORDENES_COMPRA] Error actualizar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al actualizar OC: ' + error.message });
    }
});

router.delete('/ordenes-compra/:num_oc', async function(req, res) {
    try {
        if (!req.query.id_empresa) return res.status(400).json({ ok: false, mensaje: 'id_empresa requerido' });
        var idEmpresa = parseInt(req.query.id_empresa);
        var ejercicio = parseInt(req.query.ejercicio) || new Date().getFullYear();
        var pool = await db.getPool();
        var transaction = pool.transaction();
        await transaction.begin();
        try {
            var delDet = transaction.request();
            delDet.input('num_oc', db.sql.VarChar(7), req.params.num_oc);
            delDet.input('ejercicio', db.sql.Int, ejercicio);
            delDet.input('id_empresa', db.sql.Int, idEmpresa);
            await delDet.query('DELETE FROM det_orden_compra WHERE id_empresa = @id_empresa AND ejercicio = @ejercicio AND num_oc = @num_oc');

            var delCab = transaction.request();
            delCab.input('num_oc', db.sql.VarChar(7), req.params.num_oc);
            delCab.input('ejercicio', db.sql.Int, ejercicio);
            delCab.input('id_empresa', db.sql.Int, idEmpresa);
            await delCab.query('DELETE FROM cab_orden_compra WHERE id_empresa = @id_empresa AND ejercicio = @ejercicio AND num_oc = @num_oc');

            await transaction.commit();
            res.json({ ok: true, mensaje: 'OC eliminada' });
        } catch (error) {
            await transaction.rollback();
            throw error;
        }
    } catch (error) {
        console.error('[ORDENES_COMPRA] Error eliminar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al eliminar OC' });
    }
});

var TRANSICIONES = {
    P: { A: 'Aprobado', N: 'Anulado' },
    A: { C: 'Cerrado', N: 'Anulado' },
    C: {},
    N: {}
};

router.patch('/ordenes-compra/:num_oc/estado', async function(req, res) {
    try {
        if (!req.query.id_empresa) return res.status(400).json({ ok: false, mensaje: 'id_empresa requerido' });
        var idEmpresa = parseInt(req.query.id_empresa);
        var numOc = req.params.num_oc;
        var nuevoEstado = req.body.estado;
        var ejercicio = parseInt(req.query.ejercicio) || new Date().getFullYear();
        if (!nuevoEstado || !nuevoEstado.match(/^[PACN]$/)) {
            return res.status(400).json({ ok: false, mensaje: 'Estado inválido' });
        }

        var cab = await db.query('SELECT estado FROM cab_orden_compra WHERE id_empresa = @id_empresa AND ejercicio = @ejercicio AND num_oc = @num_oc', {
            id_empresa: { type: db.sql.Int, value: idEmpresa },
            ejercicio: { type: db.sql.Int, value: ejercicio },
            num_oc: { type: db.sql.VarChar(7), value: numOc }
        });
        if (cab.length === 0) return res.status(404).json({ ok: false, mensaje: 'OC no encontrada' });

        var estadoActual = cab[0].estado;
        var destino = TRANSICIONES[estadoActual];
        if (!destino || !destino[nuevoEstado]) {
            return res.status(400).json({ ok: false, mensaje: 'No se puede cambiar de ' + mapearEstado(estadoActual) + ' a ' + mapearEstado(nuevoEstado) });
        }

        await db.execute('UPDATE cab_orden_compra SET estado = @estado WHERE id_empresa = @id_empresa AND ejercicio = @ejercicio AND num_oc = @num_oc', {
            id_empresa: { type: db.sql.Int, value: idEmpresa },
            ejercicio: { type: db.sql.Int, value: ejercicio },
            num_oc: { type: db.sql.VarChar(7), value: numOc },
            estado: { type: db.sql.VarChar(1), value: nuevoEstado }
        });

        res.json({ ok: true, mensaje: 'OC ' + numOc + ' (' + ejercicio + ') ' + destino[nuevoEstado].toLowerCase() });
    } catch (error) {
        console.error('[ORDENES_COMPRA] Error cambiar estado:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al cambiar estado' });
    }
});

module.exports = router;
