<?php
header('Content-Type: application/json');
error_reporting(0); 

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

function api_response(bool $success, $data = null, ?string $message = null, int $http_code = 200) {
    http_response_code($http_code);
    $response = ['success' => $success];
    if ($message !== null) {
        if ($success) {
            $response['message'] = $message;
        } else {
            $response['error'] = $message; 
        }
    }
    if ($data !== null) {
        $response['data'] = $data;
    }
    echo json_encode($response);
    exit;
}

if (!isset($pdo) || !$pdo instanceof PDO) {
    api_response(false, null, 'Kesalahan internal server (DB Connection).', 500);
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    api_response(false, null, 'Metode request tidak valid. Hanya POST yang diizinkan.', 405);
}

$api_key = $_POST['api_key'] ?? null;
$action = $_POST['action'] ?? null;

if (empty($api_key)) {
    api_response(false, null, 'API key wajib diisi.', 401);
}

$auth = new Auth($pdo);
$user_id = $auth->validateApiKey($api_key);

if (!$user_id) {
    api_response(false, null, 'API key tidak valid atau tidak aktif.', 401);
}

if (empty($action)) {
    api_response(false, null, 'Parameter "action" wajib diisi.', 400);
}

try {
    switch (strtolower($action)) {
        case 'services':
            $stmtServices = $pdo->prepare("
                SELECT s.id as service_id, c.name as category, s.name, s.price_per_1000, s.min_order, s.max_order
                FROM services s
                JOIN categories c ON s.category_id = c.id
                WHERE s.status = 'active' AND c.status = 'active'
                ORDER BY c.name ASC, s.name ASC
            ");
            $stmtServices->execute();
            $services = $stmtServices->fetchAll(PDO::FETCH_ASSOC);
            api_response(true, $services);
            break;

        case 'add':
            $service_id = filter_input(INPUT_POST, 'service', FILTER_VALIDATE_INT);
            $target = sanitize_input($_POST['target'] ?? '');
            $quantity = filter_input(INPUT_POST, 'quantity', FILTER_VALIDATE_INT);
            $custom_comments = sanitize_input($_POST['custom_comments'] ?? null);
            $custom_link = sanitize_input($_POST['custom_link'] ?? null);


            if (!$service_id || empty($target) || !$quantity || $quantity <= 0) {
                api_response(false, null, 'Parameter service, target, dan quantity wajib diisi dengan benar.', 400);
            }

            $stmtService = $pdo->prepare("
                SELECT s.id as local_service_id, s.name as service_name, s.price_per_1000, s.min_order, s.max_order, s.provider_service_id,
                       p.api_url, p.api_id as provider_api_id, p.api_key as provider_api_key, p.secret_key as provider_secret_key
                FROM services s
                JOIN providers p ON s.provider_id = p.id
                WHERE s.id = :sid AND s.status = 'active' AND p.status = 'active'
                LIMIT 1
            ");
            $stmtService->bindParam(':sid', $service_id, PDO::PARAM_INT);
            $stmtService->execute();
            $serviceDetails = $stmtService->fetch(PDO::FETCH_ASSOC);

            if (!$serviceDetails) {
                api_response(false, null, 'Layanan tidak ditemukan, tidak aktif, atau provider tidak aktif.', 400);
            }

            if ($quantity < $serviceDetails['min_order']) {
                api_response(false, null, "Jumlah pesanan kurang dari minimum ({$serviceDetails['min_order']}).", 400);
            }
            if ($quantity > $serviceDetails['max_order']) {
                api_response(false, null, "Jumlah pesanan melebihi maksimum ({$serviceDetails['max_order']}).", 400);
            }

            $totalPrice = round(($quantity / 1000) * $serviceDetails['price_per_1000'], 2);

            $stmtUser = $pdo->prepare("SELECT balance FROM users WHERE id = :uid FOR UPDATE");
            $stmtUser->bindParam(':uid', $user_id, PDO::PARAM_INT);
            $stmtUser->execute();
            $user = $stmtUser->fetch(PDO::FETCH_ASSOC);

            if (!$user || $user['balance'] < $totalPrice) {
                api_response(false, null, 'Saldo tidak mencukupi.', 400);
            }

            $pdo->beginTransaction();

            $newBalance = $user['balance'] - $totalPrice;
            $stmtUpdateBalance = $pdo->prepare("UPDATE users SET balance = :new_balance WHERE id = :uid");
            $stmtUpdateBalance->bindParam(':new_balance', $newBalance);
            $stmtUpdateBalance->bindParam(':uid', $user_id, PDO::PARAM_INT);
            if (!$stmtUpdateBalance->execute()) {
                $pdo->rollBack();
                api_response(false, null, 'Gagal memperbarui saldo pengguna.', 500);
            }

            $initialStatus = 'pending';
            $providerApiOrderId = null;
            $providerApiResponse = null;
            $orderToProviderSuccess = false;

            if (!empty($serviceDetails['api_url']) && !empty($serviceDetails['provider_api_id']) && !empty($serviceDetails['provider_api_key'])) {
                $providerOrderUrl = rtrim($serviceDetails['api_url'], '/') . '/order';
                if (substr($serviceDetails['api_url'], -5) !== '/api/') {
                     $providerOrderUrl = rtrim($serviceDetails['api_url'], '/') . '/api/order';
                }


                $postDataToProvider = [
                    'api_id'     => $serviceDetails['provider_api_id'],
                    'api_key'    => $serviceDetails['provider_api_key'],
                    'service'    => $serviceDetails['provider_service_id'],
                    'target'     => $target,
                    'quantity'   => $quantity,
                ];
                if (!empty($serviceDetails['provider_secret_key'])) {
                    $postDataToProvider['secret_key'] = $serviceDetails['provider_secret_key'];
                }
                if ($custom_comments !== null) {
                    $postDataToProvider['custom_comments'] = $custom_comments;
                }
                if ($custom_link !== null) {
                    $postDataToProvider['custom_link'] = $custom_link;
                }

                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $providerOrderUrl);
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postDataToProvider));
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch, CURLOPT_TIMEOUT, 60); // Timeout 60 detik
                $apiResultJson = curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $curlError = curl_error($ch);
                curl_close($ch);

                $providerApiResponse = $apiResultJson ?: $curlError ?: "HTTP Code: " . $httpCode;

                if ($curlError || $httpCode !== 200) {
                    $initialStatus = 'error';
                    error_log("API Order to Provider Failed (cURL/HTTP Error): UserID {$user_id}, ServiceID {$service_id}, Target {$target}, Error: {$providerApiResponse}");
                } else {
                    $apiResult = json_decode($apiResultJson, true);
                    if (json_last_error() === JSON_ERROR_NONE && isset($apiResult['response']) && $apiResult['response'] === true && isset($apiResult['data']['id'])) {
                        $providerApiOrderId = $apiResult['data']['id'];
                        $initialStatus = 'processing'; // Atau status lain sesuai respons provider jika ada
                        $orderToProviderSuccess = true;
                    } else {
                        $initialStatus = 'error';
                        $providerApiResponse = $apiResult['data']['msg'] ?? $providerApiResponse; // Ambil pesan error dari provider jika ada
                        error_log("API Order to Provider Failed (API Logic Error): UserID {$user_id}, ServiceID {$service_id}, Target {$target}, Response: {$providerApiResponse}");
                    }
                }
            } else {
                $providerApiResponse = "Provider API details not configured for this service.";
                $initialStatus = 'pending'; // Atau 'error' jika direct order adalah wajib
                error_log("API Order Skipped (No Provider Details): UserID {$user_id}, ServiceID {$service_id}, Target {$target}");
            }

            if ($initialStatus === 'error' || !$orderToProviderSuccess && !empty($serviceDetails['api_url'])) {
                $stmtRollbackBalance = $pdo->prepare("UPDATE users SET balance = balance + :amount WHERE id = :uid");
                $stmtRollbackBalance->bindParam(':amount', $totalPrice);
                $stmtRollbackBalance->bindParam(':uid', $user_id, PDO::PARAM_INT);
                $stmtRollbackBalance->execute(); 
                $pdo->rollBack(); 
                api_response(false, null, "Gagal mengirim pesanan ke provider. " . ($providerApiResponse ?: 'Silakan coba lagi nanti atau hubungi support.'), 500);
            }
            
            $ip_address = $_SERVER['REMOTE_ADDR'] ?? null;

            $sqlInsertOrder = "INSERT INTO orders (user_id, service_id, target, quantity, price, status, order_source, api_order_id, api_response, custom_comments, custom_link, ip_address, created_at, updated_at)
                               VALUES (:uid, :sid, :target, :qty, :price, :status, 'API', :api_oid_prov, :api_resp, :custom_comments, :custom_link, :ip_address, NOW(), NOW())";
            $stmtInsertOrder = $pdo->prepare($sqlInsertOrder);
            $stmtInsertOrder->bindParam(':uid', $user_id, PDO::PARAM_INT);
            $stmtInsertOrder->bindParam(':sid', $service_id, PDO::PARAM_INT);
            $stmtInsertOrder->bindParam(':target', $target);
            $stmtInsertOrder->bindParam(':qty', $quantity, PDO::PARAM_INT);
            $stmtInsertOrder->bindParam(':price', $totalPrice);
            $stmtInsertOrder->bindParam(':status', $initialStatus);
            $stmtInsertOrder->bindParam(':api_oid_prov', $providerApiOrderId);
            $stmtInsertOrder->bindParam(':api_resp', $providerApiResponse);
            $stmtInsertOrder->bindParam(':custom_comments', $custom_comments);
            $stmtInsertOrder->bindParam(':custom_link', $custom_link);
            $stmtInsertOrder->bindParam(':ip_address', $ip_address);


            if (!$stmtInsertOrder->execute()) {
                error_log("CRITICAL: Failed to insert order locally AFTER provider interaction (if any). UserID {$user_id}, ProviderOrderID {$providerApiOrderId}");
                $stmtRollbackBalance = $pdo->prepare("UPDATE users SET balance = balance + :amount WHERE id = :uid");
                $stmtRollbackBalance->bindParam(':amount', $totalPrice);
                $stmtRollbackBalance->bindParam(':uid', $user_id, PDO::PARAM_INT);
                $stmtRollbackBalance->execute();
                $pdo->rollBack();
                api_response(false, null, 'Gagal menyimpan pesanan setelah interaksi provider.', 500);
            }
            $localOrderId = $pdo->lastInsertId();
            $pdo->commit();

            api_response(true, ['order_id' => $localOrderId], 'Pesanan berhasil dibuat.');
            break;

        case 'status':
            $order_id = filter_input(INPUT_POST, 'order_id', FILTER_VALIDATE_INT);
            if (!$order_id) {
                api_response(false, null, 'Parameter "order_id" wajib diisi dan harus berupa angka.', 400);
            }

            $stmtOrderStatus = $pdo->prepare("
                SELECT id as order_id, status, start_count, remains, quantity
                FROM orders
                WHERE id = :oid AND user_id = :uid
                LIMIT 1
            ");
            $stmtOrderStatus->bindParam(':oid', $order_id, PDO::PARAM_INT);
            $stmtOrderStatus->bindParam(':uid', $user_id, PDO::PARAM_INT);
            $stmtOrderStatus->execute();
            $orderStatus = $stmtOrderStatus->fetch(PDO::FETCH_ASSOC);

            if ($orderStatus) {
                api_response(true, $orderStatus);
            } else {
                api_response(false, null, 'Pesanan tidak ditemukan atau bukan milik Anda.', 404);
            }
            break;

        case 'balance':
            $stmtBalance = $pdo->prepare("SELECT balance FROM users WHERE id = :uid LIMIT 1");
            $stmtBalance->bindParam(':uid', $user_id, PDO::PARAM_INT);
            $stmtBalance->execute();
            $user = $stmtBalance->fetch(PDO::FETCH_ASSOC);

            if ($user) {
                api_response(true, ['balance' => number_format($user['balance'], 2, '.', ''), 'currency' => 'IDR']);
            } else {
                api_response(false, null, 'Pengguna tidak ditemukan.', 404);
            }
            break;

        default:
            api_response(false, null, 'Parameter "action" tidak valid.', 400);
            break;
    }

} catch (PDOException $e) {
    if (isset($pdo) && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    error_log("API Handler PDOException: " . $e->getMessage());
    api_response(false, null, 'Terjadi kesalahan database pada server.', 500);
} catch (Exception $e) {
    if (isset($pdo) && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    error_log("API Handler Exception: " . $e->getMessage());
    api_response(false, null, 'Terjadi kesalahan pada server: ' . $e->getMessage(), 500);
}
