const { Reservation, Client, Table } = require('../models/associations');
const { Op } = require('sequelize');

class ReservationController {
    // Get all reservations
    async getAllReservations(req, res) {
        try {
            const {
                page = 1,
                limit = 10,
                statut,
                date_debut,
                date_fin,
                table_id,
                sort_by = 'date_reservation',
                sort_order = 'ASC'
            } = req.query;

            const offset = (parseInt(page) - 1) * parseInt(limit);
            const whereClause = {};

            // Status filter
            if (statut) {
                whereClause.statut = statut;
            }

            // Date range filter
            if (date_debut && date_fin) {
                whereClause.date_reservation = {
                    [Op.between]: [new Date(date_debut), new Date(date_fin)]
                };
            } else if (date_debut) {
                whereClause.date_reservation = {
                    [Op.gte]: new Date(date_debut)
                };
            } else if (date_fin) {
                whereClause.date_reservation = {
                    [Op.lte]: new Date(date_fin)
                };
            }

            // Table filter
            if (table_id) {
                whereClause.table_id = table_id;
            }

            const { count, rows } = await Reservation.findAndCountAll({
                where: whereClause,
                include: [
                    {
                        model: Client,
                        as: 'client',
                        attributes: ['nom', 'prenom', 'email', 'telephone']
                    },
                    {
                        model: Table,
                        as: 'table',
                        attributes: ['nom', 'capacity', 'location']
                    }
                ],
                limit: parseInt(limit),
                offset: offset,
                order: [[sort_by, sort_order.toUpperCase()]]
            });

            res.json({
                success: true,
                data: {
                    reservations: rows,
                    pagination: {
                        currentPage: parseInt(page),
                        totalPages: Math.ceil(count / parseInt(limit)),
                        totalItems: count,
                        itemsPerPage: parseInt(limit)
                    }
                }
            });
        } catch (error) {
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la récupération des réservations',
                error: error.message
            });
        }
    }

    // Get reservation by ID
    async getReservationById(req, res) {
        try {
            const { id } = req.params;

            const reservation = await Reservation.findByPk(id, {
                include: [
                    {
                        model: Client,
                        as: 'client',
                        attributes: ['nom', 'prenom', 'email', 'telephone']
                    },
                    {
                        model: Table,
                        as: 'table',
                        attributes: ['nom', 'capacity', 'location']
                    },
                    {
                        association: 'commandes'
                    }
                ]
            });

            if (!reservation) {
                return res.status(404).json({
                    success: false,
                    message: 'Réservation non trouvée'
                });
            }

            res.json({
                success: true,
                data: reservation
            });
        } catch (error) {
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la récupération de la réservation',
                error: error.message
            });
        }
    }

    // Create new reservation
    async createReservation(req, res) {
        try {
            const reservationData = req.body;

            // Check table availability
            const existingReservation = await Reservation.findOne({
                where: {
                    table_id: reservationData.table_id,
                    date_reservation: {
                        [Op.between]: [
                            new Date(new Date(reservationData.date_reservation).getTime() - 2 * 60 * 60 * 1000),
                            new Date(new Date(reservationData.date_reservation).getTime() + 2 * 60 * 60 * 1000)
                        ]
                    },
                    statut: {
                        [Op.in]: ['confirmee', 'en_attente']
                    }
                }
            });

            if (existingReservation) {
                return res.status(400).json({
                    success: false,
                    message: 'Table déjà réservée à cette heure'
                });
            }

            // Check table capacity
            const table = await Table.findByPk(reservationData.table_id);
            if (!table) {
                return res.status(404).json({
                    success: false,
                    message: 'Table non trouvée'
                });
            }

            if (reservationData.nombre_personnes > table.capacity) {
                return res.status(400).json({
                    success: false,
                    message: 'Nombre de personnes supérieur à la capacité de la table'
                });
            }

            const reservation = await Reservation.create(reservationData);

            // Include related data in response
            const createdReservation = await Reservation.findByPk(reservation.id, {
                include: [
                    {
                        model: Client,
                        as: 'client',
                        attributes: ['nom', 'prenom', 'email', 'telephone']
                    },
                    {
                        model: Table,
                        as: 'table',
                        attributes: ['nom', 'capacity', 'location']
                    }
                ]
            });

            res.status(201).json({
                success: true,
                message: 'Réservation créée avec succès',
                data: createdReservation
            });
        } catch (error) {
            if (error.name === 'SequelizeValidationError') {
                return res.status(400).json({
                    success: false,
                    message: 'Données invalides',
                    errors: error.errors.map(e => ({
                        field: e.path,
                        message: e.message
                    }))
                });
            }

            res.status(500).json({
                success: false,
                message: 'Erreur lors de la création de la réservation',
                error: error.message
            });
        }
    }

    // Update reservation
    async updateReservation(req, res) {
        try {
            const { id } = req.params;
            const updateData = req.body;

            const reservation = await Reservation.findByPk(id);
            if (!reservation) {
                return res.status(404).json({
                    success: false,
                    message: 'Réservation non trouvée'
                });
            }

            await reservation.update(updateData);

            const updatedReservation = await Reservation.findByPk(id, {
                include: [
                    {
                        model: Client,
                        as: 'client',
                        attributes: ['nom', 'prenom', 'email', 'telephone']
                    },
                    {
                        model: Table,
                        as: 'table',
                        attributes: ['nom', 'capacity', 'location']
                    }
                ]
            });

            res.json({
                success: true,
                message: 'Réservation mise à jour avec succès',
                data: updatedReservation
            });
        } catch (error) {
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la mise à jour de la réservation',
                error: error.message
            });
        }
    }

    // Delete reservation
    async deleteReservation(req, res) {
        try {
            const { id } = req.params;

            const reservation = await Reservation.findByPk(id);
            if (!reservation) {
                return res.status(404).json({
                    success: false,
                    message: 'Réservation non trouvée'
                });
            }

            await reservation.destroy();

            res.json({
                success: true,
                message: 'Réservation supprimée avec succès'
            });
        } catch (error) {
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la suppression de la réservation',
                error: error.message
            });
        }
    }

    // Get reservations by status
    async getReservationsByStatus(req, res) {
        try {
            const { status } = req.params;
            const { page = 1, limit = 10 } = req.query;

            const offset = (parseInt(page) - 1) * parseInt(limit);

            const { count, rows } = await Reservation.findAndCountAll({
                where: { statut: status },
                include: [
                    {
                        model: Client,
                        as: 'client',
                        attributes: ['nom', 'prenom', 'email', 'telephone']
                    },
                    {
                        model: Table,
                        as: 'table',
                        attributes: ['nom', 'capacity', 'location']
                    }
                ],
                limit: parseInt(limit),
                offset: offset,
                order: [['date_reservation', 'ASC']]
            });

            res.json({
                success: true,
                data: {
                    reservations: rows,
                    pagination: {
                        currentPage: parseInt(page),
                        totalPages: Math.ceil(count / parseInt(limit)),
                        totalItems: count,
                        itemsPerPage: parseInt(limit)
                    }
                }
            });
        } catch (error) {
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la récupération des réservations',
                error: error.message
            });
        }
    }

    // Get today's reservations
    async getTodayReservations(req, res) {
        try {
            const today = new Date();
            const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate());
            const endOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);

            const reservations = await Reservation.findAll({
                where: {
                    date_reservation: {
                        [Op.between]: [startOfDay, endOfDay]
                    }
                },
                include: [
                    {
                        model: Client,
                        as: 'client',
                        attributes: ['nom', 'prenom', 'email', 'telephone']
                    },
                    {
                        model: Table,
                        as: 'table',
                        attributes: ['nom', 'capacity', 'location']
                    }
                ],
                order: [['date_reservation', 'ASC']]
            });

            res.json({
                success: true,
                data: reservations
            });
        } catch (error) {
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la récupération des réservations du jour',
                error: error.message
            });
        }
    }

    // Get reservation statistics
    async getReservationStats(req, res) {
        try {
            const total = await Reservation.count();
            const confirmees = await Reservation.count({ where: { statut: 'confirmee' } });
            const en_attente = await Reservation.count({ where: { statut: 'en_attente' } });
            const annulees = await Reservation.count({ where: { statut: 'annulee' } });
            const terminees = await Reservation.count({ where: { statut: 'terminee' } });

            const today = new Date();
            const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate());
            const endOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);

            const todayCount = await Reservation.count({
                where: {
                    date_reservation: {
                        [Op.between]: [startOfDay, endOfDay]
                    }
                }
            });

            res.json({
                success: true,
                data: {
                    total,
                    confirmees,
                    en_attente,
                    annulees,
                    terminees,
                    todayCount
                }
            });
        } catch (error) {
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la récupération des statistiques',
                error: error.message
            });
        }
    }
}

module.exports = new ReservationController();
