const Table = require('../models/Table');
const { Op } = require('sequelize');

class TableController {
    // Get all tables with optional filtering
    static async getAllTables(req, res) {
        try {
            console.log('🔍 TableController.getAllTables - Début');
            
            const { 
                status, 
                location, 
                capacity_min, 
                capacity_max, 
                page = 1, 
                limit = 10,
                sort = 'id',
                order = 'ASC'
            } = req.query;

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

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

            if (location) {
                whereClause.location = {
                    [Op.like]: `%${location}%`
                };
            }

            if (capacity_min || capacity_max) {
                whereClause.capacity = {};
                if (capacity_min) whereClause.capacity[Op.gte] = parseInt(capacity_min);
                if (capacity_max) whereClause.capacity[Op.lte] = parseInt(capacity_max);
            }

            console.log('Where conditions:', whereClause);

            const { count, rows } = await Table.findAndCountAll({
                where: whereClause,
                limit: parseInt(limit),
                offset: parseInt(offset),
                order: [[sort, order.toUpperCase()]]
            });

            console.log(`✅ Found ${count} tables, returning ${rows.length} tables`);

            res.json({
                success: true,
                data: rows,
                pagination: {
                    total: count,
                    page: parseInt(page),
                    limit: parseInt(limit),
                    totalPages: Math.ceil(count / limit)
                }
            });
        } catch (error) {
            console.error('❌ Error in getAllTables:', error);
            res.status(500).json({
                success: false,
                error: 'Failed to fetch tables',
                message: error.message
            });
        }
    }

    // Get table by ID
    static async getTableById(req, res) {
        try {
            const { id } = req.params;
            
            if (!id || isNaN(id)) {
                return res.status(400).json({
                    success: false,
                    error: 'Valid table ID is required'
                });
            }

            const table = await Table.findByPk(id);

            if (!table) {
                return res.status(404).json({
                    success: false,
                    error: 'Table not found'
                });
            }

            res.json({
                success: true,
                data: table
            });
        } catch (error) {
            console.error('❌ Error in getTableById:', error);
            res.status(500).json({
                success: false,
                error: 'Failed to fetch table',
                message: error.message
            });
        }
    }

    // Create new table
    static async createTable(req, res) {
        try {
            const { nom, capacity, status, location } = req.body;

            // Validation
            if (!nom) {
                return res.status(400).json({
                    success: false,
                    error: 'Table name is required'
                });
            }

            if (nom.length > 100) {
                return res.status(400).json({
                    success: false,
                    error: 'Table name must be less than 100 characters'
                });
            }

            if (capacity && (capacity < 1 || capacity > 20)) {
                return res.status(400).json({
                    success: false,
                    error: 'Capacity must be between 1 and 20'
                });
            }

            if (status && !['available', 'occupied', 'reserved', 'maintenance'].includes(status)) {
                return res.status(400).json({
                    success: false,
                    error: 'Status must be: available, occupied, reserved, or maintenance'
                });
            }

            if (location && location.length > 50) {
                return res.status(400).json({
                    success: false,
                    error: 'Location must be less than 50 characters'
                });
            }

            // Check if table name already exists
            const existingTable = await Table.findOne({
                where: { nom }
            });

            if (existingTable) {
                return res.status(409).json({
                    success: false,
                    error: 'Table name already exists'
                });
            }

            const table = await Table.create({
                nom,
                capacity: capacity || 4,
                status: status || 'available',
                location: location || null
            });

            res.status(201).json({
                success: true,
                data: table,
                message: 'Table created successfully'
            });
        } catch (error) {
            console.error('❌ Error in createTable:', error);
            
            if (error.name === 'SequelizeValidationError') {
                return res.status(400).json({
                    success: false,
                    error: 'Validation error',
                    details: error.errors.map(err => ({
                        field: err.path,
                        message: err.message
                    }))
                });
            }

            if (error.name === 'SequelizeUniqueConstraintError') {
                return res.status(409).json({
                    success: false,
                    error: 'Table name already exists'
                });
            }

            res.status(500).json({
                success: false,
                error: 'Failed to create table',
                message: error.message
            });
        }
    }

    // Update table
    static async updateTable(req, res) {
        try {
            const { id } = req.params;
            const { nom, capacity, status, location } = req.body;

            if (!id || isNaN(id)) {
                return res.status(400).json({
                    success: false,
                    error: 'Valid table ID is required'
                });
            }

            const table = await Table.findByPk(id);

            if (!table) {
                return res.status(404).json({
                    success: false,
                    error: 'Table not found'
                });
            }

            // Validation
            if (nom !== undefined) {
                if (!nom || nom.length === 0) {
                    return res.status(400).json({
                        success: false,
                        error: 'Table name cannot be empty'
                    });
                }

                if (nom.length > 100) {
                    return res.status(400).json({
                        success: false,
                        error: 'Table name must be less than 100 characters'
                    });
                }

                // Check if new name already exists (excluding current table)
                const existingTable = await Table.findOne({
                    where: { 
                        nom,
                        id: { [Op.ne]: id }
                    }
                });

                if (existingTable) {
                    return res.status(409).json({
                        success: false,
                        error: 'Table name already exists'
                    });
                }
            }

            if (capacity !== undefined && (capacity < 1 || capacity > 20)) {
                return res.status(400).json({
                    success: false,
                    error: 'Capacity must be between 1 and 20'
                });
            }

            if (status && !['available', 'occupied', 'reserved', 'maintenance'].includes(status)) {
                return res.status(400).json({
                    success: false,
                    error: 'Status must be: available, occupied, reserved, or maintenance'
                });
            }

            if (location !== undefined && location && location.length > 50) {
                return res.status(400).json({
                    success: false,
                    error: 'Location must be less than 50 characters'
                });
            }

            // Update fields
            const updateData = {};
            if (nom !== undefined) updateData.nom = nom;
            if (capacity !== undefined) updateData.capacity = capacity;
            if (status !== undefined) updateData.status = status;
            if (location !== undefined) updateData.location = location;

            await table.update(updateData);

            res.json({
                success: true,
                data: table,
                message: 'Table updated successfully'
            });
        } catch (error) {
            console.error('❌ Error in updateTable:', error);
            
            if (error.name === 'SequelizeValidationError') {
                return res.status(400).json({
                    success: false,
                    error: 'Validation error',
                    details: error.errors.map(err => ({
                        field: err.path,
                        message: err.message
                    }))
                });
            }

            if (error.name === 'SequelizeUniqueConstraintError') {
                return res.status(409).json({
                    success: false,
                    error: 'Table name already exists'
                });
            }

            res.status(500).json({
                success: false,
                error: 'Failed to update table',
                message: error.message
            });
        }
    }

    // Delete table
    static async deleteTable(req, res) {
        try {
            const { id } = req.params;
            
            if (!id || isNaN(id)) {
                return res.status(400).json({
                    success: false,
                    error: 'Valid table ID is required'
                });
            }

            const table = await Table.findByPk(id);

            if (!table) {
                return res.status(404).json({
                    success: false,
                    error: 'Table not found'
                });
            }

            // Check if table is currently occupied or reserved
            if (table.status === 'occupied' || table.status === 'reserved') {
                return res.status(400).json({
                    success: false,
                    error: 'Cannot delete table that is currently occupied or reserved'
                });
            }

            await table.destroy();

            res.json({
                success: true,
                message: 'Table deleted successfully'
            });
        } catch (error) {
            console.error('❌ Error in deleteTable:', error);
            res.status(500).json({
                success: false,
                error: 'Failed to delete table',
                message: error.message
            });
        }
    }

    // Get tables by status
    static async getTablesByStatus(req, res) {
        try {
            const { status } = req.params;
            
            const validStatuses = ['available', 'occupied', 'reserved', 'maintenance'];
            if (!validStatuses.includes(status)) {
                return res.status(400).json({
                    success: false,
                    error: `Invalid status. Must be: ${validStatuses.join(', ')}`
                });
            }

            const tables = await Table.findAll({
                where: { status },
                order: [['nom', 'ASC']]
            });

            res.json({
                success: true,
                data: tables,
                count: tables.length
            });
        } catch (error) {
            console.error('❌ Error in getTablesByStatus:', error);
            res.status(500).json({
                success: false,
                error: 'Failed to fetch tables by status',
                message: error.message
            });
        }
    }

    // Update table status
    static async updateTableStatus(req, res) {
        try {
            const { id } = req.params;
            const { status } = req.body;

            if (!id || isNaN(id)) {
                return res.status(400).json({
                    success: false,
                    error: 'Valid table ID is required'
                });
            }

            const validStatuses = ['available', 'occupied', 'reserved', 'maintenance'];
            if (!status || !validStatuses.includes(status)) {
                return res.status(400).json({
                    success: false,
                    error: `Valid status is required (${validStatuses.join(', ')})`
                });
            }

            const table = await Table.findByPk(id);

            if (!table) {
                return res.status(404).json({
                    success: false,
                    error: 'Table not found'
                });
            }

            const oldStatus = table.status;
            await table.update({ status });

            res.json({
                success: true,
                data: table,
                message: `Table status updated from ${oldStatus} to ${status}`
            });
        } catch (error) {
            console.error('❌ Error in updateTableStatus:', error);
            res.status(500).json({
                success: false,
                error: 'Failed to update table status',
                message: error.message
            });
        }
    }

    // Get table statistics
    static async getTableStats(req, res) {
        try {
            const totalTables = await Table.count();

            const statusStats = await Table.findAll({
                attributes: [
                    'status',
                    [Table.sequelize.fn('COUNT', Table.sequelize.col('status')), 'count']
                ],
                group: ['status'],
                raw: true
            });

            const capacityStats = await Table.findOne({
                attributes: [
                    [Table.sequelize.fn('SUM', Table.sequelize.col('capacity')), 'total_capacity'],
                    [Table.sequelize.fn('AVG', Table.sequelize.col('capacity')), 'avg_capacity'],
                    [Table.sequelize.fn('MIN', Table.sequelize.col('capacity')), 'min_capacity'],
                    [Table.sequelize.fn('MAX', Table.sequelize.col('capacity')), 'max_capacity']
                ],
                raw: true
            });

            const locationStats = await Table.findAll({
                where: {
                    location: { [Op.ne]: null }
                },
                attributes: [
                    'location',
                    [Table.sequelize.fn('COUNT', Table.sequelize.col('location')), 'count']
                ],
                group: ['location'],
                raw: true
            });

            res.json({
                success: true,
                data: {
                    total: totalTables,
                    statusBreakdown: statusStats.reduce((acc, stat) => {
                        acc[stat.status] = parseInt(stat.count);
                        return acc;
                    }, {}),
                    locationBreakdown: locationStats.reduce((acc, stat) => {
                        acc[stat.location] = parseInt(stat.count);
                        return acc;
                    }, {}),
                    capacityStats: {
                        total: parseInt(capacityStats?.total_capacity) || 0,
                        average: parseFloat(capacityStats?.avg_capacity) || 0,
                        min: parseInt(capacityStats?.min_capacity) || 0,
                        max: parseInt(capacityStats?.max_capacity) || 0
                    }
                }
            });
        } catch (error) {
            console.error('❌ Error in getTableStats:', error);
            res.status(500).json({
                success: false,
                error: 'Failed to get table statistics',
                message: error.message
            });
        }
    }

    // Search tables
    static async searchTables(req, res) {
        try {
            const { q, status, location, capacity_min, limit = 10 } = req.query;

            if (!q || q.length < 2) {
                return res.status(400).json({
                    success: false,
                    error: 'Search term must be at least 2 characters long'
                });
            }

            const whereClause = {
                [Op.or]: [
                    { nom: { [Op.like]: `%${q}%` } },
                    { location: { [Op.like]: `%${q}%` } }
                ]
            };

            if (status) {
                whereClause.status = status;
            }

            if (location) {
                whereClause.location = { [Op.like]: `%${location}%` };
            }

            if (capacity_min) {
                whereClause.capacity = { [Op.gte]: parseInt(capacity_min) };
            }

            const tables = await Table.findAll({
                where: whereClause,
                limit: parseInt(limit),
                order: [['nom', 'ASC']]
            });

            res.json({
                success: true,
                data: tables,
                count: tables.length
            });
        } catch (error) {
            console.error('❌ Error in searchTables:', error);
            res.status(500).json({
                success: false,
                error: 'Failed to search tables',
                message: error.message
            });
        }
    }

    // Get tables by location
    static async getTablesByLocation(req, res) {
        try {
            const { location } = req.params;

            if (!location) {
                return res.status(400).json({
                    success: false,
                    error: 'Location parameter is required'
                });
            }

            const tables = await Table.findAll({
                where: { 
                    location: { [Op.like]: `%${location}%` }
                },
                order: [['nom', 'ASC']]
            });

            res.json({
                success: true,
                data: tables,
                count: tables.length
            });
        } catch (error) {
            console.error('❌ Error in getTablesByLocation:', error);
            res.status(500).json({
                success: false,
                error: 'Failed to fetch tables by location',
                message: error.message
            });
        }
    }

    // Get available tables with optional capacity filter
    static async getAvailableTables(req, res) {
        try {
            const { capacity_min, location } = req.query;
            
            const whereClause = {
                status: 'available'
            };

            if (capacity_min) {
                whereClause.capacity = { [Op.gte]: parseInt(capacity_min) };
            }

            if (location) {
                whereClause.location = { [Op.like]: `%${location}%` };
            }

            const tables = await Table.findAll({
                where: whereClause,
                order: [['capacity', 'ASC'], ['nom', 'ASC']]
            });

            res.json({
                success: true,
                data: tables,
                count: tables.length
            });
        } catch (error) {
            console.error('❌ Error in getAvailableTables:', error);
            res.status(500).json({
                success: false,
                error: 'Failed to fetch available tables',
                message: error.message
            });
        }
    }
}

module.exports = TableController;
