<?php
/**
 * Simple script to check order status from data website
 * This can be run as a cron job or called manually
 */

require_once '../config.php';
require_once '../app/classes/DataIntegrationConfig.php';

use App\classes\DataIntegrationConfig;

// Create logs directory if it doesn't exist
if (!is_dir('../logs')) {
    mkdir('../logs', 0755, true);
}

// Log file path
$log_file = '../logs/cron.log';

// Simple logging function
function cronLog($message, $type = 'INFO') {
    global $log_file;
    $timestamp = date('Y-m-d H:i:s');
    $log_entry = "[$timestamp] [$type] $message\n";
    file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
    
    // Also output to console if running from command line
    if (php_sapi_name() === 'cli') {
        echo $log_entry;
    }
}

// Start logging
cronLog("=== CRON JOB STARTED ===");
cronLog("PHP Version: " . PHP_VERSION);
cronLog("Script Path: " . __FILE__);
cronLog("Server Time: " . date('Y-m-d H:i:s'));
cronLog("Timezone: " . date_default_timezone_get());

// Get configuration
$configManager = new DataIntegrationConfig($conn);

// Check if integration is enabled
if (!$configManager->isEnabled()) {
    cronLog("Data integration is disabled or not properly configured", 'WARNING');
    exit(0);
}

cronLog("Data integration is enabled", 'SUCCESS');

$DATA_WEBSITE_URL = trim($configManager->getDataWebsiteUrl());
$DATA_WEBSITE_API_KEY = trim($configManager->getApiKey());

// Validate and clean the URL
$DATA_WEBSITE_URL = rtrim($DATA_WEBSITE_URL, '/');
if (empty($DATA_WEBSITE_URL) || !filter_var($DATA_WEBSITE_URL, FILTER_VALIDATE_URL)) {
    cronLog("Invalid or missing Data Website URL: '$DATA_WEBSITE_URL'", 'ERROR');
    cronLog("Please update the data_website_url in the data_integration_config table", 'ERROR');
    exit(1);
}

cronLog("Data Website URL: " . $DATA_WEBSITE_URL);
cronLog("API Key: " . (empty($DATA_WEBSITE_API_KEY) ? 'Not set' : 'Set (' . strlen($DATA_WEBSITE_API_KEY) . ' chars)'));

// Debug: Check what orders exist in database
$debug_stmt = $conn->prepare("
    SELECT 
        (SELECT COUNT(*) FROM orders) as total_orders,
        (SELECT COUNT(*) FROM agent_orders) as total_agent_orders,
        (SELECT COUNT(CASE WHEN external_transaction_id IS NOT NULL AND external_transaction_id != '' THEN 1 END) FROM orders) as orders_with_external_id,
        (SELECT COUNT(CASE WHEN external_transaction_id IS NOT NULL AND external_transaction_id != '' THEN 1 END) FROM agent_orders) as agent_orders_with_external_id,
        (SELECT COUNT(CASE WHEN status IN ('pending', 'processing') THEN 1 END) FROM orders) as pending_processing_orders,
        (SELECT COUNT(CASE WHEN status IN ('pending', 'processing') THEN 1 END) FROM agent_orders) as pending_processing_agent_orders
");
$debug_stmt->execute();
$debug_result = $debug_stmt->get_result();
$debug_data = $debug_result->fetch_assoc();
$debug_stmt->close();

cronLog("Database Debug - Orders table: " . $debug_data['total_orders'] . " total, " . $debug_data['orders_with_external_id'] . " with external_id, " . $debug_data['pending_processing_orders'] . " pending/processing");
cronLog("Database Debug - Agent_orders table: " . $debug_data['total_agent_orders'] . " total, " . $debug_data['agent_orders_with_external_id'] . " with external_id, " . $debug_data['pending_processing_agent_orders'] . " pending/processing");

// Get orders that have external_transaction_id from both tables
// Prioritize pending/processing orders, but also check recently completed ones
// Note: This includes store orders (from orders table with store_id) and agent orders (from agent_orders table)
$query = "
    SELECT id, external_transaction_id, status, created_at, beneficiary_number, package_size, network_type, 'agent_orders' as table_name
    FROM agent_orders 
    WHERE external_transaction_id IS NOT NULL 
    AND external_transaction_id != ''
    AND status IN ('pending', 'processing')
    
    UNION ALL
    
    SELECT id, external_transaction_id, status, created_at, beneficiary_number, package_size, network_type, 'orders' as table_name
    FROM orders 
    WHERE external_transaction_id IS NOT NULL 
    AND external_transaction_id != ''
    AND status IN ('pending', 'processing')
    
    ORDER BY created_at ASC
";

$result = mysqli_query($conn, $query);
if (!$result) {
    cronLog("Database query failed: " . mysqli_error($conn), 'ERROR');
    exit(1);
}

$orders = [];
while ($row = mysqli_fetch_assoc($result)) {
    $orders[] = $row;
}

if (empty($orders)) {
    cronLog("No orders to check", 'INFO');
    exit(0);
}

cronLog("Found " . count($orders) . " orders to check", 'INFO');

foreach ($orders as $order) {
    $orderId = $order['id'];
    $externalTransactionId = trim($order['external_transaction_id']);
    $currentStatus = $order['status'];
    $networkType = $order['network_type'] ?? 'N/A';
    $tableName = $order['table_name'] ?? 'agent_orders';
    
    // Skip if external_transaction_id is empty after trimming
    if (empty($externalTransactionId)) {
        cronLog("Skipping order $orderId from $tableName - empty external_transaction_id", 'WARNING');
        continue;
    }
    
    // Build URL with direct concatenation - no whitespace
    $orderIdParam = trim((string)$externalTransactionId);
    $apiKeyParam = trim((string)$DATA_WEBSITE_API_KEY);
    $baseUrl = trim($DATA_WEBSITE_URL);
    
    // Direct concatenation to prevent any whitespace
    $url = trim($baseUrl) . '/api/check_order_status.php?order_id=' . urlencode($orderIdParam) . '&api_key=' . urlencode($apiKeyParam);
    
    // Log the API call with the actual URL (masking API key for security)
    $logUrl = preg_replace('/([?&]api_key=)[^&]+/', '$1***', $url);
    cronLog("Checking order $orderId from $tableName (External ID: $externalTransactionId, Network: $networkType)");
    cronLog("API URL: $logUrl");
    
    $context = stream_context_create([
        'http' => [
            'timeout' => 10,
            'method' => 'GET',
            'user_agent' => 'BunlesHub-Cron/1.0',
            'ignore_errors' => true // Don't fail on HTTP errors, we'll check status code
        ]
    ]);
    
    $start_time = microtime(true);
    $response = @file_get_contents($url, false, $context);
    $end_time = microtime(true);
    $response_time = round(($end_time - $start_time) * 1000, 2);
    
    $httpStatus = null;
    if (isset($http_response_header) && is_array($http_response_header) && !empty($http_response_header[0])) {
        if (preg_match('#HTTP/\d\.\d\s+(\d{3})#', $http_response_header[0], $matches)) {
            $httpStatus = (int)$matches[1];
        }
    }
    
    if ($response === false || ($httpStatus !== null && $httpStatus >= 400)) {
        $statusText = $httpStatus ? "HTTP $httpStatus" : "network error";
        $errorMsg = "Failed to call API for order $orderId - {$statusText}";
        if ($httpStatus === 404) {
            $errorMsg .= ". URL not found. Please verify the data_website_url in data_integration_config table is correct.";
        }
        cronLog($errorMsg, 'ERROR');
        cronLog("Full URL used: " . $logUrl, 'ERROR');
        continue;
    }
    
    $data = json_decode($response, true);
    
    $ordersPayload = [];
    if (isset($data['order']) && is_array($data['order'])) {
        $ordersPayload = [$data['order']];
    } elseif (isset($data['orders']) && is_array($data['orders'])) {
        $ordersPayload = $data['orders'];
    }
    
    $orderData = null;
    if (!empty($ordersPayload)) {
        foreach ($ordersPayload as $orderEntry) {
            if (!is_array($orderEntry)) continue;
            if (($orderEntry['external_transaction_id'] ?? '') === $externalTransactionId) {
                $orderData = $orderEntry;
                break;
            }
        }
        if (!$orderData && count($ordersPayload) === 1) {
            $orderData = $ordersPayload[0];
        }
    }
    
    if ($data && ($data['success'] ?? false) && $orderData) {
        $externalStatus = $orderData['status'];
        cronLog("API response for order $orderId: External Status = $externalStatus (Response time: {$response_time}ms)", 'SUCCESS');
        
        // Map external status to internal status (direct mapping - no conversion)
        $status_mapping = [
            'delivered' => 'delivered',
            'pending' => 'pending',
            'failed' => 'failed'
        ];
        
        $mappedStatus = $status_mapping[strtolower($externalStatus)] ?? 'processing';
        $currentStatusLower = strtolower(trim($currentStatus));
        $mappedStatusLower = strtolower(trim($mappedStatus));
        
        cronLog("Status mapping - External: '$externalStatus' -> Internal: '$mappedStatus' | Current: '$currentStatus'", 'INFO');
        
        // CRITICAL: Prevent resetting processed orders back to pending
        // Once an order is in any processed state, it should never go back to 'pending'
        // This prevents Process/Cancel buttons from reappearing after an order has been processed
        $final_states = ['processing', 'completed', 'failed', 'delivered', 'paid', 'cancelled'];
        
        // Block if trying to reset any processed state back to pending
        if (in_array($currentStatusLower, $final_states) && $mappedStatusLower === 'pending') {
            cronLog("STATUS RESET BLOCKED - Order $orderId: Attempt to reset from '$currentStatus' to 'pending' blocked. Order already processed.", 'WARNING');
            continue; // Skip this order, don't update it
        }
        
        // ADDITIONAL PROTECTION: Also block if current status is NOT 'pending' and mapped status is 'pending'
        // This catches any edge cases where status might not be in final_states but still shouldn't go back to pending
        if ($currentStatusLower !== 'pending' && $mappedStatusLower === 'pending') {
            cronLog("STATUS RESET BLOCKED - Order $orderId: Attempt to reset from '$currentStatus' to 'pending' blocked. Order status is not pending.", 'WARNING');
            continue; // Skip this order, don't update it
        }
        
        // If status is different, update BunlesHub
        if ($currentStatusLower !== $mappedStatusLower) {
            // Determine which table to update based on order data
            // 'orders' table includes store orders (regular customers buying from stores)
            // 'agent_orders' table includes agent/sub-agent orders
            $tableName = $order['table_name'] ?? 'agent_orders';
            
            if ($tableName === 'agent_orders') {
                $updateStmt = $conn->prepare("UPDATE agent_orders SET status = ?, status_updated_at = NOW() WHERE id = ?");
            } else {
                // Update orders table (includes store orders with store_id)
                $updateStmt = $conn->prepare("UPDATE orders SET status = ?, status_updated_at = NOW() WHERE id = ?");
            }
            
            if ($updateStmt) {
                $updateStmt->bind_param("si", $mappedStatus, $orderId);
                $updateStmt->execute();
                $updateStmt->close();
                cronLog("Order $orderId in $tableName status updated: $currentStatus -> $mappedStatus", 'SUCCESS');
                
                // Send SMS alert to admins if status changed to 'failed'
                if ($mappedStatus === 'failed' && $currentStatusLower !== 'failed') {
                    try {
                        require_once __DIR__ . '/../app/classes/AdminNotificationManager.php';
                        $adminNotifier = new AdminNotificationManager($conn);
                        
                        // Get order details for SMS
                        $orderDetails = [];
                        if ($tableName === 'agent_orders') {
                            $detailStmt = $conn->prepare("SELECT beneficiary_number, package_size, network_type FROM agent_orders WHERE id = ?");
                            $detailStmt->bind_param("i", $orderId);
                            $detailStmt->execute();
                            $detailResult = $detailStmt->get_result();
                            if ($detailRow = $detailResult->fetch_assoc()) {
                                $orderDetails = [
                                    'beneficiary_number' => $detailRow['beneficiary_number'] ?? 'N/A',
                                    'package_size' => $detailRow['package_size'] ?? 'N/A',
                                    'network_type' => $detailRow['network_type'] ?? 'N/A',
                                    'error' => 'Status changed to failed via status check'
                                ];
                            }
                            $detailStmt->close();
                        } else {
                            $detailStmt = $conn->prepare("SELECT beneficiary_number, package_size, network_type FROM orders WHERE id = ?");
                            $detailStmt->bind_param("i", $orderId);
                            $detailStmt->execute();
                            $detailResult = $detailStmt->get_result();
                            if ($detailRow = $detailResult->fetch_assoc()) {
                                $orderDetails = [
                                    'beneficiary_number' => $detailRow['beneficiary_number'] ?? 'N/A',
                                    'package_size' => $detailRow['package_size'] ?? 'N/A',
                                    'network_type' => $detailRow['network_type'] ?? 'N/A',
                                    'error' => 'Status changed to failed via status check'
                                ];
                            }
                            $detailStmt->close();
                        }
                        
                        if (!empty($orderDetails)) {
                            $adminNotifier->sendOrderFailedSMS($orderId, $orderDetails);
                            cronLog("SMS alert sent to admins for failed order $orderId", 'INFO');
                        }
                    } catch (Exception $e) {
                        cronLog("Failed to send order failure SMS alert: " . $e->getMessage(), 'ERROR');
                    }
                }
            } else {
                cronLog("Failed to prepare update statement for order $orderId in $tableName", 'ERROR');
            }
        } else {
            cronLog("Order $orderId: Status already matches ($currentStatus)", 'INFO');
        }
    } else {
        if (($data['success'] ?? false) && empty($orderData)) {
            cronLog("Failed to get status for order $orderId - Order not present in API payload", 'ERROR');
        } else {
            cronLog("Failed to get status for order $orderId - Invalid API response: " . substr($response, 0, 200), 'ERROR');
        }
    }
    
    // Small delay to avoid overwhelming the API
    usleep(500000); // 0.5 seconds
}

cronLog("=== CRON JOB COMPLETED ===");
cronLog("Total execution time: " . round((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']), 2) . " seconds");
cronLog("Memory usage: " . number_format(memory_get_usage(true)) . " bytes");
cronLog("");
?>
