<?php
/**
 * Admin Notification Manager Class
 * Handles admin-to-agent notification system
 */

class AdminNotificationManager {
    private $conn;
    
    public function __construct($connection) {
        $this->conn = $connection;
    }
    
    /**
     * Send notification to agents/super agents
     */
    public function sendNotification($title, $message, $senderId, $recipientType = 'all', $recipientIds = null, $priority = 'normal', $expiresAt = null) {
        // Validate inputs
        if (empty($title) || empty($message) || empty($senderId)) {
            return ['success' => false, 'message' => 'Title, message, and sender ID are required'];
        }
        
        if (!in_array($recipientType, ['all', 'agents', 'specific'])) {
            return ['success' => false, 'message' => 'Invalid recipient type'];
        }
        
        if ($recipientType === 'specific' && empty($recipientIds)) {
            return ['success' => false, 'message' => 'Recipient IDs required for specific notifications'];
        }
        
        if (!in_array($priority, ['low', 'normal', 'high', 'urgent'])) {
            $priority = 'normal';
        }
        
        // Prepare recipient IDs for storage
        $recipientIdsJson = null;
        if ($recipientType === 'specific' && is_array($recipientIds)) {
            $recipientIdsJson = json_encode($recipientIds);
        }
        
        // Insert notification
        $stmt = $this->conn->prepare("
            INSERT INTO notifications (title, message, sender_id, sender_type, recipient_type, recipient_ids, priority, expires_at, created_at)
            VALUES (?, ?, ?, 'admin', ?, ?, ?, ?, NOW())
        ");
        
        $stmt->bind_param("ssissss", $title, $message, $senderId, $recipientType, $recipientIdsJson, $priority, $expiresAt);
        
        if ($stmt->execute()) {
            $notificationId = $stmt->insert_id;
            $stmt->close();
            
            // Get recipient count for response
            $recipientCount = $this->getRecipientCount($recipientType, $recipientIds);
            
            return [
                'success' => true, 
                'message' => 'Notification sent successfully',
                'notification_id' => $notificationId,
                'recipient_count' => $recipientCount
            ];
        } else {
            $stmt->close();
            return ['success' => false, 'message' => 'Failed to send notification: ' . mysqli_error($this->conn)];
        }
    }
    
    /**
     * Get notifications for a specific user
     */
    public function getUserNotifications($userId, $userType, $limit = 50, $offset = 0, $unreadOnly = false) {
        $whereClause = "WHERE (n.recipient_type = 'all' OR n.recipient_type = ?";
        $params = [$userType];
        $paramTypes = "s";
        
        if ($userType === 'agent') {
            $whereClause .= " OR n.recipient_type = 'agents'";
        // All users are now 'agent' role
        }
        
        $whereClause .= " OR (n.recipient_type = 'specific' AND n.recipient_ids LIKE ?))";
        $params[] = '%"' . $userId . '"%';
        $paramTypes .= "s";
        
        if ($unreadOnly) {
            $whereClause .= " AND nr.id IS NULL";
        }
        
        $whereClause .= " AND (n.expires_at IS NULL OR n.expires_at > NOW())";
        
        $sql = "
            SELECT n.*, nr.read_at, nr.id as read_id
            FROM notifications n
            LEFT JOIN notification_reads nr ON n.id = nr.notification_id AND nr.user_id = ?
            $whereClause
            ORDER BY n.priority DESC, n.created_at DESC
            LIMIT ? OFFSET ?
        ";
        
        $params[] = $userId;
        $params[] = $limit;
        $params[] = $offset;
        $paramTypes .= "iii";
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param($paramTypes, ...$params);
        $stmt->execute();
        $result = $stmt->get_result();
        
        $notifications = [];
        while ($row = $result->fetch_assoc()) {
            $notifications[] = $row;
        }
        
        $stmt->close();
        return $notifications;
    }
    
    /**
     * Mark notification as read for a user
     */
    public function markAsRead($notificationId, $userId, $userType) {
        // First, check if the notification exists
        $checkNotificationStmt = $this->conn->prepare("SELECT id FROM notifications WHERE id = ?");
        $checkNotificationStmt->bind_param("i", $notificationId);
        $checkNotificationStmt->execute();
        $notificationResult = $checkNotificationStmt->get_result();
        
        if ($notificationResult->num_rows === 0) {
            $checkNotificationStmt->close();
            return ['success' => false, 'message' => 'Notification not found'];
        }
        $checkNotificationStmt->close();
        
        // Check if already read
        $checkStmt = $this->conn->prepare("SELECT id FROM notification_reads WHERE notification_id = ? AND user_id = ?");
        $checkStmt->bind_param("ii", $notificationId, $userId);
        $checkStmt->execute();
        $result = $checkStmt->get_result();
        
        if ($result->num_rows > 0) {
            $checkStmt->close();
            return ['success' => true, 'message' => 'Already marked as read'];
        }
        $checkStmt->close();
        
        // Mark as read
        $stmt = $this->conn->prepare("INSERT INTO notification_reads (notification_id, user_id, user_type, read_at) VALUES (?, ?, ?, NOW())");
        $stmt->bind_param("iis", $notificationId, $userId, $userType);
        
        if ($stmt->execute()) {
            $stmt->close();
            return ['success' => true, 'message' => 'Marked as read'];
        } else {
            $stmt->close();
            return ['success' => false, 'message' => 'Failed to mark as read: ' . mysqli_error($this->conn)];
        }
    }
    
    /**
     * Mark all notifications as read for a user
     */
    public function markAllAsRead($userId, $userType) {
        // Get all unread notifications for this user
        $notifications = $this->getUserNotifications($userId, $userType, 1000, 0, true);
        
        $markedCount = 0;
        foreach ($notifications as $notification) {
            $result = $this->markAsRead($notification['id'], $userId, $userType);
            if ($result['success']) {
                $markedCount++;
            }
        }
        
        return ['success' => true, 'message' => "Marked $markedCount notifications as read"];
    }
    
    /**
     * Get unread notification count for a user
     */
    public function getUnreadCount($userId, $userType) {
        $notifications = $this->getUserNotifications($userId, $userType, 1000, 0, true);
        return count($notifications);
    }
    
    /**
     * Get all notifications (admin view)
     */
    public function getAllNotifications($limit = 50, $offset = 0) {
        $sql = "
            SELECT n.*, 
                   COUNT(nr.id) as read_count,
                   (SELECT COUNT(*) FROM agents WHERE role = 'agent') as total_recipients
            FROM notifications n
            LEFT JOIN notification_reads nr ON n.id = nr.notification_id
            GROUP BY n.id
            ORDER BY n.created_at DESC
            LIMIT ? OFFSET ?
        ";
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("ii", $limit, $offset);
        $stmt->execute();
        $result = $stmt->get_result();
        
        $notifications = [];
        while ($row = $result->fetch_assoc()) {
            $notifications[] = $row;
        }
        
        $stmt->close();
        return $notifications;
    }
    
    /**
     * Delete notification (admin only)
     */
    public function deleteNotification($notificationId) {
        $stmt = $this->conn->prepare("DELETE FROM notifications WHERE id = ?");
        $stmt->bind_param("i", $notificationId);
        
        if ($stmt->execute()) {
            $stmt->close();
            return ['success' => true, 'message' => 'Notification deleted successfully'];
        } else {
            $stmt->close();
            return ['success' => false, 'message' => 'Failed to delete notification'];
        }
    }
    
    /**
     * Get recipient count for a notification
     */
    private function getRecipientCount($recipientType, $recipientIds = null) {
        $stmt = null;
        
        switch ($recipientType) {
            case 'all':
                $stmt = $this->conn->prepare("SELECT COUNT(*) as count FROM agents WHERE role = 'agent'");
                break;
            case 'agents':
                $stmt = $this->conn->prepare("SELECT COUNT(*) as count FROM agents WHERE role = 'agent'");
                break;
            // All users are now 'agent' role - super_agents case removed
                break;
            case 'specific':
                if (is_array($recipientIds) && !empty($recipientIds)) {
                    $placeholders = str_repeat('?,', count($recipientIds) - 1) . '?';
                    $stmt = $this->conn->prepare("SELECT COUNT(*) as count FROM agents WHERE id IN ($placeholders)");
                    $stmt->bind_param(str_repeat('i', count($recipientIds)), ...$recipientIds);
                } else {
                    return 0;
                }
                break;
            default:
                return 0;
        }
        
        if ($stmt) {
            $stmt->execute();
            $result = $stmt->get_result();
            $count = $result->fetch_assoc()['count'];
            $stmt->close();
            return $count;
        }
        
        return 0;
    }
    
    /**
     * Get agents for recipient selection
     */
    public function getAgents($role = null) {
        $sql = "SELECT id, username, email, role FROM agents WHERE 1=1";
        $params = [];
        $paramTypes = "";
        
        if ($role) {
            $sql .= " AND role = ?";
            $params[] = $role;
            $paramTypes .= "s";
        }
        
        $sql .= " ORDER BY role, username";
        
        $stmt = $this->conn->prepare($sql);
        if (!empty($params)) {
            $stmt->bind_param($paramTypes, ...$params);
        }
        $stmt->execute();
        $result = $stmt->get_result();
        
        $agents = [];
        while ($row = $result->fetch_assoc()) {
            $agents[] = $row;
        }
        
        $stmt->close();
        return $agents;
    }
    
    /**
     * Get notification statistics
     */
    public function getNotificationStats() {
        $stats = [];
        
        // Total notifications
        $result = mysqli_query($this->conn, "SELECT COUNT(*) as total FROM notifications");
        $stats['total_notifications'] = mysqli_fetch_assoc($result)['total'];
        
        // Unread notifications (across all users)
        $result = mysqli_query($this->conn, "
            SELECT COUNT(DISTINCT n.id) as unread_count
            FROM notifications n
            LEFT JOIN notification_reads nr ON n.id = nr.notification_id
            WHERE nr.id IS NULL AND (n.expires_at IS NULL OR n.expires_at > NOW())
        ");
        $stats['unread_notifications'] = mysqli_fetch_assoc($result)['unread_count'];
        
        // Notifications by priority
        $result = mysqli_query($this->conn, "
            SELECT priority, COUNT(*) as count
            FROM notifications
            WHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)
            GROUP BY priority
        ");
        $stats['by_priority'] = [];
        while ($row = mysqli_fetch_assoc($result)) {
            $stats['by_priority'][$row['priority']] = $row['count'];
        }
        
        return $stats;
    }
    
    /**
     * Send notification to admins only
     * Used for critical system alerts like payment processing failures
     * This method works outside of transactions and always logs to error_log as backup
     */
    public function notifyAdmins($title, $message, $priority = 'urgent') {
        // Always log to error_log first (this works even if database fails)
        error_log("ADMIN NOTIFICATION [URGENT]: $title - $message");
        
        try {
            // Get all active admin user IDs
            $adminStmt = $this->conn->prepare("SELECT id FROM admin_users WHERE status = 'active'");
            if (!$adminStmt) {
                error_log("ADMIN NOTIFICATION ERROR: Failed to prepare admin query - " . mysqli_error($this->conn));
                return ['success' => false, 'message' => 'Database query failed'];
            }
            
            $adminStmt->execute();
            $adminResult = $adminStmt->get_result();
            
            $adminIds = [];
            while ($admin = $adminResult->fetch_assoc()) {
                $adminIds[] = $admin['id'];
            }
            $adminStmt->close();
            
            if (empty($adminIds)) {
                error_log("WARNING: No active admins found to notify. Title: $title");
                return ['success' => false, 'message' => 'No active admins found'];
            }
            
            // Insert into notifications table with system sender and admin recipient type
            // Use sender_id = 0 to indicate system-generated notification
            $systemMessage = "[SYSTEM ALERT] $message";
            $recipientType = 'admin'; // Special recipient type for admins
            $senderId = 0; // System sender
            
            $stmt = $this->conn->prepare("
                INSERT INTO notifications (title, message, sender_id, sender_type, recipient_type, recipient_ids, priority, created_at)
                VALUES (?, ?, ?, 'system', ?, NULL, ?, NOW())
            ");
            
            if (!$stmt) {
                error_log("ADMIN NOTIFICATION ERROR: Failed to prepare notification insert - " . mysqli_error($this->conn));
                return ['success' => false, 'message' => 'Failed to prepare notification'];
            }
            
            $stmt->bind_param("sisss", $title, $systemMessage, $senderId, $recipientType, $priority);
            
            if ($stmt->execute()) {
                $notificationId = $stmt->insert_id;
                $stmt->close();
                
                error_log("ADMIN NOTIFICATION SUCCESS: Notification ID $notificationId sent to " . count($adminIds) . " admin(s)");
                
                return [
                    'success' => true,
                    'message' => 'Admin notification sent successfully',
                    'notification_id' => $notificationId,
                    'admin_count' => count($adminIds)
                ];
            } else {
                $error = mysqli_error($this->conn);
                $stmt->close();
                error_log("ADMIN NOTIFICATION ERROR: Failed to insert notification - $error");
                return ['success' => false, 'message' => 'Failed to send admin notification: ' . $error];
            }
        } catch (Exception $e) {
            error_log("ADMIN NOTIFICATION EXCEPTION: " . $e->getMessage());
            return ['success' => false, 'message' => 'Exception: ' . $e->getMessage()];
        }
    }
    
    /**
     * Send SMS alert to admins when an order fails
     * @param int $orderId The order ID
     * @param array $orderDetails Order details (beneficiary_number, package_size, error, etc.)
     * @return array Result with success status and count of admins notified
     */
    public function sendOrderFailedSMS($orderId, $orderDetails = []) {
        try {
            require_once __DIR__ . '/NotificationManager.php';
            $notificationManager = new NotificationManager($this->conn);
            
            // Get all active admins with phone numbers
            $adminStmt = $this->conn->prepare("SELECT id, username, phone FROM admin_users WHERE status = 'active' AND phone IS NOT NULL AND phone != ''");
            if (!$adminStmt) {
                error_log("Failed to prepare admin query for order failed SMS: " . mysqli_error($this->conn));
                return ['success' => false, 'message' => 'Database query failed'];
            }
            
            $adminStmt->execute();
            $adminResult = $adminStmt->get_result();
            
            $admins = [];
            while ($admin = $adminResult->fetch_assoc()) {
                $admins[] = $admin;
            }
            $adminStmt->close();
            
            if (empty($admins)) {
                error_log("No active admins with phone numbers found to notify about failed order $orderId");
                return ['success' => false, 'message' => 'No active admins with phone numbers found'];
            }
            
            // Build SMS message
            $beneficiary = $orderDetails['beneficiary_number'] ?? 'N/A';
            $packageSize = $orderDetails['package_size'] ?? 'N/A';
            $error = $orderDetails['error'] ?? 'Unknown error';
            $networkType = $orderDetails['network_type'] ?? 'N/A';
            
            $message = "⚠️ ORDER FAILED ALERT - D-Bundles Stores\n\n";
            $message .= "Order ID: #$orderId\n";
            $message .= "Network: $networkType\n";
            $message .= "Phone: $beneficiary\n";
            $message .= "Package: $packageSize\n";
            $message .= "Error: $error\n\n";
            $message .= "Please check the order in the admin panel.\n\n";
            $message .= "D-Bundles Stores System";
            
            // Send SMS to each admin
            $sentCount = 0;
            $failedCount = 0;
            
            foreach ($admins as $admin) {
                // Use reflection to access private sendSMS method, or use a public wrapper
                // Since sendSMS is private, we'll use the SMS sending logic directly
                $phoneNumber = $admin['phone'];
                
                // Clean phone number
                $phoneNumber = preg_replace('/[^0-9+]/', '', $phoneNumber);
                if (strpos($phoneNumber, '0') === 0) {
                    $phoneNumber = '233' . substr($phoneNumber, 1);
                } elseif (strpos($phoneNumber, '233') !== 0 && strpos($phoneNumber, '+233') !== 0) {
                    $phoneNumber = '233' . $phoneNumber;
                }
                $phoneNumber = str_replace('+', '', $phoneNumber);
                
                // Get SMS configuration
                $smsResult = mysqli_query($this->conn, "SELECT config_data FROM notification_config WHERE type = 'sms'");
                if (!$smsResult || mysqli_num_rows($smsResult) == 0) {
                    error_log("SMS configuration not found for order failed alert");
                    $failedCount++;
                    continue;
                }
                
                $smsData = mysqli_fetch_assoc($smsResult);
                $smsConfig = json_decode($smsData['config_data'], true) ?: [];
                
                if (empty($smsConfig['enabled'])) {
                    error_log("SMS is disabled in configuration");
                    $failedCount++;
                    continue;
                }
                
                // Send SMS based on provider
                $provider = $smsConfig['provider'] ?? 'generic';
                $smsSent = false;
                
                if ($provider === 'smsonlinegh') {
                    $smsSent = $this->sendSMSViaSMSOnlineGH($phoneNumber, $message, $smsConfig);
                } else {
                    $smsSent = $this->sendSMSViaGeneric($phoneNumber, $message, $smsConfig);
                }
                
                if ($smsSent) {
                    $sentCount++;
                    error_log("Order failed SMS alert sent to admin {$admin['username']} (Phone: {$admin['phone']}) for order $orderId");
                } else {
                    $failedCount++;
                    error_log("Failed to send order failed SMS alert to admin {$admin['username']} (Phone: {$admin['phone']}) for order $orderId");
                }
            }
            
            return [
                'success' => $sentCount > 0,
                'message' => "SMS sent to $sentCount admin(s), failed for $failedCount admin(s)",
                'sent_count' => $sentCount,
                'failed_count' => $failedCount,
                'total_admins' => count($admins)
            ];
            
        } catch (Exception $e) {
            error_log("Exception in sendOrderFailedSMS: " . $e->getMessage());
            return ['success' => false, 'message' => 'Exception: ' . $e->getMessage()];
        }
    }
    
    /**
     * Send SMS via SMS Online Ghana
     */
    private function sendSMSViaSMSOnlineGH($phoneNumber, $message, $smsConfig) {
        $apiKey = $smsConfig['api_key'] ?? '';
        $senderId = $smsConfig['sender_id'] ?? '';
        
        if (empty($apiKey) || empty($senderId)) {
            error_log("SMS Online Ghana: Missing API key or sender ID");
            return false;
        }
        
        // Ensure phone number starts with country code
        if (strpos($phoneNumber, '233') !== 0) {
            if (strpos($phoneNumber, '0') === 0) {
                $phoneNumber = '233' . substr($phoneNumber, 1);
            } else {
                $phoneNumber = '233' . $phoneNumber;
            }
        }
        
        // Set up the request headers according to SMS Online Ghana API documentation
        $headers = [
            'Host: api.smsonlinegh.com',
            'Content-Type: application/json',
            'Accept: application/json',
            'Authorization: key ' . $apiKey
        ];
        
        // Set up the message data according to SMS Online Ghana API documentation
        $messageData = [
            'text' => $message,
            'type' => 0, // GSM default
            'sender' => $senderId,
            'destinations' => [$phoneNumber]
        ];
        
        // Initialize cURL with the correct endpoint (v5)
        $ch = curl_init('https://api.smsonlinegh.com/v5/sms/send');
        
        // Set cURL options according to SMS Online Ghana API documentation
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($messageData));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        
        // Execute for response
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlError = curl_error($ch);
        
        // Close curl
        curl_close($ch);
        
        // Log the attempt
        error_log("SMS Online Ghana - HTTP Code: $httpCode, Response: $response, Error: $curlError");
        
        // Check if successful (SMS Online Ghana returns 200 for success)
        if ($httpCode == 200) {
            $responseData = json_decode($response, true);
            // Check if response indicates success
            if (isset($responseData['status']) && $responseData['status'] === 'success') {
                error_log("SMS Online Ghana: Success - Response: $response");
                return true;
            } elseif (isset($responseData['handshake'])) {
                // Handshake error indicates authentication/access issue
                error_log("SMS Online Ghana API error: " . ($response ?: 'Empty response'));
                return false;
            } else {
                // Assume success if HTTP 200 but check response structure
                error_log("SMS Online Ghana: Success (HTTP 200) - Response: $response");
                return true;
            }
        } else {
            error_log("SMS Online Ghana: Failed - HTTP Code: $httpCode, Response: $response");
            return false;
        }
    }
    
    /**
     * Send SMS via Generic API
     */
    private function sendSMSViaGeneric($phoneNumber, $message, $smsConfig) {
        $url = $smsConfig['api_url'] ?? '';
        $apiKey = $smsConfig['api_key'] ?? '';
        $senderId = $smsConfig['sender_id'] ?? '';
        
        if (empty($url) || empty($apiKey)) {
            error_log("Generic SMS: Missing API URL or API key");
            return false;
        }
        
        $data = [
            'to' => $phoneNumber,
            'message' => $message,
            'sender_id' => $senderId,
            'api_key' => $apiKey
        ];
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Accept: application/json'
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlError = curl_error($ch);
        curl_close($ch);
        
        if ($curlError) {
            error_log("Generic SMS cURL error: $curlError");
            return false;
        }
        
        return $httpCode >= 200 && $httpCode < 300;
    }
}
?>
