<?php
/**
 * Script d'envoi de notifications push pour le chat
 * 
 * Ce script est appelé par l'API backend pour envoyer des notifications
 * lorsqu'un nouveau message est reçu
 */

require_once 'vendor/autoload.php';

use Kreait\Firebase\Factory;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Notification;

class ChatNotificationSender {
    private $messaging;
    private $db;

    public function __construct($firebaseServiceAccount, $dbConnection) {
        $factory = (new Factory)->withServiceAccount($firebaseServiceAccount);
        $this->messaging = $factory->createMessaging();
        $this->db = $dbConnection;
    }

    /**
     * Envoie une notification à un utilisateur pour un nouveau message
     */
    public function sendMessageNotification($userId, $messageId, $senderId, $content, $conversationId) {
        try {
            // Récupérer les préférences de notification de l'utilisateur
            $settings = $this->getUserNotificationSettings($userId);
            
            if (!$settings['enable_notifications']) {
                return ['status' => 'skipped', 'reason' => 'notifications_disabled'];
            }

            // Vérifier si la conversation est en silencieux
            if (in_array($conversationId, $settings['muted_conversations'])) {
                return ['status' => 'skipped', 'reason' => 'conversation_muted'];
            }

            // Vérifier le mode Ne pas déranger
            if ($this->isInDoNotDisturbPeriod($settings)) {
                return ['status' => 'skipped', 'reason' => 'do_not_disturb'];
            }

            // Obtenir le token du device
            $deviceToken = $this->getUserDeviceToken($userId);
            if (!$deviceToken) {
                return ['status' => 'error', 'reason' => 'no_device_token'];
            }

            // Obtenir les informations de l'expéditeur
            $sender = $this->getSenderInfo($senderId);
            
            // Obtenir le nom de la conversation
            $conversationName = $this->getConversationName($conversationId, $userId);

            // Préparation du contenu de la notification
            $title = $conversationName ?? $sender['name'];
            $body = $settings['show_preview'] ? $content : 'Nouveau message';

            // Créer le message Firebase
            $message = CloudMessage::withTarget('token', $deviceToken)
                ->withNotification(Notification::create($title, $body))
                ->withData([
                    'type' => 'chat_message',
                    'messageId' => $messageId,
                    'conversationId' => $conversationId,
                    'senderId' => $senderId,
                    'click_action' => 'FLUTTER_NOTIFICATION_CLICK',
                ])
                ->withAndroidConfig([
                    'priority' => 'high',
                    'notification' => [
                        'sound' => $settings['sound_enabled'] ? 'default' : null,
                        'channel_id' => 'chat_messages',
                        'icon' => 'ic_launcher',
                    ],
                ])
                ->withApnsConfig([
                    'payload' => [
                        'aps' => [
                            'sound' => $settings['sound_enabled'] ? 'default' : null,
                            'badge' => 1, // TODO: Calculer le nombre réel de messages non lus
                        ],
                    ],
                ]);

            // Envoyer la notification
            $result = $this->messaging->send($message);

            // Enregistrer la notification dans la base de données
            $this->saveNotificationToDatabase($userId, $messageId, $conversationId, $title, $body);

            return [
                'status' => 'success',
                'message_id' => $result,
            ];

        } catch (Exception $e) {
            return [
                'status' => 'error',
                'reason' => $e->getMessage(),
            ];
        }
    }

    /**
     * Envoie une notification de type broadcast
     */
    public function sendBroadcastNotification($audienceTargets, $messageId, $content, $conversationId) {
        $results = [];
        
        // Résoudre les cibles d'audience
        $userIds = $this->resolveAudienceTargets($audienceTargets);
        
        foreach ($userIds as $userId) {
            $result = $this->sendMessageNotification($userId, $messageId, null, $content, $conversationId);
            $results[$userId] = $result;
        }
        
        return $results;
    }

    /**
     * Enregistre la notification dans la base de données
     */
    private function saveNotificationToDatabase($userId, $messageId, $conversationId, $title, $body) {
        $stmt = $this->db->prepare("
            INSERT INTO chat_notifications (fk_user, fk_message, fk_room, type, contenu, statut)
            VALUES (?, ?, ?, 'chat_message', ?, 'non_lue')
        ");
        
        $stmt->execute([$userId, $messageId, $conversationId, json_encode([
            'title' => $title,
            'body' => $body,
        ])]);
    }

    /**
     * Récupère les préférences de notification de l'utilisateur
     */
    private function getUserNotificationSettings($userId) {
        // Implémenter la logique pour récupérer les paramètres
        return [
            'enable_notifications' => true,
            'sound_enabled' => true,
            'vibration_enabled' => true,
            'muted_conversations' => [],
            'show_preview' => true,
            'do_not_disturb' => false,
            'do_not_disturb_start' => null,
            'do_not_disturb_end' => null,
        ];
    }

    /**
     * Vérifie si on est dans la période Ne pas déranger
     */
    private function isInDoNotDisturbPeriod($settings) {
        if (!$settings['do_not_disturb']) {
            return false;
        }

        $now = new DateTime();
        $start = new DateTime($settings['do_not_disturb_start']);
        $end = new DateTime($settings['do_not_disturb_end']);

        if ($start < $end) {
            return $now >= $start && $now <= $end;
        } else {
            // Période qui chevauche minuit
            return $now >= $start || $now <= $end;
        }
    }

    /**
     * Récupère le token du device de l'utilisateur
     */
    private function getUserDeviceToken($userId) {
        $stmt = $this->db->prepare("
            SELECT device_token 
            FROM notification_settings 
            WHERE user_id = ? AND device_token IS NOT NULL
            ORDER BY updated_at DESC LIMIT 1
        ");
        
        $stmt->execute([$userId]);
        return $stmt->fetchColumn();
    }

    /**
     * Récupère les informations de l'expéditeur
     */
    private function getSenderInfo($senderId) {
        $stmt = $this->db->prepare("
            SELECT id, name, username 
            FROM users 
            WHERE id = ?
        ");
        
        $stmt->execute([$senderId]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    /**
     * Récupère le nom de la conversation
     */
    private function getConversationName($conversationId, $userId) {
        $stmt = $this->db->prepare("
            SELECT title 
            FROM chat_rooms 
            WHERE id = ?
        ");
        
        $stmt->execute([$conversationId]);
        return $stmt->fetchColumn();
    }

    /**
     * Résout les cibles d'audience en une liste d'IDs utilisateur
     */
    private function resolveAudienceTargets($targets) {
        $userIds = [];
        
        foreach ($targets as $target) {
            switch ($target['target_type']) {
                case 'all':
                    // Récupérer tous les utilisateurs
                    $stmt = $this->db->query("SELECT id FROM users WHERE chk_active = 1");
                    $userIds = array_merge($userIds, $stmt->fetchAll(PDO::FETCH_COLUMN));
                    break;
                    
                case 'role':
                    // Récupérer les utilisateurs par rôle
                    $stmt = $this->db->prepare("SELECT id FROM users WHERE fk_role = ?");
                    $stmt->execute([$target['role_filter']]);
                    $userIds = array_merge($userIds, $stmt->fetchAll(PDO::FETCH_COLUMN));
                    break;
                    
                case 'entity':
                    // Récupérer les utilisateurs par entité
                    $stmt = $this->db->prepare("SELECT id FROM users WHERE fk_entite = ?");
                    $stmt->execute([$target['entity_filter']]);
                    $userIds = array_merge($userIds, $stmt->fetchAll(PDO::FETCH_COLUMN));
                    break;
                    
                case 'combined':
                    // Récupérer les utilisateurs par combinaison de rôle et entité
                    $stmt = $this->db->prepare("
                        SELECT id FROM users 
                        WHERE fk_role = ? AND fk_entite = ?
                    ");
                    $stmt->execute([$target['role_filter'], $target['entity_filter']]);
                    $userIds = array_merge($userIds, $stmt->fetchAll(PDO::FETCH_COLUMN));
                    break;
            }
        }
        
        return array_unique($userIds);
    }
}
