const { Menu, MenuCategory } = require('../models/associations');
const { Op } = require('sequelize');

const menuController = {
    // Get all menus with pagination and filters
    getAllMenus: async (req, res) => {
        try {
            const {
                page = 1,
                limit = 10,
                categorie_id,
                disponible,
                prix_min,
                prix_max,
                search,
                sort_by = 'nom',
                sort_order = 'ASC'
            } = req.query;

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

            // Apply filters
            if (categorie_id) {
                whereClause.categorie_id = categorie_id;
            }

            if (disponible !== undefined) {
                whereClause.disponible = disponible === 'true';
            }

            if (prix_min || prix_max) {
                whereClause.prix = {};
                if (prix_min) whereClause.prix[Op.gte] = parseFloat(prix_min);
                if (prix_max) whereClause.prix[Op.lte] = parseFloat(prix_max);
            }

            if (search) {
                whereClause[Op.or] = [
                    { nom: { [Op.like]: `%${search}%` } },
                    { commentaire: { [Op.like]: `%${search}%` } },
                    { ingredients: { [Op.like]: `%${search}%` } }
                ];
            }

            const { count, rows } = await Menu.findAndCountAll({
                where: whereClause,
                include: [{
                    model: MenuCategory,
                    as: 'category',
                    attributes: ['id', 'nom', 'description']
                }],
                limit: parseInt(limit),
                offset: offset,
                order: [[sort_by, sort_order.toUpperCase()]],
                distinct: true
            });

            const totalPages = Math.ceil(count / parseInt(limit));

            res.json({
                success: true,
                data: {
                    menus: rows,
                    pagination: {
                        currentPage: parseInt(page),
                        totalPages,
                        totalItems: count,
                        itemsPerPage: parseInt(limit)
                    }
                }
            });

        } catch (error) {
            console.error('Error fetching menus:', error);
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la récupération des menus',
                error: error.message
            });
        }
    },

    // Get menu by ID
    getMenuById: async (req, res) => {
        try {
            const { id } = req.params;

            if (!id || isNaN(id)) {
                return res.status(400).json({
                    success: false,
                    message: 'ID de menu invalide'
                });
            }

            const menu = await Menu.findByPk(id, {
                include: [{
                    model: MenuCategory,
                    as: 'category',
                    attributes: ['id', 'nom', 'description']
                }]
            });

            if (!menu) {
                return res.status(404).json({
                    success: false,
                    message: 'Menu non trouvé'
                });
            }

            res.json({
                success: true,
                data: menu
            });

        } catch (error) {
            console.error('Error fetching menu:', error);
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la récupération du menu',
                error: error.message
            });
        }
    },

    // Get menus by category
    getMenusByCategory: async (req, res) => {
        try {
            const { categoryId } = req.params;
            const { disponible_only = 'false' } = req.query;

            const whereClause = { categorie_id: categoryId };
            if (disponible_only === 'true') {
                whereClause.disponible = true;
            }

            const menus = await Menu.findAll({
                where: whereClause,
                include: [{
                    model: MenuCategory,
                    as: 'category',
                    attributes: ['id', 'nom', 'description']
                }],
                order: [['nom', 'ASC']]
            });

            res.json({
                success: true,
                data: menus,
                count: menus.length
            });

        } catch (error) {
            console.error('Error fetching menus by category:', error);
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la récupération des menus par catégorie',
                error: error.message
            });
        }
    },

    // Create new menu
    createMenu: async (req, res) => {
        try {
            const {
                nom,
                commentaire,
                prix,
                categorie_id,
                disponible = true,
                image_url,
                ingredients,
                allergenes,
                calories,
                temps_preparation
            } = req.body;

            // Validate required fields
            if (!nom || !prix || !categorie_id) {
                return res.status(400).json({
                    success: false,
                    message: 'Les champs nom, prix et categorie_id sont requis'
                });
            }

            // Check if category exists
            const category = await MenuCategory.findByPk(categorie_id);
            if (!category) {
                return res.status(400).json({
                    success: false,
                    message: 'Catégorie non trouvée'
                });
            }

            const newMenu = await Menu.create({
                nom,
                commentaire,
                prix,
                categorie_id,
                disponible,
                image_url,
                ingredients,
                allergenes,
                calories,
                temps_preparation
            });

            // Fetch the created menu with category info
            const menuWithCategory = await Menu.findByPk(newMenu.id, {
                include: [{
                    model: MenuCategory,
                    as: 'category',
                    attributes: ['id', 'nom', 'description']
                }]
            });

            res.status(201).json({
                success: true,
                message: 'Menu créé avec succès',
                data: menuWithCategory
            });

        } catch (error) {
            console.error('Error creating menu:', error);
            
            if (error.name === 'SequelizeValidationError') {
                return res.status(400).json({
                    success: false,
                    message: 'Erreur de validation',
                    errors: error.errors.map(err => ({
                        field: err.path,
                        message: err.message
                    }))
                });
            }

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

    // Update menu
    updateMenu: async (req, res) => {
        try {
            const { id } = req.params;
            const {
                nom,
                commentaire,
                prix,
                categorie_id,
                disponible,
                image_url,
                ingredients,
                allergenes,
                calories,
                temps_preparation
            } = req.body;

            if (!id || isNaN(id)) {
                return res.status(400).json({
                    success: false,
                    message: 'ID de menu invalide'
                });
            }

            const menu = await Menu.findByPk(id);
            if (!menu) {
                return res.status(404).json({
                    success: false,
                    message: 'Menu non trouvé'
                });
            }

            // Check if new category exists
            if (categorie_id && categorie_id !== menu.categorie_id) {
                const category = await MenuCategory.findByPk(categorie_id);
                if (!category) {
                    return res.status(400).json({
                        success: false,
                        message: 'Catégorie non trouvée'
                    });
                }
            }

            await menu.update({
                nom: nom !== undefined ? nom : menu.nom,
                commentaire: commentaire !== undefined ? commentaire : menu.commentaire,
                prix: prix !== undefined ? prix : menu.prix,
                categorie_id: categorie_id !== undefined ? categorie_id : menu.categorie_id,
                disponible: disponible !== undefined ? disponible : menu.disponible,
                image_url: image_url !== undefined ? image_url : menu.image_url,
                ingredients: ingredients !== undefined ? ingredients : menu.ingredients,
                allergenes: allergenes !== undefined ? allergenes : menu.allergenes,
                calories: calories !== undefined ? calories : menu.calories,
                temps_preparation: temps_preparation !== undefined ? temps_preparation : menu.temps_preparation
            });

            // Fetch updated menu with category
            const updatedMenu = await Menu.findByPk(id, {
                include: [{
                    model: MenuCategory,
                    as: 'category',
                    attributes: ['id', 'nom', 'description']
                }]
            });

            res.json({
                success: true,
                message: 'Menu mis à jour avec succès',
                data: updatedMenu
            });

        } catch (error) {
            console.error('Error updating menu:', error);
            
            if (error.name === 'SequelizeValidationError') {
                return res.status(400).json({
                    success: false,
                    message: 'Erreur de validation',
                    errors: error.errors.map(err => ({
                        field: err.path,
                        message: err.message
                    }))
                });
            }

            res.status(500).json({
                success: false,
                message: 'Erreur lors de la mise à jour du menu',
                error: error.message
            });
        }
    },

    // Update menu availability
    updateMenuAvailability: async (req, res) => {
        try {
            const { id } = req.params;
            const { disponible } = req.body;

            if (!id || isNaN(id)) {
                return res.status(400).json({
                    success: false,
                    message: 'ID de menu invalide'
                });
            }

            if (typeof disponible !== 'boolean') {
                return res.status(400).json({
                    success: false,
                    message: 'Le champ disponible doit être un booléen'
                });
            }

            const menu = await Menu.findByPk(id);
            if (!menu) {
                return res.status(404).json({
                    success: false,
                    message: 'Menu non trouvé'
                });
            }

            await menu.update({ disponible });

            res.json({
                success: true,
                message: `Menu ${disponible ? 'activé' : 'désactivé'} avec succès`,
                data: { id: menu.id, disponible }
            });

        } catch (error) {
            console.error('Error updating menu availability:', error);
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la mise à jour de la disponibilité',
                error: error.message
            });
        }
    },

    // Delete menu
    deleteMenu: async (req, res) => {
        try {
            const { id } = req.params;

            if (!id || isNaN(id)) {
                return res.status(400).json({
                    success: false,
                    message: 'ID de menu invalide'
                });
            }

            const menu = await Menu.findByPk(id);
            if (!menu) {
                return res.status(404).json({
                    success: false,
                    message: 'Menu non trouvé'
                });
            }

            await menu.destroy();

            res.json({
                success: true,
                message: 'Menu supprimé avec succès'
            });

        } catch (error) {
            console.error('Error deleting menu:', error);
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la suppression du menu',
                error: error.message
            });
        }
    },

    // Get menu statistics
    getMenuStats: async (req, res) => {
        try {
            const totalMenus = await Menu.count();
            const availableMenus = await Menu.count({ where: { disponible: true } });
            const unavailableMenus = await Menu.count({ where: { disponible: false } });
            
            const menusByCategory = await Menu.findAll({
                attributes: [
                    'categorie_id',
                    [Menu.sequelize.fn('COUNT', Menu.sequelize.col('id')), 'count']
                ],
                include: [{
                    model: MenuCategory,
                    as: 'category',
                    attributes: ['nom']
                }],
                group: ['categorie_id', 'category.id'],
                raw: false
            });

            const priceStats = await Menu.findOne({
                attributes: [
                    [Menu.sequelize.fn('MIN', Menu.sequelize.col('prix')), 'min_prix'],
                    [Menu.sequelize.fn('MAX', Menu.sequelize.col('prix')), 'max_prix'],
                    [Menu.sequelize.fn('AVG', Menu.sequelize.col('prix')), 'avg_prix']
                ],
                raw: true
            });

            res.json({
                success: true,
                data: {
                    total: totalMenus,
                    disponible: availableMenus,
                    non_disponible: unavailableMenus,
                    by_category: menusByCategory,
                    price_stats: {
                        min_price: parseFloat(priceStats.min_prix) || 0,
                        max_price: parseFloat(priceStats.max_prix) || 0,
                        avg_price: parseFloat(priceStats.avg_prix) || 0
                    }
                }
            });

        } catch (error) {
            console.error('Error fetching menu statistics:', error);
            res.status(500).json({
                success: false,
                message: 'Erreur lors de la récupération des statistiques',
                error: error.message
            });
        }
    }
};

module.exports = menuController;
