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

router.get('/roles', async function(req, res) {
    try {
        var buscar = req.query.buscar || '';
        var page = parseInt(req.query.page) || 1;
        var limit = parseInt(req.query.limit) || 50;
        var sort = req.query.sort || 'nombre_rol';
        var order = req.query.order || 'ASC';
        var estado = req.query.estado;
        var idEmpresa = parseInt(req.query.id_empresa);
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });
        var idSucursal = req.query.id_sucursal ? parseInt(req.query.id_sucursal) : null;
        var offset = (page - 1) * limit;

        var where = ['r.id_empresa = @id_empresa'];
        var params = { id_empresa: { type: db.sql.Int, value: idEmpresa } };

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

        if (buscar) {
            where.push("(r.nombre_rol LIKE @buscar OR r.descripcion LIKE @buscar)");
            params.buscar = { type: db.sql.NVarChar(100), value: '%' + buscar + '%' };
        }
        if (estado !== undefined && estado !== '') {
            where.push("r.estado = @estado");
            params.estado = { type: db.sql.Int, value: parseInt(estado) };
        }

        var filtros = req.query.filtros ? JSON.parse(req.query.filtros) : null;
        if (filtros) {
            var colMapRol = {
                nombre_rol: 'r.nombre_rol',
                descripcion: 'r.descripcion',
                estado: 'r.estado'
            };
            for (var col in filtros) {
                var sqlCol = colMapRol[col] || 'r.' + col;
                var vals = Array.isArray(filtros[col]) ? filtros[col] : String(filtros[col]).split('\x01');
                var placeholders = vals.map(function(v, i) { return '@f_' + col + '_' + i; });
                where.push(sqlCol + ' IN (' + placeholders.join(',') + ')');
                vals.forEach(function(v, i) {
                    if (col === 'estado') {
                        params['f_' + col + '_' + i] = { type: db.sql.Bit, value: String(v).trim() === '1' || String(v).trim() === 'true' ? 1 : 0 };
                    } else {
                        params['f_' + col + '_' + i] = { type: db.sql.NVarChar(100), value: String(v).trim() };
                    }
                });
            }
        }

        var whereStr = 'WHERE ' + where.join(' AND ');

        if (await dh.tryDistinct(req, res, { db, table: 'roles', alias: 'r', colMap: { nombre_rol: 'r.nombre_rol', descripcion: 'r.descripcion', estado: 'r.estado' }, where: whereStr, params, bitColumns: ['estado'] })) return;

        var countResult = await db.query('SELECT COUNT(*) AS total FROM roles r ' + whereStr, params);
        var total = countResult[0].total;

        var allowedSort = { nombre_rol: 'r.nombre_rol', descripcion: 'r.descripcion', estado: 'r.estado', fecha_creacion: 'r.fecha_creacion' };
        var sortCol = allowedSort[sort] || 'r.nombre_rol';
        var sortOrder = order === 'DESC' ? 'DESC' : 'ASC';

        var rows = await db.query(
            'SELECT r.id_rol, r.id_sucursal, r.nombre_rol, r.descripcion, r.estado, r.fecha_creacion FROM roles r ' + whereStr + ' ORDER BY ' + sortCol + ' ' + sortOrder + ' OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY',
            Object.assign({}, params, { offset: { type: db.sql.Int, value: offset }, limit: { type: db.sql.Int, value: limit } })
        );

        res.json({ ok: true, data: rows, total: total });
    } catch (error) {
        console.error('[ROLES] Error al listar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al listar roles' });
    }
});

router.get('/roles/:id', async function(req, res) {
    try {
        var id = parseInt(req.params.id);
        var idEmpresa = parseInt(req.query.id_empresa);
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });
        var rows = await db.query('SELECT id_rol, id_sucursal, nombre_rol, descripcion, estado FROM roles WHERE id_rol = @id AND id_empresa = @id_empresa', { id: { type: db.sql.Int, value: id }, id_empresa: { type: db.sql.Int, value: idEmpresa } });
        if (rows.length === 0) return res.status(404).json({ ok: false, mensaje: 'Rol no encontrado' });

        var permisos = await db.query('SELECT id_permiso FROM roles_permisos WHERE id_empresa = @id_empresa AND id_rol = @id AND estado = 1', { id: { type: db.sql.Int, value: id }, id_empresa: { type: db.sql.Int, value: idEmpresa } });
        var idsPermisos = permisos.map(function(p) { return p.id_permiso; });

        res.json({ ok: true, data: rows[0], permisos: idsPermisos });
    } catch (error) {
        console.error('[ROLES] Error al obtener:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al obtener rol' });
    }
});

router.get('/permisos', async function(req, res) {
    try {
        var idEmpresa = req.query.id_empresa ? parseInt(req.query.id_empresa) : null;
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });
        var rows = await db.query('SELECT id_permiso, modulo, accion, descripcion FROM permisos WHERE id_empresa = @id_empresa ORDER BY modulo, accion', {
            id_empresa: { type: db.sql.Int, value: idEmpresa }
        });
        res.json({ ok: true, data: rows });
    } catch (error) {
        console.error('[PERMISOS] Error al listar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al listar permisos' });
    }
});

router.post('/roles', async function(req, res) {
    try {
        var nombre_rol = (req.body.nombre_rol || '').toString().trim().toUpperCase();
        var descripcion = (req.body.descripcion || '').toString().trim();
        var estado = req.body.estado !== undefined ? (req.body.estado ? 1 : 0) : 1;

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

        var idEmpresa = req.body.id_empresa;
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });
        var idSucursal = req.body.id_sucursal || null;

        var dup = await db.query('SELECT id_rol FROM roles WHERE nombre_rol = @nombre_rol AND id_empresa = @id_empresa', { nombre_rol: { type: db.sql.NVarChar(50), value: nombre_rol }, id_empresa: { type: db.sql.Int, value: idEmpresa } });
        if (dup.length > 0) {
            return res.status(400).json({ ok: false, mensaje: 'El nombre del rol ya existe' });
        }

        var result = await db.query(
            "INSERT INTO roles (id_empresa, id_sucursal, nombre_rol, descripcion, estado) VALUES (@id_empresa, @id_sucursal, @nombre, @descripcion, @estado); SELECT SCOPE_IDENTITY() as id",
            {
                id_empresa: { type: db.sql.Int, value: idEmpresa },
                id_sucursal: { type: db.sql.Int, value: idSucursal },
                nombre: { type: db.sql.NVarChar(50), value: nombre_rol },
                descripcion: { type: db.sql.NVarChar(200), value: descripcion || null },
                estado: { type: db.sql.Bit, value: estado }
            }
        );
        var idRol = result[0].id;

        var permisos = req.body.permisos;
        if (permisos && Array.isArray(permisos) && permisos.length > 0) {
            for (var i = 0; i < permisos.length; i++) {
                await db.execute(
                    'INSERT INTO roles_permisos (id_rol, id_permiso, id_empresa, id_sucursal, estado) VALUES (@id_rol, @id_permiso, @id_empresa, @id_sucursal, 1)',
                    {
                        id_rol: { type: db.sql.Int, value: idRol },
                        id_permiso: { type: db.sql.Int, value: parseInt(permisos[i]) },
                        id_empresa: { type: db.sql.Int, value: idEmpresa },
                        id_sucursal: { type: db.sql.Int, value: idSucursal }
                    }
                );
            }
        }

        res.json({ ok: true, mensaje: 'Rol creado correctamente', data: { id_rol: idRol } });
    } catch (error) {
        console.error('[ROLES] Error al crear:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al crear rol' });
    }
});

router.put('/roles/: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: 'Empresa requerida' });
        var idSucursal = req.body.id_sucursal || null;
        var nombre_rol = (req.body.nombre_rol || '').toString().trim().toUpperCase();
        var descripcion = (req.body.descripcion || '').toString().trim();
        var estado = req.body.estado !== undefined ? (req.body.estado ? 1 : 0) : 1;

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

        var dup = await db.query('SELECT id_rol FROM roles WHERE nombre_rol = @nombre_rol AND id_empresa = @id_empresa AND id_rol != @id', {
            nombre_rol: { type: db.sql.NVarChar(50), value: nombre_rol },
            id_empresa: { type: db.sql.Int, value: idEmpresa },
            id: { type: db.sql.Int, value: id }
        });
        if (dup.length > 0) {
            return res.status(400).json({ ok: false, mensaje: 'El nombre del rol ya existe' });
        }

        await db.execute(
            'UPDATE roles SET nombre_rol = @nombre, descripcion = @descripcion, estado = @estado WHERE id_rol = @id AND id_empresa = @id_empresa',
            {
                nombre: { type: db.sql.NVarChar(50), value: nombre_rol },
                descripcion: { type: db.sql.NVarChar(200), value: descripcion || null },
                estado: { type: db.sql.Bit, value: estado },
                id: { type: db.sql.Int, value: id },
                id_empresa: { type: db.sql.Int, value: idEmpresa }
            }
        );

        await db.execute('DELETE FROM roles_permisos WHERE id_rol = @id AND id_empresa = @id_empresa', { id: { type: db.sql.Int, value: id }, id_empresa: { type: db.sql.Int, value: idEmpresa } });

        var permisos = req.body.permisos;
        if (permisos && Array.isArray(permisos) && permisos.length > 0) {
            for (var i = 0; i < permisos.length; i++) {
                await db.execute(
                    'INSERT INTO roles_permisos (id_rol, id_permiso, id_empresa, id_sucursal, estado) VALUES (@id_rol, @id_permiso, @id_empresa, @id_sucursal, 1)',
                    {
                        id_rol: { type: db.sql.Int, value: id },
                        id_permiso: { type: db.sql.Int, value: parseInt(permisos[i]) },
                        id_empresa: { type: db.sql.Int, value: idEmpresa },
                        id_sucursal: { type: db.sql.Int, value: idSucursal }
                    }
                );
            }
        }

        res.json({ ok: true, mensaje: 'Rol actualizado correctamente' });
    } catch (error) {
        console.error('[ROLES] Error al actualizar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al actualizar rol' });
    }
});

router.delete('/roles/:id', async function(req, res) {
    try {
        var id = parseInt(req.params.id);
        var idEmpresa = parseInt(req.query.id_empresa);
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });
        var refs = await db.query('SELECT COUNT(*) as cnt FROM usuarios_empresas WHERE id_rol = @id AND id_empresa = @id_empresa AND estado = 1', { id: { type: db.sql.Int, value: id }, id_empresa: { type: db.sql.Int, value: idEmpresa } });
        if (refs[0].cnt > 0) {
            return res.status(400).json({ ok: false, mensaje: 'No se puede desactivar: el rol está asignado a usuarios activos' });
        }
        await db.execute('UPDATE roles SET estado = 0 WHERE id_rol = @id AND id_empresa = @id_empresa', { id: { type: db.sql.Int, value: id }, id_empresa: { type: db.sql.Int, value: idEmpresa } });
        res.json({ ok: true, mensaje: 'Rol desactivado correctamente' });
    } catch (error) {
        console.error('[ROLES] Error al desactivar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al desactivar rol' });
    }
});

module.exports = router;
