<?php
/**
 * Status Polling Service
 * This script polls external APIs for order status updates
 * Should be run as a cron job every 2-5 minutes
 */

require_once '../../config.php';
require_once '../../vendor/autoload.php';
require_once '../../app/classes/ExternalAPIService.php';

// Set execution time limit
set_time_limit(300);

// Log start of polling
error_log("Starting status polling service");

try {
    // Get orders that need status checking
    $stmt = $conn->prepare("
        SELECT pq.*, o.status as current_status, o.user_id, o.beneficiary_number, o.package_size, o.network_type
        FROM api_polling_queue pq
        JOIN orders o ON pq.order_id = o.id
        WHERE pq.status = 'pending' 
        AND pq.next_poll_at <= NOW()
        AND pq.poll_count < pq.max_polls
        ORDER BY pq.next_poll_at ASC
        LIMIT 50
    ");
    
    $stmt->execute();
    $result = $stmt->get_result();
    $orders_to_check = $result->fetch_all(MYSQLI_ASSOC);
    $stmt->close();
    
    if (empty($orders_to_check)) {
        error_log("No orders to check for status updates");
        exit(0);
    }
    
    error_log("Found " . count($orders_to_check) . " orders to check");
    
    $processed = 0;
    $updated = 0;
    $errors = 0;
    
    foreach ($orders_to_check as $order) {
        try {
            // Mark as processing
            $update_stmt = $conn->prepare("UPDATE api_polling_queue SET status = 'processing' WHERE id = ?");
            $update_stmt->bind_param("i", $order['id']);
            $update_stmt->execute();
            $update_stmt->close();
            
            // Initialize API service for the network type
            $apiService = new ExternalAPIService($order['network_type']);
            
            // Check transaction status
            $statusResponse = $apiService->checkTransactionStatus($order['external_transaction_id']);
            
            if ($statusResponse['success']) {
                $external_status = $statusResponse['data']['status'] ?? 'unknown';
                
                // Map external status to internal status
                $status_mapping = [
                    'completed' => 'delivered',
                    'success' => 'delivered',
                    'delivered' => 'delivered',
                    'failed' => 'failed',
                    'error' => 'failed',
                    'cancelled' => 'cancelled',
                    'refunded' => 'refunded',
                    'pending' => 'processing',
                    'processing' => 'processing'
                ];
                
                $new_status = $status_mapping[strtolower($external_status)] ?? 'processing';
                
                // Check if status changed
                if ($order['current_status'] !== $new_status) {
                    // Update order status
                    $conn->begin_transaction();
                    
                    $order_update_stmt = $conn->prepare("UPDATE orders SET status = ?, status_updated_at = NOW(), last_status_check = NOW(), api_response_data = ? WHERE id = ?");
                    $api_response_json = json_encode($statusResponse['data']);
                    $order_update_stmt->bind_param("ssi", $new_status, $api_response_json, $order['order_id']);
                    $order_update_stmt->execute();
                    $order_update_stmt->close();
                    
                    // Log status change
                    $history_stmt = $conn->prepare("INSERT INTO order_status_history (order_id, old_status, new_status, change_reason, changed_by, external_data) VALUES (?, ?, ?, ?, 'polling', ?)");
                    $reason = "Status updated via polling from external API";
                    $history_stmt->bind_param("issss", $order['order_id'], $order['current_status'], $new_status, $reason, $api_response_json);
                    $history_stmt->execute();
                    $history_stmt->close();
                    
                    $conn->commit();
                    
                    $updated++;
                    error_log("Order {$order['order_id']} status updated from '{$order['current_status']}' to '$new_status'");
                    
                    // Send SMS alert to admins if status changed to 'failed'
                    if ($new_status === 'failed' && $order['current_status'] !== 'failed') {
                        try {
                            require_once __DIR__ . '/../../app/classes/AdminNotificationManager.php';
                            $adminNotifier = new AdminNotificationManager($conn);
                            
                            // Get order details for SMS
                            $orderDetails = [
                                'beneficiary_number' => $order['beneficiary_number'] ?? 'N/A',
                                'package_size' => $order['package_size'] ?? 'N/A',
                                'network_type' => $order['network_type'] ?? 'N/A',
                                'error' => 'Status changed to failed via polling'
                            ];
                            
                            $adminNotifier->sendOrderFailedSMS($order['order_id'], $orderDetails);
                            error_log("SMS alert sent to admins for failed order {$order['order_id']}");
                        } catch (Exception $e) {
                            error_log("Failed to send order failure SMS alert: " . $e->getMessage());
                        }
                    }
                }
                
                // Update polling queue
                $poll_count = $order['poll_count'] + 1;
                $is_completed = in_array($new_status, ['delivered', 'failed', 'cancelled', 'refunded']);
                
                if ($is_completed || $poll_count >= $order['max_polls']) {
                    // Mark as completed
                    $queue_update_stmt = $conn->prepare("UPDATE api_polling_queue SET status = 'completed', poll_count = ?, last_response = ? WHERE id = ?");
                    $queue_update_stmt->bind_param("isi", $poll_count, $api_response_json, $order['id']);
                    $queue_update_stmt->execute();
                    $queue_update_stmt->close();
                } else {
                    // Schedule next poll (exponential backoff)
                    $next_poll_minutes = min(30, pow(2, $poll_count)); // Max 30 minutes
                    $queue_update_stmt = $conn->prepare("UPDATE api_polling_queue SET status = 'pending', poll_count = ?, next_poll_at = DATE_ADD(NOW(), INTERVAL ? MINUTE), last_response = ? WHERE id = ?");
                    $queue_update_stmt->bind_param("iisi", $poll_count, $next_poll_minutes, $api_response_json, $order['id']);
                    $queue_update_stmt->execute();
                    $queue_update_stmt->close();
                }
                
            } else {
                // API call failed, schedule retry
                $poll_count = $order['poll_count'] + 1;
                $next_poll_minutes = min(30, pow(2, $poll_count));
                
                if ($poll_count >= $order['max_polls']) {
                    // Mark as failed after max retries
                    $queue_update_stmt = $conn->prepare("UPDATE api_polling_queue SET status = 'failed', poll_count = ?, last_response = ? WHERE id = ?");
                    $error_response = json_encode(['error' => $statusResponse['error']]);
                    $queue_update_stmt->bind_param("isi", $poll_count, $error_response, $order['id']);
                    $queue_update_stmt->execute();
                    $queue_update_stmt->close();
                    
                    error_log("Order {$order['order_id']} polling failed after {$poll_count} attempts: " . $statusResponse['error']);
                } else {
                    // Schedule retry
                    $queue_update_stmt = $conn->prepare("UPDATE api_polling_queue SET status = 'pending', poll_count = ?, next_poll_at = DATE_ADD(NOW(), INTERVAL ? MINUTE), last_response = ? WHERE id = ?");
                    $error_response = json_encode(['error' => $statusResponse['error']]);
                    $queue_update_stmt->bind_param("iisi", $poll_count, $next_poll_minutes, $error_response, $order['id']);
                    $queue_update_stmt->execute();
                    $queue_update_stmt->close();
                }
                
                $errors++;
            }
            
            $processed++;
            
            // Small delay to avoid overwhelming the external API
            usleep(500000); // 0.5 seconds
            
        } catch (Exception $e) {
            error_log("Error processing order {$order['order_id']}: " . $e->getMessage());
            
            // Mark as failed
            $queue_update_stmt = $conn->prepare("UPDATE api_polling_queue SET status = 'failed', last_response = ? WHERE id = ?");
            $error_response = json_encode(['error' => $e->getMessage()]);
            $queue_update_stmt->bind_param("si", $error_response, $order['id']);
            $queue_update_stmt->execute();
            $queue_update_stmt->close();
            
            $errors++;
        }
    }
    
    error_log("Status polling completed: $processed processed, $updated updated, $errors errors");
    
} catch (Exception $e) {
    error_log("Status polling service error: " . $e->getMessage());
    exit(1);
}
?>
