<?php
/**
 * ============================================================================
 * classes/PushNotification.php
 * Web Push Notification Handler (using web-push library)
 * ============================================================================
 */

namespace App;

use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;

class PushNotification {
    private $db;
    private $webPush;
    
    // VAPID keys - Generate these using: vendor/bin/web-push generate-vapid-keys
    // Or use: https://vapidkeys.com/
    private $vapidPublicKey;
    private $vapidPrivateKey;
    
    public function __construct($db) {
        $this->db = $db;
        
        // Load VAPID keys from environment or config
        $this->vapidPublicKey = getenv('VAPID_PUBLIC_KEY') ?: 
            'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U';
        
        $this->vapidPrivateKey = getenv('VAPID_PRIVATE_KEY') ?: 
            'UUxI4O8-FbRouAevSmBQ6o18hgE4nSG3qwvJTfKc-ls';
        
        // Initialize WebPush
        $auth = [
            'VAPID' => [
                'subject' => 'mailto:admin@aims.ug',
                'publicKey' => $this->vapidPublicKey,
                'privateKey' => $this->vapidPrivateKey,
            ],
        ];
        
        $this->webPush = new WebPush($auth);
    }
    
    /**
     * Get VAPID public key for client-side subscription
     */
    public function getPublicKey() {
        return $this->vapidPublicKey;
    }
    
    /**
     * Save push subscription from client
     */
    public function saveSubscription($userId, $subscriptionData) {
        try {
            $endpoint = $subscriptionData['endpoint'];
            $keys = json_encode($subscriptionData['keys']);
            
            // Check if subscription already exists
            $sql = "SELECT id FROM push_subscriptions 
                    WHERE user_id = ? AND endpoint = ?";
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$userId, $endpoint]);
            
            if ($stmt->fetch()) {
                // Update existing subscription
                $sql = "UPDATE push_subscriptions 
                        SET p256dh = ?, auth = ?, updated_at = CURRENT_TIMESTAMP
                        WHERE user_id = ? AND endpoint = ?";
                $stmt = $this->db->prepare($sql);
                $stmt->execute([
                    $subscriptionData['keys']['p256dh'],
                    $subscriptionData['keys']['auth'],
                    $userId,
                    $endpoint
                ]);
            } else {
                // Insert new subscription
                $sql = "INSERT INTO push_subscriptions 
                        (user_id, endpoint, p256dh, auth) 
                        VALUES (?, ?, ?, ?)";
                $stmt = $this->db->prepare($sql);
                $stmt->execute([
                    $userId,
                    $endpoint,
                    $subscriptionData['keys']['p256dh'],
                    $subscriptionData['keys']['auth']
                ]);
            }
            
            return ['success' => true, 'message' => 'Subscription saved'];
            
        } catch (\Exception $e) {
            error_log('Save subscription error: ' . $e->getMessage());
            return ['success' => false, 'message' => 'Failed to save subscription'];
        }
    }
    
    /**
     * Remove subscription (when user unsubscribes)
     */
    public function removeSubscription($userId, $endpoint) {
        try {
            $sql = "DELETE FROM push_subscriptions 
                    WHERE user_id = ? AND endpoint = ?";
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$userId, $endpoint]);
            
            return ['success' => true, 'message' => 'Subscription removed'];
            
        } catch (\Exception $e) {
            error_log('Remove subscription error: ' . $e->getMessage());
            return ['success' => false, 'message' => 'Failed to remove subscription'];
        }
    }
    
    /**
     * Send push notification to a user
     */
    public function sendToUser($userId, $title, $body, $data = []) {
        try {
            // Get user's subscriptions
            $sql = "SELECT endpoint, p256dh, auth 
                    FROM push_subscriptions 
                    WHERE user_id = ? AND is_active = 1";
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$userId]);
            $subscriptions = $stmt->fetchAll(\PDO::FETCH_ASSOC);
            
            if (empty($subscriptions)) {
                return ['success' => false, 'message' => 'No active subscriptions'];
            }
            
            $payload = json_encode([
                'title' => $title,
                'body' => $body,
                'icon' => '/pwa/icons/icon-192x192.png',
                'badge' => '/pwa/icons/badge-96x96.png',
                'data' => $data,
                'vibrate' => [200, 100, 200],
                'tag' => 'aims-' . ($data['type'] ?? 'notification'),
                'requireInteraction' => false,
                'actions' => [
                    ['action' => 'open', 'title' => 'Open'],
                    ['action' => 'close', 'title' => 'Dismiss']
                ]
            ]);
            
            $successCount = 0;
            $failCount = 0;
            
            foreach ($subscriptions as $sub) {
                $subscription = Subscription::create([
                    'endpoint' => $sub['endpoint'],
                    'keys' => [
                        'p256dh' => $sub['p256dh'],
                        'auth' => $sub['auth']
                    ]
                ]);
                
                $result = $this->webPush->sendOneNotification($subscription, $payload);
                
                if ($result->isSuccess()) {
                    $successCount++;
                } else {
                    $failCount++;
                    
                    // If subscription is invalid (410 Gone), remove it
                    if ($result->getResponse()->getStatusCode() === 410) {
                        $this->removeSubscription($userId, $sub['endpoint']);
                    }
                    
                    error_log('Push failed: ' . $result->getReason());
                }
            }
            
            return [
                'success' => true,
                'sent' => $successCount,
                'failed' => $failCount
            ];
            
        } catch (\Exception $e) {
            error_log('Send push error: ' . $e->getMessage());
            return ['success' => false, 'message' => 'Failed to send notification'];
        }
    }
    
    /**
     * Send push notification to multiple users
     */
    public function sendToMultipleUsers($userIds, $title, $body, $data = []) {
        $results = [
            'total' => count($userIds),
            'success' => 0,
            'failed' => 0
        ];
        
        foreach ($userIds as $userId) {
            $result = $this->sendToUser($userId, $title, $body, $data);
            if ($result['success']) {
                $results['success']++;
            } else {
                $results['failed']++;
            }
        }
        
        return $results;
    }
    
    /**
     * Send notification when user receives a new message
     */
    public function notifyNewMessage($recipientId, $senderName, $messagePreview) {
        return $this->sendToUser(
            $recipientId,
            "New message from {$senderName}",
            $messagePreview,
            [
                'type' => 'message',
                'url' => '/chat/',
                'icon' => '/pwa/icons/icon-192x192.png'
            ]
        );
    }
    
    /**
     * Send notification when user receives a general notification
     */
    public function notifyUser($userId, $notificationData) {
        return $this->sendToUser(
            $userId,
            $notificationData['title'],
            $notificationData['message'],
            [
                'type' => $notificationData['type'] ?? 'info',
                'url' => $notificationData['link'] ?? '/',
                'id' => $notificationData['id'] ?? null
            ]
        );
    }
    
    /**
     * Test notification
     */
    public function sendTestNotification($userId) {
        return $this->sendToUser(
            $userId,
            '🌾 AIMS Test Notification',
            'Push notifications are working! You will receive updates for new messages and activities.',
            [
                'type' => 'test',
                'url' => '/dashboard/',
                'requireInteraction' => true
            ]
        );
    }
}
?>