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

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

        var buscar = req.query.buscar || '';
        var page = parseInt(req.query.page) || 1;
        var limit = parseInt(req.query.limit) || 50;
        var sort = req.query.sort || 'usuario';
        var order = req.query.order || 'ASC';
        var estado = req.query.estado;
        var offset = (page - 1) * limit;

        var where = ["u.id_empresa = @id_empresa"];
        var params = { id_empresa: { type: db.sql.Int, value: id_empresa } };

        if (buscar) {
            where.push("(u.usuario LIKE @buscar OR u.nombre_completo LIKE @buscar OR u.email LIKE @buscar)");
            params.buscar = { type: db.sql.NVarChar(100), value: '%' + buscar + '%' };
        }
        if (estado !== undefined && estado !== '') {
            where.push("u.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 colMapUsu = {
                usuario: 'u.usuario',
                nombre_completo: 'u.nombre_completo',
                email: 'u.email',
                estado: 'u.estado',
                sucursal_nombre: 'su.nombre'
            };
            for (var col in filtros) {
                var sqlCol = colMapUsu[col] || 'u.' + 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.length > 0 ? 'WHERE ' + where.join(' AND ') : '';

        if (await dh.tryDistinct(req, res, { db, table: 'usuarios', alias: 'u', joins: 'LEFT JOIN sucursales su ON u.id_sucursal = su.id_sucursal', colMap: { usuario: 'u.usuario', nombre_completo: 'u.nombre_completo', email: 'u.email', estado: 'u.estado', sucursal_nombre: 'su.nombre' }, where: whereStr, params, bitColumns: ['estado'] })) return;

        var countResult = await db.query('SELECT COUNT(*) AS total FROM usuarios u LEFT JOIN sucursales su ON u.id_sucursal = su.id_sucursal ' + whereStr, params);
        var total = countResult[0].total;

        var allowedSort = { usuario: 'u.usuario', nombre_completo: 'u.nombre_completo', email: 'u.email', superadmin: 'u.superadmin', estado: 'u.estado' };
        var sortCol = allowedSort[sort] || 'u.usuario';
        var sortOrder = order === 'DESC' ? 'DESC' : 'ASC';

        var rows = await db.query(
            'SELECT u.id_usuario, u.usuario, u.nombre_completo, u.email, u.estado, u.superadmin, u.debe_cambiar_pwd, u.fecha_actualizacion, u.id_sucursal, su.nombre AS sucursal_nombre FROM usuarios u LEFT JOIN sucursales su ON u.id_sucursal = su.id_sucursal ' + 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('[USUARIOS] Error al listar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al listar usuarios' });
    }
});

router.get('/usuarios/:id', async function(req, res) {
    try {
        var id = parseInt(req.params.id);
        var id_empresa = parseInt(req.query.id_empresa);
        if (!id_empresa) {
            return res.status(400).json({ ok: false, mensaje: 'id_empresa es requerido' });
        }
        var rows = await db.query(
            'SELECT u.id_usuario, u.usuario, u.nombre_completo, u.email, u.estado, u.superadmin, u.debe_cambiar_pwd, u.fecha_actualizacion, u.id_sucursal FROM usuarios u WHERE u.id_usuario = @id',
            { id: { type: db.sql.Int, value: id } }
        );
        if (rows.length === 0) return res.status(404).json({ ok: false, mensaje: 'Usuario no encontrado' });

        var usuario = rows[0];

        var asignaciones = await db.query(
            'SELECT ue.id_rol, ue.id_sucursal, r.nombre_rol, su.nombre AS sucursal_nombre FROM usuarios_empresas ue LEFT JOIN roles r ON ue.id_rol = r.id_rol LEFT JOIN sucursales su ON ue.id_sucursal = su.id_sucursal WHERE ue.id_usuario = @id AND ue.id_empresa = @id_empresa AND ue.estado = 1',
            { id: { type: db.sql.Int, value: id }, id_empresa: { type: db.sql.Int, value: id_empresa } }
        );

        usuario.asignaciones = asignaciones;

        res.json({ ok: true, data: usuario });
    } catch (error) {
        console.error('[USUARIOS] Error al obtener:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al obtener usuario' });
    }
});

router.post('/usuarios', async function(req, res) {
    try {
        var id_empresa = parseInt(req.body.id_empresa);
        if (!id_empresa) {
            return res.status(400).json({ ok: false, mensaje: 'id_empresa es requerido' });
        }

        var usuario = (req.body.usuario || '').toString().trim().toUpperCase();
        var nombre_completo = (req.body.nombre_completo || '').toString().trim().toUpperCase();
        var email = (req.body.email || '').toString().trim();
        var password = req.body.password;
        var estado = req.body.estado;

        if (!usuario || !nombre_completo || !password) {
            return res.status(400).json({ ok: false, mensaje: 'usuario, nombre_completo y password son requeridos' });
        }

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

        var superadmin = req.body.superadmin === true || req.body.superadmin === 1 || req.body.superadmin === '1';
        var idSucursal = req.body.id_sucursal ? parseInt(req.body.id_sucursal) : null;
        var asignaciones = req.body.asignaciones || [];

        var hash = await bcrypt.hash(password, 10);
        var result = await db.query(
            'INSERT INTO usuarios (id_empresa, usuario, nombre_completo, email, password_hash, superadmin, estado, intentos_fallidos, debe_cambiar_pwd, id_sucursal) VALUES (@id_empresa, @usuario, @nombre, @email, @hash, @superadmin, @estado, 0, 1, @id_sucursal); SELECT SCOPE_IDENTITY() as id',
            {
                id_empresa: { type: db.sql.Int, value: id_empresa },
                usuario: { type: db.sql.NVarChar(50), value: usuario.trim() },
                nombre: { type: db.sql.NVarChar(150), value: nombre_completo.trim() },
                email: { type: db.sql.NVarChar(100), value: email || null },
                hash: { type: db.sql.NVarChar(255), value: hash },
                superadmin: { type: db.sql.Bit, value: superadmin ? 1 : 0 },
                estado: { type: db.sql.Bit, value: estado !== undefined ? (estado ? 1 : 0) : 1 },
                id_sucursal: { type: db.sql.Int, value: idSucursal }
            }
        );
        var idUsuario = result[0].id;

        if (asignaciones.length > 0) {
            for (var i = 0; i < asignaciones.length; i++) {
                var a = asignaciones[i];
                await db.execute(
                    'INSERT INTO usuarios_empresas (id_usuario, id_empresa, id_rol, id_sucursal, estado) VALUES (@id_usuario, @id_empresa, @id_rol, @id_sucursal, 1)',
                    {
                        id_usuario: { type: db.sql.Int, value: idUsuario },
                        id_empresa: { type: db.sql.Int, value: id_empresa },
                        id_rol: { type: db.sql.Int, value: parseInt(a.id_rol) },
                        id_sucursal: { type: db.sql.Int, value: a.id_sucursal ? parseInt(a.id_sucursal) : null }
                    }
                );
            }
        } else if (req.body.id_rol) {
            await db.execute(
                'INSERT INTO usuarios_empresas (id_usuario, id_empresa, id_rol, id_sucursal, estado) VALUES (@id_usuario, @id_empresa, @id_rol, @id_sucursal, 1)',
                {
                    id_usuario: { type: db.sql.Int, value: idUsuario },
                    id_empresa: { type: db.sql.Int, value: id_empresa },
                    id_rol: { type: db.sql.Int, value: parseInt(req.body.id_rol) },
                    id_sucursal: { type: db.sql.Int, value: idSucursal }
                }
            );
        }

        res.json({ ok: true, mensaje: 'Usuario creado correctamente' });
    } catch (error) {
        console.error('[USUARIOS] Error al crear:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al crear usuario' });
    }
});

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

        var usuario = (req.body.usuario || '').toString().trim().toUpperCase();
        var nombre_completo = (req.body.nombre_completo || '').toString().trim().toUpperCase();
        var email = (req.body.email || '').toString().trim();
        var password = req.body.password;
        var estado = req.body.estado;

        var superadmin = req.body.superadmin === true || req.body.superadmin === 1 || req.body.superadmin === '1';
        var idSucursal = req.body.id_sucursal ? parseInt(req.body.id_sucursal) : null;
        var asignaciones = req.body.asignaciones;

        if (!usuario || !nombre_completo) {
            return res.status(400).json({ ok: false, mensaje: 'usuario y nombre_completo son requeridos' });
        }

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

        if (password) {
            var hash = await bcrypt.hash(password, 10);
            await db.execute(
                'UPDATE usuarios SET usuario = @usuario, nombre_completo = @nombre, email = @email, password_hash = @hash, superadmin = @superadmin, estado = @estado, id_sucursal = @id_sucursal WHERE id_usuario = @id',
                {
                    usuario: { type: db.sql.NVarChar(50), value: usuario.trim() },
                    nombre: { type: db.sql.NVarChar(150), value: nombre_completo.trim() },
                    email: { type: db.sql.NVarChar(100), value: email || null },
                    hash: { type: db.sql.NVarChar(255), value: hash },
                    superadmin: { type: db.sql.Bit, value: superadmin ? 1 : 0 },
                    estado: { type: db.sql.Bit, value: estado ? 1 : 0 },
                    id_sucursal: { type: db.sql.Int, value: idSucursal },
                    id: { type: db.sql.Int, value: id }
                }
            );
        } else {
            await db.execute(
                'UPDATE usuarios SET usuario = @usuario, nombre_completo = @nombre, email = @email, superadmin = @superadmin, estado = @estado, id_sucursal = @id_sucursal WHERE id_usuario = @id',
                {
                    usuario: { type: db.sql.NVarChar(50), value: usuario.trim() },
                    nombre: { type: db.sql.NVarChar(150), value: nombre_completo.trim() },
                    email: { type: db.sql.NVarChar(100), value: email || null },
                    superadmin: { type: db.sql.Bit, value: superadmin ? 1 : 0 },
                    estado: { type: db.sql.Bit, value: estado ? 1 : 0 },
                    id_sucursal: { type: db.sql.Int, value: idSucursal },
                    id: { type: db.sql.Int, value: id }
                }
            );
        }

        if (Array.isArray(asignaciones)) {
            await db.execute('DELETE FROM usuarios_empresas WHERE id_usuario = @id AND id_empresa = @id_empresa', {
                id: { type: db.sql.Int, value: id },
                id_empresa: { type: db.sql.Int, value: id_empresa }
            });
            for (var i = 0; i < asignaciones.length; i++) {
                var a = asignaciones[i];
                await db.execute(
                    'INSERT INTO usuarios_empresas (id_usuario, id_empresa, id_rol, id_sucursal, estado) VALUES (@id_usuario, @id_empresa, @id_rol, @id_sucursal, 1)',
                    {
                        id_usuario: { type: db.sql.Int, value: id },
                        id_empresa: { type: db.sql.Int, value: id_empresa },
                        id_rol: { type: db.sql.Int, value: parseInt(a.id_rol) },
                        id_sucursal: { type: db.sql.Int, value: a.id_sucursal ? parseInt(a.id_sucursal) : null }
                    }
                );
            }
        } else if (req.body.id_rol) {
            var existe = await db.query('SELECT id FROM usuarios_empresas WHERE id_usuario = @id AND id_empresa = @id_empresa', { id: { type: db.sql.Int, value: id }, id_empresa: { type: db.sql.Int, value: id_empresa } });
            if (existe.length > 0) {
                await db.execute(
                    'UPDATE usuarios_empresas SET id_rol = @id_rol, id_sucursal = @id_sucursal WHERE id_usuario = @id AND id_empresa = @id_empresa',
                    {
                        id_rol: { type: db.sql.Int, value: parseInt(req.body.id_rol) },
                        id_sucursal: { type: db.sql.Int, value: idSucursal },
                        id: { type: db.sql.Int, value: id },
                        id_empresa: { type: db.sql.Int, value: id_empresa }
                    }
                );
            } else {
                await db.execute(
                    'INSERT INTO usuarios_empresas (id_usuario, id_empresa, id_rol, id_sucursal, estado) VALUES (@id_usuario, @id_empresa, @id_rol, @id_sucursal, 1)',
                    {
                        id_usuario: { type: db.sql.Int, value: id },
                        id_empresa: { type: db.sql.Int, value: id_empresa },
                        id_rol: { type: db.sql.Int, value: parseInt(req.body.id_rol) },
                        id_sucursal: { type: db.sql.Int, value: idSucursal }
                    }
                );
            }
        }

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

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

        await db.execute('UPDATE usuarios_empresas SET estado = 0 WHERE id_usuario = @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: 'Usuario desactivado correctamente' });
    } catch (error) {
        console.error('[USUARIOS] Error al desactivar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al desactivar usuario' });
    }
});

module.exports = router;
