<?php
/**
 * Cron Job / Manual Script - Update Order Status from Provider API
 *
 * Mengambil pesanan yang belum selesai (pending, processing, in progress),
 * menanyakan statusnya ke API provider, memperbarui data lokal,
 * dan menangani refund jika diperlukan.
 */

set_time_limit(600); // 10 menit
ini_set('memory_limit', '256M');

error_reporting(E_ALL);
ini_set('display_errors', 1);

require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../includes/db_connect.php'; 
require_once __DIR__ . '/../includes/functions.php'; 

echo "<h1>Memulai Update Status Pesanan</h1>";
echo "<pre>";

if (!isset($pdo) || !$pdo instanceof PDO) {
    die("FATAL ERROR: Koneksi database (\$pdo) tidak tersedia. Periksa db_connect.php dan log error.");
}

$statusesToCheck = ['pending', 'processing', 'in progress'];
$limitCheck = 50; // Ambil 50 pesanan per run

$statusPlaceholders = [];
$statusParams = [];
foreach ($statusesToCheck as $index => $status) {
    $key = ':status' . $index;
    $statusPlaceholders[] = $key;
    $statusParams[$key] = $status; 
}
$inClause = implode(',', $statusPlaceholders);
$sqlSelectOrders = "SELECT
                        o.id as local_order_id, o.api_order_id, o.user_id, o.price, o.quantity,
                        p.id as provider_id, p.api_url, p.api_id, p.api_key, p.secret_key
                    FROM orders o
                    JOIN services s ON o.service_id = s.id
                    JOIN providers p ON s.provider_id = p.id
                    WHERE o.api_order_id IS NOT NULL AND o.status IN ({$inClause})
                    ORDER BY o.updated_at ASC
                    LIMIT :limit";

try {
    $stmtSelect = $pdo->prepare($sqlSelectOrders);

    foreach ($statusParams as $key => $value) {
        $stmtSelect->bindValue($key, $value); 
    }
    $stmtSelect->bindParam(':limit', $limitCheck, PDO::PARAM_INT);
    $stmtSelect->execute();
    $ordersToCheck = $stmtSelect->fetchAll(PDO::FETCH_ASSOC);

    if (empty($ordersToCheck)) {
        echo "Tidak ada pesanan yang perlu dicek statusnya saat ini.\n";
        echo "</pre>";
        exit;
    }

    echo "Ditemukan " . count($ordersToCheck) . " pesanan untuk dicek statusnya...\n\n";

    $updatedCount = 0;
    $refundedCount = 0;
    $errorCount = 0;

    $sqlUpdateOrder = $pdo->prepare("UPDATE orders SET status = :status, start_count = :start_count, remains = :remains, api_response = :api_response, updated_at = NOW() WHERE id = :local_order_id");
    $stmtUpdateUserBalance = $pdo->prepare("UPDATE users SET balance = balance + :refund_amount WHERE id = :user_id");
    $stmtUpdateRespOnly = $pdo->prepare("UPDATE orders SET api_response = :resp, updated_at = NOW() WHERE id = :local_order_id");

    foreach ($ordersToCheck as $order) {
        echo "Memeriksa Pesanan Lokal ID: {$order['local_order_id']} (API Order ID: {$order['api_order_id']})... ";

        if (empty($order['api_url']) || empty($order['api_id']) || empty($order['api_key']) || empty($order['secret_key'])) {
            echo "[ERROR] Data API provider tidak lengkap. Melewati.\n";
            $errorCount++;
            continue;
        }

        $statusApiUrl = $order['api_url'];
        if (strpos($statusApiUrl, 'status') === false) {
             if(substr($statusApiUrl, -5) === '/api/'){ $statusApiUrl .= 'status'; }
             elseif (substr($statusApiUrl, -1) === '/') { $statusApiUrl .= 'api/status'; }
             else { $statusApiUrl .= '/api/status'; }
        }
         if (empty($statusApiUrl) || !filter_var($statusApiUrl, FILTER_VALIDATE_URL)) {
              echo "[ERROR] URL API Status tidak valid: " . htmlspecialchars($statusApiUrl) . ". Melewati.\n";
              $errorCount++;
              continue;
         }

        $postData = [
            'api_id'     => $order['api_id'], 'api_key'    => $order['api_key'],
            'secret_key' => $order['secret_key'], 'id' => $order['api_order_id']
        ];

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $statusApiUrl); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        $apiResultJson = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($ch);
        $apiResponseLog = $apiResultJson ?: $curlError ?: "HTTP: " . $httpCode;

        if ($curlError || $httpCode !== 200) {
            echo "[ERROR] Gagal menghubungi API ({$apiResponseLog}). Melewati.\n";
            $stmtUpdateRespOnly->execute([':resp' => $apiResponseLog, ':local_order_id' => $order['local_order_id']]);
            $errorCount++; continue;
        }

        $apiResult = json_decode($apiResultJson, true);
        if (json_last_error() !== JSON_ERROR_NONE || !isset($apiResult['response'])) {
            echo "[ERROR] Respons API tidak valid. Melewati.\n";
             $stmtUpdateRespOnly->execute([':resp' => $apiResponseLog, ':local_order_id' => $order['local_order_id']]);
            $errorCount++; continue;
        }

        if ($apiResult['response'] === false) {
            $apiMsg = $apiResult['data']['msg'] ?? 'API mengembalikan status gagal.';
            echo "[API FAIL] {$apiMsg}. Melewati.\n";
             $stmtUpdateRespOnly->execute([':resp' => $apiResponseLog, ':local_order_id' => $order['local_order_id']]);
            $errorCount++; continue;
        }

        if ($apiResult['response'] === true && isset($apiResult['data'])) {
            $apiData = $apiResult['data'];
            $newStatus = strtolower($apiData['status'] ?? '');
            $startCount = isset($apiData['start_count']) ? (int)$apiData['start_count'] : null;
            $remains = isset($apiData['remains']) ? (int)$apiData['remains'] : null;

            $validApiStatuses = ['pending', 'processing', 'success', 'error', 'partial', 'canceled', 'in progress'];
            if (!in_array($newStatus, $validApiStatuses)) {
                echo "[ERROR] Status dari API tidak valid ('{$newStatus}'). Melewati.\n";
                $errorCount++; continue;
            }

            $pdo->beginTransaction();
            try {
                $sqlUpdateOrder->bindParam(':status', $newStatus);
                $sqlUpdateOrder->bindParam(':start_count', $startCount, PDO::PARAM_INT);
                $sqlUpdateOrder->bindParam(':remains', $remains, PDO::PARAM_INT);
                $sqlUpdateOrder->bindParam(':api_response', $apiResponseLog);
                $sqlUpdateOrder->bindParam(':local_order_id', $order['local_order_id'], PDO::PARAM_INT);
                $sqlUpdateOrder->execute();
                $updatedCount++;
                echo "[OK] Status diperbarui menjadi '{$newStatus}'. ";

                // Logika Refund
                $refundAmount = 0;
                if ($newStatus === 'error' || $newStatus === 'canceled') {
                    $refundAmount = $order['price'];
                    echo "Melakukan refund penuh ({$refundAmount})... ";
                } elseif ($newStatus === 'partial' && $remains !== null && $remains >= 0 && $order['quantity'] > 0) {
                    $pricePerUnit = $order['price'] / $order['quantity'];
                    $refundAmount = round($remains * $pricePerUnit, 2);
                     echo "Melakukan refund partial ({$refundAmount} untuk {$remains} sisa)... ";
                }

                if ($refundAmount > 0) {
                    $stmtUpdateUserBalance->bindParam(':refund_amount', $refundAmount);
                    $stmtUpdateUserBalance->bindParam(':user_id', $order['user_id'], PDO::PARAM_INT);
                    if ($stmtUpdateUserBalance->execute()) {
                        echo "Refund berhasil. ";
                        $refundedCount++;
                    } else {
                         throw new Exception("Gagal update saldo user saat refund.");
                    }
                }
                $pdo->commit();
                echo "Selesai.\n";

            } catch (\Exception $e) {
                if ($pdo->inTransaction()) { $pdo->rollBack(); }
                echo "[ERROR DB] Gagal memproses update/refund: " . $e->getMessage() . ". Melewati.\n";
                error_log("Cron Update Status DB Error for Order ID {$order['local_order_id']}: " . $e->getMessage());
                $errorCount++;
            } 

        } else {
             echo "[WARN] Respons API sukses tapi data tidak ditemukan/valid. Melewati.\n";
             $stmtUpdateRespOnly->execute([':resp' => $apiResponseLog, ':local_order_id' => $order['local_order_id']]);
             $errorCount++;
        } 

    } 

    echo "\n=====================================\n";
    echo "Update Status Selesai!\n";
    echo "=====================================\n";
    echo "Pesanan Diperbarui: {$updatedCount}\n";
    echo "Pesanan Direfund: {$refundedCount}\n";
    echo "Pesanan Error/Dilewati: {$errorCount}\n";

} catch (\PDOException $e) {
    echo "\n=====================================\n";
    echo "ERROR DATABASE UTAMA!\n";
    echo "=====================================\n";
    echo "Pesan Error: " . $e->getMessage() . "\n";
    error_log("Cron Update Status PDO Exception: " . $e->getMessage());
} catch (\Throwable $e) {
     echo "\n=====================================\n";
    echo "ERROR UMUM!\n";
    echo "=====================================\n";
    echo "Pesan Error: " . $e->getMessage() . "\n";
    error_log("Cron Update Status General Error: " . $e->getMessage());
}

echo "</pre>";
?>
