<?php
/**
 * Contrôleur pour la gestion des notifications de check-out et nettoyage
 */

class NotificationController {
    private $pdo;
    
    public function __construct($pdo) {
        $this->pdo = $pdo;
    }
    
    /**
     * Afficher le dashboard des notifications
     */
    public function dashboard() {
        try {
            // Récupérer les notifications actives
            $notifications = $this->getActiveNotifications();
            
            // Récupérer les statistiques
            $stats = $this->getNotificationStats();
            
            // Récupérer les chambres par statut
            $roomsByStatus = $this->getRoomsByStatus();
            
            // Titre de la page
            $pageTitle = 'Notifications - Gestion des Chambres';
            
            // Inclure la vue
            include __DIR__ . '/../views/notifications/dashboard.php';
            
        } catch (Exception $e) {
            $_SESSION['error'] = 'Erreur lors du chargement des notifications: ' . $e->getMessage();
            header('Location: dashboard.php');
            exit();
        }
    }
    
    /**
     * Récupérer les notifications actives
     */
    public function getActiveNotifications() {
        $sql = "SELECT 
                    n.id,
                    n.notification_type,
                    n.status,
                    n.priority,
                    n.message,
                    n.created_at,
                    ro.room_number,
                    ro.floor,
                    r.reservation_number,
                    c.first_name as client_first_name,
                    c.last_name as client_last_name,
                    r.check_out_date,
                    u.first_name as acknowledged_by_name,
                    u.last_name as acknowledged_by_lastname
                FROM room_status_notifications n
                INNER JOIN rooms ro ON n.room_id = ro.id
                LEFT JOIN reservations r ON n.reservation_id = r.id
                LEFT JOIN clients c ON r.client_id = c.id
                LEFT JOIN users u ON n.acknowledged_by = u.id
                WHERE n.status = 'active'
                ORDER BY n.priority DESC, n.created_at ASC";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    /**
     * Récupérer les statistiques des notifications
     */
    public function getNotificationStats() {
        $sql = "SELECT 
                    COUNT(*) as total_notifications,
                    SUM(CASE WHEN notification_type = 'checkout_pending' THEN 1 ELSE 0 END) as checkout_pending,
                    SUM(CASE WHEN notification_type = 'cleaning_required' THEN 1 ELSE 0 END) as cleaning_required,
                    SUM(CASE WHEN notification_type = 'room_ready' THEN 1 ELSE 0 END) as room_ready,
                    SUM(CASE WHEN priority = 'urgent' THEN 1 ELSE 0 END) as urgent_count,
                    SUM(CASE WHEN priority = 'high' THEN 1 ELSE 0 END) as high_count
                FROM room_status_notifications 
                WHERE status = 'active'";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    
    /**
     * Récupérer les chambres par statut
     */
    public function getRoomsByStatus() {
        $sql = "SELECT 
                    ro.id,
                    ro.room_number,
                    ro.floor,
                    ro.status as room_status,
                    r.status as reservation_status,
                    r.check_out_date,
                    r.reservation_number,
                    c.first_name as client_first_name,
                    c.last_name as client_last_name,
                    CASE 
                        WHEN r.status = 'checked_out' THEN 'libre'
                        WHEN r.status = 'checked_in' AND r.check_out_date <= CURDATE() THEN 'à nettoyer'
                        WHEN r.status = 'checked_in' THEN 'occupée'
                        WHEN r.status = 'confirmed' AND r.check_in_date <= CURDATE() THEN 'à occuper'
                        ELSE 'libre'
                    END as computed_status
                FROM rooms ro
                LEFT JOIN reservations r ON ro.id = r.room_id 
                AND r.status IN ('confirmed', 'checked_in', 'checked_out')
                AND r.check_out_date >= CURDATE() - INTERVAL 1 DAY
                LEFT JOIN clients c ON r.client_id = c.id
                WHERE ro.is_active = 1
                ORDER BY ro.room_number";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    /**
     * Marquer une notification comme acquittée
     */
    public function acknowledgeNotification($notificationId, $userId) {
        try {
            $sql = "UPDATE room_status_notifications 
                    SET status = 'acknowledged', 
                        acknowledged_at = NOW(), 
                        acknowledged_by = ?
                    WHERE id = ? AND status = 'active'";
            
            $stmt = $this->pdo->prepare($sql);
            $result = $stmt->execute([$userId, $notificationId]);
            
            if ($result && $stmt->rowCount() > 0) {
                $_SESSION['success'] = 'Notification acquittée avec succès';
                return true;
            } else {
                $_SESSION['error'] = 'Notification non trouvée ou déjà acquittée';
                return false;
            }
        } catch (Exception $e) {
            $_SESSION['error'] = 'Erreur lors de l\'acquittement: ' . $e->getMessage();
            return false;
        }
    }
    
    /**
     * Marquer une notification comme terminée
     */
    public function completeNotification($notificationId, $userId) {
        try {
            $sql = "UPDATE room_status_notifications 
                    SET status = 'completed', 
                        completed_at = NOW(), 
                        completed_by = ?
                    WHERE id = ? AND status IN ('active', 'acknowledged')";
            
            $stmt = $this->pdo->prepare($sql);
            $result = $stmt->execute([$userId, $notificationId]);
            
            if ($result && $stmt->rowCount() > 0) {
                $_SESSION['success'] = 'Notification marquée comme terminée';
                return true;
            } else {
                $_SESSION['error'] = 'Notification non trouvée ou déjà terminée';
                return false;
            }
        } catch (Exception $e) {
            $_SESSION['error'] = 'Erreur lors de la finalisation: ' . $e->getMessage();
            return false;
        }
    }
    
    /**
     * Créer une notification automatique
     */
    public function createNotification($roomId, $reservationId, $type, $priority = 'medium', $message = null) {
        try {
            if (!$message) {
                $room = $this->pdo->query("SELECT room_number FROM rooms WHERE id = $roomId")->fetch();
                $message = "Notification automatique pour la chambre {$room['room_number']}";
            }
            
            $sql = "INSERT INTO room_status_notifications 
                    (room_id, reservation_id, notification_type, priority, message)
                    VALUES (?, ?, ?, ?, ?)";
            
            $stmt = $this->pdo->prepare($sql);
            $result = $stmt->execute([$roomId, $reservationId, $type, $priority, $message]);
            
            return $result;
        } catch (Exception $e) {
            error_log("Erreur création notification: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Traiter automatiquement les check-outs
     */
    public function processCheckouts() {
        try {
            // Trouver les réservations qui doivent être check-out
            $sql = "SELECT r.id, r.room_id, r.reservation_number, ro.room_number
                    FROM reservations r
                    INNER JOIN rooms ro ON r.room_id = ro.id
                    WHERE r.status = 'checked_in'
                    AND r.check_out_date <= CURDATE()
                    AND r.checkout_time IS NULL";
            
            $reservations = $this->pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
            
            foreach ($reservations as $reservation) {
                // Créer une notification de check-out
                $this->createNotification(
                    $reservation['room_id'],
                    $reservation['id'],
                    'checkout_pending',
                    'high',
                    "Check-out requis pour la chambre {$reservation['room_number']} (Réservation: {$reservation['reservation_number']})"
                );
            }
            
            return count($reservations);
        } catch (Exception $e) {
            error_log("Erreur traitement check-outs: " . $e->getMessage());
            return 0;
        }
    }
    
    /**
     * Traiter automatiquement les chambres à nettoyer
     */
    public function processCleaningRequired() {
        try {
            // Trouver les chambres qui ont été check-out et nécessitent un nettoyage
            $sql = "SELECT DISTINCT r.room_id, ro.room_number
                    FROM reservations r
                    INNER JOIN rooms ro ON r.room_id = ro.id
                    WHERE r.status = 'checked_out'
                    AND r.checkout_time IS NOT NULL
                    AND r.checkout_time >= CURDATE() - INTERVAL 1 DAY
                    AND ro.id NOT IN (
                        SELECT room_id FROM room_status_notifications 
                        WHERE notification_type = 'cleaning_required' 
                        AND status = 'active'
                    )";
            
            $rooms = $this->pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
            
            foreach ($rooms as $room) {
                // Créer une notification de nettoyage
                $this->createNotification(
                    $room['room_id'],
                    null,
                    'cleaning_required',
                    'medium',
                    "Nettoyage requis pour la chambre {$room['room_number']}"
                );
            }
            
            return count($rooms);
        } catch (Exception $e) {
            error_log("Erreur traitement nettoyage: " . $e->getMessage());
            return 0;
        }
    }
    
    /**
     * Mettre à jour le statut d'une chambre
     */
    public function updateRoomStatus($roomId, $newStatus, $userId = null) {
        try {
            $validStatuses = ['available', 'occupied', 'reserved', 'maintenance', 'checkout'];
            
            if (!in_array($newStatus, $validStatuses)) {
                throw new Exception("Statut invalide: $newStatus");
            }
            
            $sql = "UPDATE rooms 
                    SET status = ?, updated_at = NOW() 
                    WHERE id = ?";
            
            $stmt = $this->pdo->prepare($sql);
            $result = $stmt->execute([$newStatus, $roomId]);
            
            if ($result) {
                // Créer une notification si nécessaire
                $this->createRoomStatusNotification($roomId, $newStatus, $userId);
                return true;
            }
            
            return false;
        } catch (Exception $e) {
            error_log("Erreur mise à jour statut chambre: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Créer une notification basée sur le changement de statut
     */
    private function createRoomStatusNotification($roomId, $newStatus, $userId = null) {
        $room = $this->pdo->query("SELECT room_number FROM rooms WHERE id = $roomId")->fetch();
        
        $notificationType = '';
        $priority = 'medium';
        $message = '';
        
        switch ($newStatus) {
            case 'checkout':
                $notificationType = 'cleaning_required';
                $priority = 'high';
                $message = "Chambre {$room['room_number']} libérée - Nettoyage requis";
                break;
                
            case 'available':
                $notificationType = 'room_ready';
                $priority = 'low';
                $message = "Chambre {$room['room_number']} prête pour nouvelle réservation";
                break;
                
            case 'maintenance':
                $notificationType = 'maintenance_required';
                $priority = 'urgent';
                $message = "Chambre {$room['room_number']} en maintenance";
                break;
        }
        
        if ($notificationType) {
            $this->createNotification($roomId, null, $notificationType, $priority, $message);
        }
    }
    
    /**
     * Traiter automatiquement les changements de statut
     */
    public function processRoomStatusUpdates() {
        try {
            // Exécuter la fonction de mise à jour automatique
            $result = $this->pdo->query("SELECT update_room_status() as updated_count")->fetch();
            $updatedCount = $result['updated_count'];
            
            // Créer des notifications pour les chambres mises à jour
            $this->createStatusChangeNotifications();
            
            return $updatedCount;
        } catch (Exception $e) {
            error_log("Erreur traitement statuts: " . $e->getMessage());
            return 0;
        }
    }
    
    /**
     * Créer des notifications pour les changements de statut
     */
    private function createStatusChangeNotifications() {
        // Chambres en checkout (nettoyage requis)
        $checkoutRooms = $this->pdo->query("
            SELECT id, room_number 
            FROM rooms 
            WHERE status = 'checkout' 
            AND id NOT IN (
                SELECT room_id FROM room_status_notifications 
                WHERE notification_type = 'cleaning_required' 
                AND status = 'active'
            )
        ")->fetchAll(PDO::FETCH_ASSOC);
        
        foreach ($checkoutRooms as $room) {
            $this->createNotification(
                $room['id'],
                null,
                'cleaning_required',
                'high',
                "Nettoyage requis pour la chambre {$room['room_number']}"
            );
        }
        
        // Chambres disponibles (prêtes)
        $availableRooms = $this->pdo->query("
            SELECT id, room_number 
            FROM rooms 
            WHERE status = 'available' 
            AND last_cleaned IS NOT NULL
            AND last_cleaned >= CURDATE() - INTERVAL 1 DAY
        ")->fetchAll(PDO::FETCH_ASSOC);
        
        foreach ($availableRooms as $room) {
            $this->createNotification(
                $room['id'],
                null,
                'room_ready',
                'low',
                "Chambre {$room['room_number']} prête pour réservation"
            );
        }
    }
    
    /**
     * Marquer une chambre comme nettoyée
     */
    public function markRoomAsCleaned($roomId, $userId) {
        try {
            $sql = "UPDATE rooms 
                    SET status = 'available', 
                        last_cleaned = NOW(), 
                        updated_at = NOW() 
                    WHERE id = ?";
            
            $stmt = $this->pdo->prepare($sql);
            $result = $stmt->execute([$roomId]);
            
            if ($result) {
                // Marquer les notifications de nettoyage comme terminées
                $this->pdo->prepare("
                    UPDATE room_status_notifications 
                    SET status = 'completed', 
                        completed_at = NOW(), 
                        completed_by = ?
                    WHERE room_id = ? 
                    AND notification_type = 'cleaning_required' 
                    AND status = 'active'
                ")->execute([$userId, $roomId]);
                
                return true;
            }
            
            return false;
        } catch (Exception $e) {
            error_log("Erreur marquage nettoyage: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * API pour récupérer les notifications en temps réel
     */
    public function getNotificationsAPI() {
        header('Content-Type: application/json');
        
        try {
            $notifications = $this->getActiveNotifications();
            $stats = $this->getNotificationStats();
            
            echo json_encode([
                'success' => true,
                'notifications' => $notifications,
                'stats' => $stats,
                'timestamp' => date('Y-m-d H:i:s')
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'error' => $e->getMessage()
            ]);
        }
    }
}
?>
