

//obtener tipos de permiso

const toUpper = (val) => (typeof val === 'string' && val) ? val.toUpperCase().trim() : val;

const Permiso = require("../models/permiso");
const Tipo_Permiso = require("../models/tipo_permiso");
const { Op } = require("sequelize");
const moment = require('moment-timezone');
const Usuario = require("../models/usuario");
const Cargo = require("../models/cargo");
const Area = require("../models/area");
const fs = require('fs');
const Historial_Empresa = require("../models/historial_empresa");
const Notificacion = require("./notificacion");

// Columnas comunes para optimizar queries
const USUARIO_ATTRIBUTES = ['ID_USUARIO', 'NOMBRES', 'APELLIDOS', 'CORREO_EMPRESARIAL', 'FOTO', 'DIAS_VACACIONES'];
const TIPO_PERMISO_ATTRIBUTES = ['ID_TIPO_PERMISO', 'DETALLE_TIPO_PERMISO'];
const CARGO_ATTRIBUTES = ['ID_CARGO', 'DESCRIPCION', 'ID_AREA'];
const AREA_ATTRIBUTES = ['ID_AREA', 'DESCRIPCION'];
const HISTORIAL_ATTRIBUTES = ['ID_HISTORIAL_EMPRESA', 'ID_USUARIO', 'ID_CARGO', 'ESTADO', 'FECHA_INGRESO'];

// Calcula días de vacaciones por ley (Art. 69 Código de Trabajo Ecuador)
// Base: 15 días laborables al año. A partir del 5to año: +1 día por año adicional (máx 30)
const calcularDiasVacacionesPorLey = (fechaIngreso) => {
    if (!fechaIngreso) return 0;
    const hoy = new Date();
    const ingreso = new Date(fechaIngreso);
    const aniosCompletos = Math.floor((hoy - ingreso) / (1000 * 60 * 60 * 24 * 365.25));
    if (aniosCompletos < 1) return 0;
    return Math.min(15 + Math.max(0, aniosCompletos - 5), 30);
};

// Agrega DIAS_VACACIONES_POR_LEY a los permisos (para vistas de jefe/tthh/gerente)
const agregarInfoVacaciones = (permisos) => {
    return permisos.map(p => {
        const pJSON = p.toJSON ? p.toJSON() : { ...p };
        const historial = pJSON.USUARIO?.HISTORIAL_EMPRESA;
        const fechaIngreso = Array.isArray(historial) && historial.length > 0
            ? historial[0].FECHA_INGRESO
            : null;
        if (pJSON.USUARIO) {
            pJSON.USUARIO.DIAS_VACACIONES_POR_LEY = calcularDiasVacacionesPorLey(fechaIngreso);
        }
        return pJSON;
    });
};

async function obtenerTiposPermiso(req, res) {

    try {
        let tiposPermisoObtenidos = await Tipo_Permiso.findAll({
            where: { ESTADO: 1 },
            attributes: TIPO_PERMISO_ATTRIBUTES
        });

        if (tiposPermisoObtenidos.length > 0) {
            res.status(200).send({
                data: tiposPermisoObtenidos,
                message: "Tipos de permiso cargados correctamente"
            });
        } else {
            res.status(402).send({
                message: 'No existen tipos de permiso registrados en la base de datos'
            });
        }
    } catch (err) {
        res.status(500).send({
            message: 'error:' + err
        });
    }
}


// usuario
async function registrarPermiso(req, res) {
    try {
        let params = req.body

        let permiso = Permiso.build();
        permiso.ID_USUARIO = params.ID_USUARIO;
        permiso.ID_TIPO_PERMISO = params.ID_TIPO_PERMISO;
        permiso.FECHA_INICIO_PERMISO = params.FECHA_INICIO_PERMISO;
        permiso.FECHA_FIN_PERMISO = params.FECHA_FIN_PERMISO;
        permiso.HORA_INICIO_PERMISO = params.HORA_INICIO_PERMISO;
        permiso.HORA_FIN_PERMISO = params.HORA_FIN_PERMISO;
        permiso.TIEMPO_SOLICITADO_HORAS = params.TIEMPO_SOLICITADO_HORAS;
        permiso.DETALLE_PERMISO = toUpper(params.DETALLE_PERMISO);
        permiso.APROBACION_JEFE = params.APROBACION_JEFE;
        permiso.APROBACION_TTHH = params.APROBACION_TTHH;
        permiso.APROBACION_GERENTE = params.APROBACION_GERENTE;
        permiso.ESTADO = params.ESTADO;
        permiso.FECHA_REGISTRO = moment().tz('America/Guayaquil').format('YYYY-MM-DD HH:mm:ss')

        let permisoGuardadO = await permiso.save();
        if (permisoGuardadO) {
            // Si ESTADO=0 (pendiente jefe), verificar si existe jefe en el área
            if (params.ESTADO === 0 || params.ESTADO === '0') {
                try {
                    const usuario = await Usuario.findOne({
                        attributes: ['ID_USUARIO'],
                        where: { ID_USUARIO: params.ID_USUARIO },
                        include: [{
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            required: true,
                            where: { ESTADO: true },
                            include: [{ model: Cargo, required: true }]
                        }]
                    });

                    let tieneJefe = false;
                    if (usuario && usuario.HISTORIAL_EMPRESA && usuario.HISTORIAL_EMPRESA.length > 0) {
                        const idArea = usuario.HISTORIAL_EMPRESA[0].CARGO.ID_AREA;
                        tieneJefe = await Notificacion.verificarJefeEnArea(idArea);
                        if (tieneJefe) {
                            Notificacion.notificarJefeNuevoPermiso(idArea);
                        }
                    }

                    // Si no hay jefe de área → escalar al gerente (ESTADO=10)
                    if (!tieneJefe) {
                        await Permiso.update({ ESTADO: 10 }, { where: { ID_PERMISO: permisoGuardadO.ID_PERMISO } });
                        permisoGuardadO.ESTADO = 10;
                        Notificacion.notificarGerenteNuevoPermiso();
                    }
                } catch (pushError) {
                    console.warn('Error al verificar jefe/gerente:', pushError.message);
                }
            }

            res.status(200).send({
                message: 'Registrado exitosamente',
                data: permisoGuardadO
            });
        } else {

            res.status(402).send({
                message: 'No se ha podido registrar sus datos intenta nuevamente'
            });
        }

    } catch (e) {
        console.log(e)

        res.status(500).send({
            message: e.name
        });
    }
}


async function obtenerPermisos(req, res) {
    try {
        let buscar = req.body.palabra;
        let limit = req.body.tamanioLote;
        let offset = req.body.numeroPagina;
        let mul = limit * offset
        let permisosEncontrados;
        if (mul == 0) { mul = offset }
        permisosEncontrados = await Permiso.findAll({
            where: {
                [Op.and]: [
                    {
                        ID_USUARIO: req.params.id
                    },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar } },
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Tipo_Permiso,
                    as: 'TIPO_PERMISO',
                    attributes: TIPO_PERMISO_ATTRIBUTES
                },
                {
                    model: Usuario,
                    attributes: USUARIO_ATTRIBUTES
                }
            ],
            offset: mul,
            limit: limit,
            subQuery: false,
            order: [['ID_PERMISO', 'DESC']]
        });
        res.status(200).send({
            data: permisosEncontrados
        });


    } catch (e) {
        console.log(e)
        res.status(500).send({
            message: e.name
        });
    }
}


async function contarTotalPermisos(req, res) {
    try {
        let buscar = req.body.palabra;
        contadorPermisosEncontrados = await Permiso.count({
            where: {
                [Op.and]: [
                    {
                        ID_USUARIO: req.params.id
                    },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar } },
                        ]
                    }
                ]
            },

        });

        res.status(200).send({
            data: contadorPermisosEncontrados
        });


    } catch (e) {
        console.log(e)
        res.status(500).send({
            message: e.name
        });
    }
}



async function obtenerPermiso(req, res) {
    try {
        const permisoEncontrado = await Permiso.findOne({
            where: { ID_PERMISO: req.params.id },
            include: [
                {
                    model: Usuario,
                    attributes: USUARIO_ATTRIBUTES
                }, {
                    model: Tipo_Permiso,
                    as: 'TIPO_PERMISO',
                    attributes: TIPO_PERMISO_ATTRIBUTES
                }]
        });
        if (permisoEncontrado) {
            res.status(200).send({
                data: permisoEncontrado,
            });
        } else {
            res.status(402).send({
                message: 'No existe permiso'
            });
        }

    } catch (e) {
        console.log(e)
        res.status(500).send({
            message: e.name
        });
    }
}


async function actualizarPermiso(req, res) {
    try {
        let params = req.body;
        let permisoPorActualizar = {
            ID_TIPO_PERMISO: params.ID_TIPO_PERMISO,
            FECHA_INICIO_PERMISO: params.FECHA_INICIO_PERMISO,
            FECHA_FIN_PERMISO: params.FECHA_FIN_PERMISO,
            HORA_INICIO_PERMISO: params.HORA_INICIO_PERMISO,
            HORA_FIN_PERMISO: params.HORA_FIN_PERMISO,
            TIEMPO_SOLICITADO_HORAS: params.TIEMPO_SOLICITADO_HORAS,
            DETALLE_PERMISO: toUpper(params.DETALLE_PERMISO),
            FECHA_REGISTRO: moment.utc(moment().tz('America/Guayaquil').format('YYYY-MM-DD HH:mm:ss')).toDate()
        }

        let permisoActualizado = await Permiso.update(permisoPorActualizar, { where: { ID_PERMISO: req.params.id } });


        if (permisoActualizado) {
            res.status(200).send({
                message: 'Transaccion realizada exitosamente',
            });
        } else {

            res.status(402).send({
                message: 'No se ha podido actualziar el usuario'
            });
        }

    } catch (e) {

        console.log(e)
        res.status(500).send({
            message: e.name
        });
    }

}


async function eliminarPermiso(req, res) {
    try {
        const permisoEliminado = await Permiso.destroy({ where: { ID_PERMISO: req.params.id } });

        if (permisoEliminado) {
            res.status(200).send({
                message: 'Transaccion realizada exitosamente',
            });
        } else {
            res.status(404).send({
                message: 'No se encontro la capacitacion a eliminar',
            });
        }
    } catch (error) {
        console.error(error);
        res.status(500).send({
            message: 'Ocurrio un error en el servidor',
            error: error.message
        });
    }
}


async function registrarEvidencia(req, res) {
    try {

        const permisoPorActualizar = {
            EVIDENCIA: `uploads/evidenciaPermisos/${req.file.filename}`,
            ESTADO: 2,
            FECHA_REGISTRO: moment.utc(moment().tz('America/Guayaquil').format('YYYY-MM-DD HH:mm:ss')).toDate()
        }

        let permisoActualizado = await Permiso.update(permisoPorActualizar, { where: { ID_PERMISO: req.params.id } });

        if (permisoActualizado) {
            res.status(200).send({
                message: 'Transaccion realizada exitosamente',
            });
        } else {
            fs.unlinkSync(`uploads/evidenciaPermisos/${req.file.filename}`);
            res.status(402).send({
                message: 'No se ha podido actualziar el usuario'
            });
        }



    } catch (e) {
        console.log(e)
        fs.unlinkSync(`uploads/evidenciaPermisos/${req.file.filename}`);
        res.status(500).send({
            message: e.name
        });
    }
}



//jefe


async function obtenerPermisosPendientesParaJefe(req, res) {
    try {
        let buscar = req.body.palabra;
        let limit = req.body.tamanioLote;
        let offset = req.body.numeroPagina;
        let mul = limit * offset;

        if (mul == 0) {
            mul = offset;
        }

        const permisosEncontrados = await Permiso.findAll({
            where: {
                [Op.and]: [
                    { ESTADO: 0 },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    as: 'USUARIO',
                    required: true,
                    attributes: USUARIO_ATTRIBUTES,
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: HISTORIAL_ATTRIBUTES,
                            include: [
                                {
                                    model: Cargo,
                                    required: true,
                                    attributes: CARGO_ATTRIBUTES,
                                    where: { ID_AREA: req.params.idarea },
                                    include: [
                                        {
                                            model: Area,
                                            attributes: AREA_ATTRIBUTES
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                },
                {
                    model: Tipo_Permiso,
                    as: 'TIPO_PERMISO',
                    attributes: TIPO_PERMISO_ATTRIBUTES
                }
            ],
            subQuery: false,
            offset: mul,
            limit: limit,
            order: [['ID_PERMISO', 'DESC']]
        });

        res.status(200).send({
            data: agregarInfoVacaciones(permisosEncontrados)
        });

    } catch (e) {
        console.log(e);
        res.status(500).send({
            message: e.name
        });
    }
}

async function contarTotalPermisosPendientesParaJefe(req, res) {
    try {
        let buscar = req.body.palabra;

        const contadorPermisosEncontrados = await Permiso.count({
            where: {
                [Op.and]: [
                    { ESTADO: 0 },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: [],
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: [],
                            include: [
                                {
                                    model: Cargo,
                                    required: true,
                                    attributes: [],
                                    where: { ID_AREA: req.params.idarea },
                                    include: [
                                        {
                                            model: Area,
                                            attributes: []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        });

        res.status(200).send({
            data: contadorPermisosEncontrados
        });


    } catch (e) {
        console.log(e)
        res.status(500).send({
            message: e.name
        });
    }
}


async function obtenerPermisosRevisadosParaJefe(req, res) {
    try {
        let buscar = req.body.palabra;
        let limit = req.body.tamanioLote;
        let offset = req.body.numeroPagina;
        let mul = limit * offset;

        if (mul == 0) {
            mul = offset;
        }

        const permisosEncontrados = await Permiso.findAll({
            where: {
                [Op.and]: [
                    { ESTADO: { [Op.in]: [1, 4] } },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: USUARIO_ATTRIBUTES,
                    include: [{
                        model: Historial_Empresa,
                        as: 'HISTORIAL_EMPRESA',
                        attributes: HISTORIAL_ATTRIBUTES,
                        include: [
                            {
                                model: Cargo,
                                required: true,
                                attributes: CARGO_ATTRIBUTES,
                                where: { ID_AREA: req.params.idarea },
                                include: [
                                    {
                                        model: Area,
                                        attributes: AREA_ATTRIBUTES
                                    }
                                ]
                            }
                        ]
                    }]
                },
                {
                    model: Tipo_Permiso,
                    as: 'TIPO_PERMISO',
                    attributes: TIPO_PERMISO_ATTRIBUTES
                }
            ],
            subQuery: false,
            offset: mul,
            limit: limit,
            order: [['ID_PERMISO', 'DESC']]
        });


        res.status(200).send({
            data: agregarInfoVacaciones(permisosEncontrados)
        });

    } catch (e) {
        console.log(e);
        res.status(500).send({
            message: e.name
        });
    }
}

async function contarTotalPermisosRevisadosParaJefe(req, res) {
    try {
        let buscar = req.body.palabra;

        const contadorPermisosEncontrados = await Permiso.count({
            where: {
                [Op.and]: [
                    { ESTADO: { [Op.in]: [1, 4] } },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: [],
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: [],
                            include: [
                                {
                                    model: Cargo,
                                    required: true,
                                    attributes: [],
                                    where: { ID_AREA: req.params.idarea },
                                    include: [
                                        {
                                            model: Area,
                                            attributes: []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        });

        res.status(200).send({
            data: contadorPermisosEncontrados
        });


    } catch (e) {
        console.log(e)
        res.status(500).send({
            message: e.name
        });
    }
}

async function actualizarPermisoParaJefe(req, res) {
    try {
        let params = req.body;

        const esCargoVacJefe = params.CARGO_VACACIONES == true || params.CARGO_VACACIONES === 1 || params.CARGO_VACACIONES === '1';
        const diasCargoJefe  = parseInt(params.DIAS_CARGO_VACACIONES) || 0;

        let permisoPorActualizar = {
            ESTADO: params.ESTADO,
            COMENTARIO_JEFE: params.COMENTARIO_JEFE,
            APROBADO_POR_JEFE: params.APROBADO_POR_JEFE,
            APROBACION_JEFE: false,
            CARGO_VACACIONES: esCargoVacJefe,
            DIAS_CARGO_VACACIONES: diasCargoJefe,
            FECHA_REGISTRO: moment.utc(moment().tz('America/Guayaquil').format('YYYY-MM-DD HH:mm:ss')).toDate()
        }

        let permisoActualizado = await Permiso.update(permisoPorActualizar, { where: { ID_PERMISO: req.params.id } });

        if (permisoActualizado) {
            // Notificar al usuario via push
            const permiso = await Permiso.findOne({ where: { ID_PERMISO: req.params.id }, attributes: ['ID_USUARIO', 'ESTADO'] });
            if (permiso) {
                Notificacion.notificarUsuarioEstadoPermiso(permiso.ID_USUARIO, params.ESTADO);
            }

            res.status(200).send({
                message: 'Transaccion realizada exitosamente',
            });
        } else {

            res.status(402).send({
                message: 'No se ha podido actualziar el usuario'
            });
        }

    } catch (e) {

        console.log(e)
        res.status(500).send({
            message: e.name
        });
    }

}

// tthh

async function obtenerPermisosPendientesParaTTHH(req, res) {
    try {
        let buscar = req.body.palabra;
        let limit = req.body.tamanioLote;
        let offset = req.body.numeroPagina;
        let mul = limit * offset;

        if (mul == 0) {
            mul = offset;
        }

        const permisosEncontrados = await Permiso.findAll({
            where: {
                [Op.and]: [
                    { ESTADO: 2 },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: USUARIO_ATTRIBUTES,
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: HISTORIAL_ATTRIBUTES,
                            include: [
                                {
                                    model: Cargo,
                                    required: true,
                                    attributes: CARGO_ATTRIBUTES,
                                    include: [
                                        {
                                            model: Area,
                                            attributes: AREA_ATTRIBUTES
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                },
                {
                    model: Tipo_Permiso,
                    as: 'TIPO_PERMISO',
                    attributes: TIPO_PERMISO_ATTRIBUTES
                }
            ],
            subQuery: false,
            offset: mul,
            limit: limit,
            order: [['ID_PERMISO', 'DESC']]
        });


        res.status(200).send({
            data: agregarInfoVacaciones(permisosEncontrados)
        });

    } catch (e) {
        console.log(e);
        res.status(500).send({
            message: e.name
        });
    }
}

async function contarTotalPermisosPendientesParaTTHH(req, res) {
    try {
        let buscar = req.body.palabra;

        const contadorPermisosEncontrados = await Permiso.count({
            where: {
                [Op.and]: [
                    { ESTADO: 2 },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: [],
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: [],
                            include: [
                                {
                                    model: Cargo,
                                    required: true,
                                    attributes: [],
                                    include: [
                                        {
                                            model: Area,
                                            attributes: []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        });



        res.status(200).send({
            data: contadorPermisosEncontrados
        });


    } catch (e) {
        console.log(e)
        res.status(500).send({
            message: e.name
        });
    }
}


async function obtenerPermisosRevisadosParaTTHH(req, res) {
    try {
        let buscar = req.body.palabra;
        let limit = req.body.tamanioLote;
        let offset = req.body.numeroPagina;
        let mul = limit * offset;

        if (mul == 0) {
            mul = offset;
        }

        const permisosEncontrados = await Permiso.findAll({
            where: {
                [Op.and]: [
                    { ESTADO: { [Op.in]: [3, 5] } },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: USUARIO_ATTRIBUTES,
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: HISTORIAL_ATTRIBUTES,
                            include: [
                                {
                                    model: Cargo,
                                    required: true,
                                    attributes: CARGO_ATTRIBUTES,
                                    include: [
                                        {
                                            model: Area,
                                            attributes: AREA_ATTRIBUTES
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                },
                {
                    model: Tipo_Permiso,
                    as: 'TIPO_PERMISO',
                    attributes: TIPO_PERMISO_ATTRIBUTES
                }
            ],
            subQuery: false,
            offset: mul,
            limit: limit,
            order: [['ID_PERMISO', 'DESC']]
        });
        res.status(200).send({
            data: agregarInfoVacaciones(permisosEncontrados)
        });

    } catch (e) {
        console.log(e);
        res.status(500).send({
            message: e.name
        });
    }
}

async function contarTotalPermisosRevisadosParaTTHH(req, res) {
    try {
        let buscar = req.body.palabra;

        const contadorPermisosEncontrados = await Permiso.count({
            where: {
                [Op.and]: [
                    { ESTADO: { [Op.in]: [3, 5] } },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: [],
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: [],
                            include: [
                                {
                                    model: Cargo,
                                    required: true,
                                    attributes: [],
                                    include: [
                                        {
                                            model: Area,
                                            attributes: []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        });

        res.status(200).send({
            data: contadorPermisosEncontrados
        });


    } catch (e) {
        console.log(e)
        res.status(500).send({
            message: e.name
        });
    }
}


async function actualizarPermisoParaTTHH(req, res) {
    try {
        let params = req.body;
        const esCargoVacaciones = params.CARGO_VACACIONES == true || params.CARGO_VACACIONES === 1 || params.CARGO_VACACIONES === '1';
        const diasCargo = parseInt(params.DIAS_CARGO_VACACIONES) || 0;

        let permisoPorActualizar = {
            ESTADO: params.ESTADO,
            APROBADO_POR_ADMINISTRADOR: toUpper(params.APROBADO_POR_ADMINISTRADOR),
            APROBACION_TTHH: false,
            APROBACION_JEFE: false,
            FECHA_REGISTRO: moment.utc(moment().tz('America/Guayaquil').format('YYYY-MM-DD HH:mm:ss')).toDate(),
            CARGO_VACACIONES: esCargoVacaciones,
            DIAS_CARGO_VACACIONES: diasCargo,
            RAZON_CARGO_VACACIONES: toUpper(params.RAZON_CARGO_VACACIONES) || null,
        }

        let permisoActualizado = await Permiso.update(permisoPorActualizar, { where: { ID_PERMISO: req.params.id } });

        if (permisoActualizado) {
            // Obtener el permiso para notificación y cargo a vacaciones en una sola query
            const permisoGuardado = await Permiso.findOne({
                where: { ID_PERMISO: req.params.id },
                attributes: ['ID_USUARIO', 'ESTADO']
            });

            // Si es cargo a vacaciones, descontar días del usuario
            if (esCargoVacaciones && diasCargo > 0 && permisoGuardado) {
                const usuario = await Usuario.findOne({
                    where: { ID_USUARIO: permisoGuardado.ID_USUARIO },
                    attributes: ['ID_USUARIO', 'DIAS_VACACIONES']
                });
                if (usuario) {
                    const diasActuales = parseInt(usuario.DIAS_VACACIONES) || 0;
                    await Usuario.update(
                        { DIAS_VACACIONES: diasActuales - diasCargo },
                        { where: { ID_USUARIO: permisoGuardado.ID_USUARIO } }
                    );
                }
            }

            // Notificar al usuario via push
            if (permisoGuardado) {
                Notificacion.notificarUsuarioEstadoPermiso(permisoGuardado.ID_USUARIO, params.ESTADO);
            }

            res.status(200).send({
                message: 'Transaccion realizada exitosamente',
            });
        } else {
            res.status(402).send({
                message: 'No se ha podido actualizar el permiso'
            });
        }

    } catch (e) {
        console.log(e)
        res.status(500).send({
            message: e.name
        });
    }
}


// gerente

async function obtenerPermisosParaGerente(req, res) {
    try {
        let buscar = req.body.palabra;
        let limit = req.body.tamanioLote;
        let offset = req.body.numeroPagina;
        let mul = limit * offset;

        if (mul == 0) {
            mul = offset;
        }

        const permisosEncontrados = await Permiso.findAll({
            where: {
                [Op.and]: [
                    { ESTADO: { [Op.in]: [3, 10] } },  // 3=aprobado TTHH pendiente gerente, 10=pendiente gerente directo
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: USUARIO_ATTRIBUTES,
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: HISTORIAL_ATTRIBUTES,
                            include: [
                                {
                                    model: Cargo,
                                    required: true,
                                    attributes: CARGO_ATTRIBUTES,
                                    include: [{ model: Area, attributes: AREA_ATTRIBUTES }]
                                }
                            ]
                        }
                    ]
                },
                {
                    model: Tipo_Permiso,
                    as: 'TIPO_PERMISO',
                    attributes: TIPO_PERMISO_ATTRIBUTES
                }
            ],
            subQuery: false,
            offset: mul,
            limit: limit,
            order: [['ID_PERMISO', 'DESC']]
        });

        res.status(200).send({
            data: agregarInfoVacaciones(permisosEncontrados)
        });

    } catch (e) {
        console.log(e);
        res.status(500).send({ message: e.name });
    }
}

async function contarTotalPermisosParaGerente(req, res) {
    try {
        let buscar = req.body.palabra;

        const contadorPermisosEncontrados = await Permiso.count({
            where: {
                [Op.and]: [
                    { ESTADO: { [Op.in]: [3, 10] } },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: [],
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: [],
                            include: [{ model: Cargo, required: true, attributes: [] }]
                        }
                    ]
                }
            ]
        });

        res.status(200).send({ data: contadorPermisosEncontrados });

    } catch (e) {
        console.log(e);
        res.status(500).send({ message: e.name });
    }
}

async function actualizarPermisoParaGerente(req, res) {
    try {
        let params = req.body;

        let permisoPorActualizar = {
            ESTADO: params.ESTADO,
            APROBADO_POR_GERENTE: params.APROBADO_POR_GERENTE,
            APROBACION_GERENTE: false,
            FECHA_REGISTRO: moment.utc(moment().tz('America/Guayaquil').format('YYYY-MM-DD HH:mm:ss')).toDate()
        };

        let permisoActualizado = await Permiso.update(permisoPorActualizar, { where: { ID_PERMISO: req.params.id } });

        if (permisoActualizado) {
            const permiso = await Permiso.findOne({ where: { ID_PERMISO: req.params.id }, attributes: ['ID_USUARIO', 'ESTADO'] });
            if (permiso) {
                Notificacion.notificarUsuarioEstadoPermiso(permiso.ID_USUARIO, params.ESTADO);
            }

            res.status(200).send({ message: 'Transaccion realizada exitosamente' });
        } else {
            res.status(402).send({ message: 'No se ha podido actualizar el permiso' });
        }

    } catch (e) {
        console.log(e);
        res.status(500).send({ message: e.name });
    }
}


async function obtenerPermisosRevisadosParaGerente(req, res) {
    try {
        let buscar = req.body.palabra;
        let limit = req.body.tamanioLote;
        let offset = req.body.numeroPagina;
        let mul = limit * offset;
        if (mul == 0) { mul = offset; }

        const permisosEncontrados = await Permiso.findAll({
            where: {
                [Op.and]: [
                    { ESTADO: { [Op.in]: [11, 12, 13] } },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: USUARIO_ATTRIBUTES,
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: HISTORIAL_ATTRIBUTES,
                            include: [
                                {
                                    model: Cargo,
                                    required: true,
                                    attributes: CARGO_ATTRIBUTES,
                                    include: [{ model: Area, attributes: AREA_ATTRIBUTES }]
                                }
                            ]
                        }
                    ]
                },
                { model: Tipo_Permiso, as: 'TIPO_PERMISO', attributes: TIPO_PERMISO_ATTRIBUTES }
            ],
            subQuery: false,
            offset: mul,
            limit: limit,
            order: [['ID_PERMISO', 'DESC']]
        });

        res.status(200).send({ data: agregarInfoVacaciones(permisosEncontrados) });
    } catch (e) {
        console.log(e);
        res.status(500).send({ message: e.name });
    }
}

async function contarTotalPermisosRevisadosParaGerente(req, res) {
    try {
        let buscar = req.body.palabra;

        const contadorPermisosEncontrados = await Permiso.count({
            where: {
                [Op.and]: [
                    { ESTADO: { [Op.in]: [11, 12, 13] } },
                    {
                        [Op.or]: [
                            { DETALLE_PERMISO: { [Op.substring]: buscar || "" } },
                            { '$USUARIO.NOMBRES$': { [Op.substring]: buscar || "" } },
                            { '$USUARIO.APELLIDOS$': { [Op.substring]: buscar || "" } }
                        ]
                    }
                ]
            },
            include: [
                {
                    model: Usuario,
                    required: true,
                    attributes: [],
                    include: [
                        {
                            model: Historial_Empresa,
                            as: 'HISTORIAL_EMPRESA',
                            attributes: [],
                            include: [{ model: Cargo, required: true, attributes: [] }]
                        }
                    ]
                }
            ]
        });

        res.status(200).send({ data: contadorPermisosEncontrados });
    } catch (e) {
        console.log(e);
        res.status(500).send({ message: e.name });
    }
}


module.exports = {

    obtenerTiposPermiso,
    registrarPermiso,
    obtenerPermisos,
    contarTotalPermisos,
    obtenerPermiso,
    actualizarPermiso,
    eliminarPermiso,
    registrarEvidencia,

    //jefe
    obtenerPermisosPendientesParaJefe,
    contarTotalPermisosPendientesParaJefe,
    obtenerPermisosRevisadosParaJefe,
    contarTotalPermisosRevisadosParaJefe,
    actualizarPermisoParaJefe,

    //tthh
    obtenerPermisosPendientesParaTTHH,
    contarTotalPermisosPendientesParaTTHH,
    obtenerPermisosRevisadosParaTTHH,
    contarTotalPermisosRevisadosParaTTHH,
    actualizarPermisoParaTTHH,

    //gerente
    obtenerPermisosParaGerente,
    contarTotalPermisosParaGerente,
    obtenerPermisosRevisadosParaGerente,
    contarTotalPermisosRevisadosParaGerente,
    actualizarPermisoParaGerente,

}
