const { Op } = require('sequelize');
const moment = require('moment-timezone');
const Horario = require('../models/horario');
const TramoHorario = require('../models/tramo_horario');
const UsuarioHorario = require('../models/usuario_horario');
const Usuario = require('../models/usuario');

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

        const horariosEncontrados = await Horario.findAll({
            where: {
                NOMBRE_HORARIO: { [Op.substring]: buscar }
            },
            include: [
                {
                    model: TramoHorario,
                    as: 'TRAMOS',
                    required: false
                }
            ],
            offset: mul,
            limit: limit,
            order: [['FECHA_REGISTRO', 'DESC']]
        });

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

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

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

        const total = await Horario.count({
            where: {
                NOMBRE_HORARIO: { [Op.substring]: buscar }
            }
        });

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

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

async function registrarHorario(req, res) {
    try {
        const entidad = req.body;

        const horario = Horario.build();
        horario.NOMBRE_HORARIO = entidad.NOMBRE_HORARIO;
        horario.FECHA_INICIO = entidad.FECHA_INICIO;
        horario.FECHA_FIN = entidad.FECHA_FIN || null;
        horario.REQUIERE_MARCACION_ALMUERZO = entidad.REQUIERE_MARCACION_ALMUERZO || 0;
        // NO_ANCLADO eliminado - ya no se usa
        horario.OBSERVACION = entidad.OBSERVACION || null;
        horario.ESTADO = 1;
        horario.FECHA_REGISTRO = moment.utc(moment().tz('America/Guayaquil').format('YYYY-MM-DD HH:mm:ss')).toDate();

        const guardado = await horario.save();

        if (guardado && entidad.TRAMOS && entidad.TRAMOS.length > 0) {
            for (let i = 0; i < entidad.TRAMOS.length; i++) {
                const tramo = TramoHorario.build();
                tramo.ID_HORARIO = guardado.ID_HORARIO;
                tramo.HORA_INICIO = entidad.TRAMOS[i].HORA_INICIO;
                tramo.HORA_FIN = entidad.TRAMOS[i].HORA_FIN;
                tramo.ORDEN = i + 1;
                await tramo.save();
            }
        }

        res.status(200).send({
            message: 'Horario registrado exitosamente',
            data: guardado
        });

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

async function actualizarHorario(req, res) {
    try {
        const idHorario = req.params.idHorario;
        const entidad = req.body;

        const horario = await Horario.findOne({
            where: { ID_HORARIO: idHorario }
        });

        if (!horario) {
            return res.status(404).send({ message: 'Horario no encontrado' });
        }

        horario.NOMBRE_HORARIO = entidad.NOMBRE_HORARIO;
        horario.FECHA_INICIO = entidad.FECHA_INICIO;
        horario.FECHA_FIN = entidad.FECHA_FIN || null;
        horario.REQUIERE_MARCACION_ALMUERZO = entidad.REQUIERE_MARCACION_ALMUERZO || 0;
        // NO_ANCLADO eliminado - ya no se usa
        horario.OBSERVACION = entidad.OBSERVACION || null;

        await horario.save();

        await TramoHorario.destroy({
            where: { ID_HORARIO: idHorario }
        });

        if (entidad.TRAMOS && entidad.TRAMOS.length > 0) {
            for (let i = 0; i < entidad.TRAMOS.length; i++) {
                const tramo = TramoHorario.build();
                tramo.ID_HORARIO = idHorario;
                tramo.HORA_INICIO = entidad.TRAMOS[i].HORA_INICIO;
                tramo.HORA_FIN = entidad.TRAMOS[i].HORA_FIN;
                tramo.ORDEN = i + 1;
                await tramo.save();
            }
        }

        res.status(200).send({ message: 'Horario actualizado exitosamente' });

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

async function eliminarHorario(req, res) {
    try {
        const idHorario = req.params.idHorario;

        const eliminado = await Horario.destroy({
            where: { ID_HORARIO: idHorario }
        });

        if (eliminado > 0) {
            res.status(200).send({ message: 'Horario eliminado exitosamente' });
        } else {
            res.status(404).send({ message: 'Horario no encontrado' });
        }

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

async function asignarHorarioUsuarios(req, res) {
    try {
        const entidad = req.body;
        const idHorario = entidad.ID_HORARIO;
        const idsUsuarios = entidad.IDS_USUARIOS;

        if (!idsUsuarios || idsUsuarios.length === 0) {
            return res.status(400).send({ message: 'Debe seleccionar al menos un usuario' });
        }

        await UsuarioHorario.update(
            { ESTADO: 0 },
            { where: { ID_USUARIO: { [Op.in]: idsUsuarios } } }
        );

        for (const idUsuario of idsUsuarios) {
            const usuarioHorario = UsuarioHorario.build();
            usuarioHorario.ID_USUARIO = idUsuario;
            usuarioHorario.ID_HORARIO = idHorario;
            usuarioHorario.FECHA_ASIGNACION = moment().format('YYYY-MM-DD');
            usuarioHorario.ESTADO = 1;
            usuarioHorario.FECHA_REGISTRO = moment.utc(moment().tz('America/Guayaquil').format('YYYY-MM-DD HH:mm:ss')).toDate();
            await usuarioHorario.save();
        }

        res.status(200).send({ message: 'Horarios asignados exitosamente' });

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

async function obtenerUsuariosConHorario(req, res) {
    try {
        const idHorario = req.params.idHorario;

        const usuariosConHorario = await UsuarioHorario.findAll({
            where: {
                ID_HORARIO: idHorario,
                ESTADO: 1
            },
            include: [
                {
                    model: Usuario,
                    as: 'USUARIO',
                    required: true,
                    where: { ESTADO: 1 }
                }
            ]
        });

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

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

async function obtenerHorarioUsuario(req, res) {
    try {
        const idUsuario = req.params.idUsuario;

        const horarioActivo = await UsuarioHorario.findOne({
            where: {
                ID_USUARIO: idUsuario,
                ESTADO: 1
            },
            include: [
                {
                    model: Horario,
                    as: 'HORARIO',
                    required: true,
                    include: [
                        {
                            model: TramoHorario,
                            as: 'TRAMOS',
                            required: false
                        }
                    ]
                }
            ]
        });

        if (!horarioActivo) {
            return res.status(404).send({ message: 'Usuario sin horario asignado' });
        }

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

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

async function obtenerUsuariosConAreas(req, res) {
    try {
        const HistorialEmpresa = require('../models/historial_empresa');
        const Cargo = require('../models/cargo');
        const Area = require('../models/area');

        const usuarios = await Usuario.findAll({
            where: { ESTADO: 1 },
            attributes: ['ID_USUARIO', 'NOMBRES', 'APELLIDOS', 'IDENTIFICACION', 'ESTADO'],
            include: [
                {
                    model: HistorialEmpresa,
                    as: 'HISTORIAL_EMPRESA',
                    attributes: ['ID_CARGO'],
                    where: { ESTADO: 1 },
                    required: false,
                    include: [
                        {
                            model: Cargo,
                            attributes: ['ID_AREA'],
                            required: false,
                            include: [
                                {
                                    model: Area,
                                    attributes: ['ID_AREA', 'DESCRIPCION'],
                                    required: false
                                }
                            ]
                        }
                    ]
                }
            ],
            order: [['NOMBRES', 'ASC']]
        });

        const usuariosFormateados = usuarios.map(usuario => {
            const usuarioJSON = usuario.toJSON();
            const historialActivo = usuarioJSON.HISTORIAL_EMPRESA && usuarioJSON.HISTORIAL_EMPRESA.length > 0
                ? usuarioJSON.HISTORIAL_EMPRESA[0]
                : null;

            return {
                ID_USUARIO: usuarioJSON.ID_USUARIO,
                NOMBRES: usuarioJSON.NOMBRES,
                APELLIDOS: usuarioJSON.APELLIDOS,
                IDENTIFICACION: usuarioJSON.IDENTIFICACION,
                ESTADO: usuarioJSON.ESTADO,
                ID_AREA: historialActivo && historialActivo.CARGO && historialActivo.CARGO.AREA
                    ? historialActivo.CARGO.AREA.ID_AREA
                    : null,
                NOMBRE_AREA: historialActivo && historialActivo.CARGO && historialActivo.CARGO.AREA
                    ? historialActivo.CARGO.AREA.DESCRIPCION
                    : null
            };
        });

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

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

module.exports = {
    obtenerHorarios,
    contarTotalHorarios,
    registrarHorario,
    actualizarHorario,
    eliminarHorario,
    asignarHorarioUsuarios,
    obtenerUsuariosConHorario,
    obtenerHorarioUsuario,
    obtenerUsuariosConAreas
};
