<?php

// Prevent direct script access
if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME'])) {
    die('No direct script access allowed');
}

// --- Zarinpal Payment Gateway Service ---

/**
 * Requests a payment transaction from Zarinpal.
 *
 * @param int $amount_rial Amount in Rials.
 * @param string $description Description for the transaction.
 * @param string $callback_url The URL Zarinpal redirects to after payment attempt.
 * @param array $metadata Optional metadata (e.g., ['mobile' => '09xxxxxxxxx']).
 * @return array Result array with 'success' (bool), 'authority' (string|null), 'payment_url' (string|null), 'message' (string).
 */
function requestZarinpalPayment(int $amount_rial, string $description, string $callback_url, array $metadata = []): array {
    if (!defined('ZARINPAL_MERCHANT_ID') || !defined('ZARINPAL_API_REQUEST_URL') || !defined('ZARINPAL_STARTPAY_URL')) {
        return ['success' => false, 'authority' => null, 'payment_url' => null, 'message' => 'پیکربندی زرین‌پال ناقص است.'];
    }

    $data = [
        "merchant_id" => ZARINPAL_MERCHANT_ID,
        "amount" => $amount_rial,
        "callback_url" => $callback_url,
        "description" => $description,
    ];
    if (!empty($metadata)) {
        $data["metadata"] = $metadata;
    }
    $jsonData = json_encode($data);

    $ch = curl_init(ZARINPAL_API_REQUEST_URL);
    curl_setopt($ch, CURLOPT_USERAGENT, 'ZarinPal Rest Api v4');
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Content-Length: ' . strlen($jsonData)]);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    // Consider SSL verification in production
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    $result = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curl_error = curl_error($ch);
    curl_close($ch);

    // Log the request and response
    $log_msg = "--- Zarinpal Request ---\nData: {$jsonData}\nHTTP: {$http_code}\nError: {$curl_error}\nResponse: {$result}\n---\n";
    if (defined('ERROR_LOG_PATH')) { file_put_contents(ERROR_LOG_PATH, $log_msg, FILE_APPEND); }

    if ($curl_error) {
        return ['success' => false, 'authority' => null, 'payment_url' => null, 'message' => 'خطا در اتصال به زرین‌پال: ' . $curl_error];
    }

    $resultData = json_decode($result, true);
    
    // Check for successful request (code 100) and presence of authority
    if ($http_code == 200 && isset($resultData['data']['code']) && $resultData['data']['code'] == 100 && !empty($resultData['data']['authority'])) {
        $authority = $resultData['data']['authority'];
        $payment_url = ZARINPAL_STARTPAY_URL . $authority;
        return ['success' => true, 'authority' => $authority, 'payment_url' => $payment_url, 'message' => 'درخواست پرداخت ایجاد شد.'];
    } else {
        // Handle Zarinpal specific errors
        $error_code = $resultData['errors']['code'] ?? ($resultData['data']['code'] ?? $http_code); 
        $error_message = zarinpalErrorCodeToMessage($error_code); 
        return ['success' => false, 'authority' => null, 'payment_url' => null, 'message' => "خطا از زرین‌پال ({$error_code}): " . $error_message];
    }
}

/**
 * Verifies a Zarinpal payment transaction.
 *
 * @param int $amount_rial Amount in Rials (must match the request amount).
 * @param string $authority The authority code received from Zarinpal.
 * @return array Result array with 'success' (bool), 'ref_id' (string|null), 'card_pan' (string|null), 'message' (string), 'code' (int Zarinpal status code).
 */
function verifyZarinpalPayment(int $amount_rial, string $authority): array {
    if (!defined('ZARINPAL_MERCHANT_ID') || !defined('ZARINPAL_API_VERIFY_URL')) {
        return ['success' => false, 'ref_id' => null, 'card_pan' => null, 'message' => 'پیکربندی تایید زرین‌پال ناقص است.', 'code' => -999];
    }

    $data = [
        "merchant_id" => ZARINPAL_MERCHANT_ID,
        "amount" => $amount_rial,
        "authority" => $authority,
    ];
    $jsonData = json_encode($data);

    $ch = curl_init(ZARINPAL_API_VERIFY_URL);
    curl_setopt($ch, CURLOPT_USERAGENT, 'ZarinPal Rest Api v4');
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Content-Length: ' . strlen($jsonData)]);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_TIMEOUT, 40); // Slightly longer timeout for verification
    // Consider SSL verification in production
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    $result = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curl_error = curl_error($ch);
    curl_close($ch);

    // Log the verification attempt
    $log_msg = "--- Zarinpal Verify ---\nData: {$jsonData}\nHTTP: {$http_code}\nError: {$curl_error}\nResponse: {$result}\n---\n";
    if (defined('ERROR_LOG_PATH')) { file_put_contents(ERROR_LOG_PATH, $log_msg, FILE_APPEND); }

    if ($curl_error) {
        return ['success' => false, 'ref_id' => null, 'card_pan' => null, 'message' => 'خطا در اتصال به زرین‌پال برای تایید: ' . $curl_error, 'code' => -998]; // Custom code for cURL error
    }

    $resultData = json_decode($result, true);
    $zarinpal_code = $resultData['errors']['code'] ?? ($resultData['data']['code'] ?? $http_code); // Determine the code

    // Check for successful verification (code 100) or already verified (code 101)
    if ($http_code == 200 && isset($resultData['data']['code']) && ($resultData['data']['code'] == 100 || $resultData['data']['code'] == 101)) {
        return [
            'success' => true,
            'ref_id' => $resultData['data']['ref_id'] ?? null,
            'card_pan' => $resultData['data']['card_pan'] ?? null, // Masked card number
            'message' => ($resultData['data']['code'] == 101) ? 'پرداخت قبلا تایید شده است.' : 'پرداخت با موفقیت تایید شد.',
            'code' => (int)$resultData['data']['code']
        ];
    } else {
        // Handle verification errors
        $error_message = zarinpalErrorCodeToMessage($zarinpal_code);
        return [
            'success' => false,
            'ref_id' => null,
            'card_pan' => null,
            'message' => "خطا در تایید پرداخت ({$zarinpal_code}): " . $error_message,
            'code' => (int)$zarinpal_code
        ];
    }
}

/**
 * Translates Zarinpal error codes to Persian messages.
 */
function zarinpalErrorCodeToMessage($code): string {
    // Cast code to integer for array lookup safety
    $code = (int)$code;
    $messages = [
        100 => 'تراکنش با موفقیت انجام گردید', 
        101 => 'عمليات پرداخت موفق بوده و قبلا عملیات وریفای روی اين تراكنش انجام شده است',
        -9 => 'خطا در اعتبار سنجی', 
        -10 => 'آی پی یا مرچنت كد پذيرنده صحيح نمی باشد',
        -11 => 'مرچنت کد فعال نیست',
        -12 => 'تلاش بیش از حد در یک بازه زمانی کوتاه',
        -15 => 'ترمینال شما به حالت تعلیق در آمده با پشتیبانی تماس بگیرید',
        -16 => 'سطح تایید پذیرنده پایین تر از سطح نقره ای است',
        -30 => 'اجازه دسترسی به تسویه اشتراکی شناور ندارید',
        -31 => 'حساب بانکی تسویه را به پنل اضافه کنید مقادیر وارد شده برای تسهیم درست نمی باشد',
        -32 => 'مبلغ وارد شده از نرخ تعیین شده در زرین پال کمتر است',
        -33 => 'درصد های وارد شده صحيح نمی باشد',
        -34 => 'مبلغ از کل تراکنش بیشتر است',
        -35 => 'تعداد افراد دریافت کننده تسهیم بیش از حد مجاز است',
        -40 => 'پارامترهای ارسالی نامعتبر است',
        -50 => 'مبلغ پرداخت شده با مبلغ وریفای متفاوت است',
        -51 => 'پرداخت ناموفق',
        -52 => 'خطای غیر منتظره ای رخ داده است',
        -53 => 'اتوریتی نامعتبر است',
        -54 => 'اتوریتی منقضی شده است',
        // Add common HTTP codes if needed
        404 => 'آدرس API یافت نشد',
        500 => 'خطای سرور زرین‌پال',
    ]; 
    return $messages[$code] ?? "خطای تعریف نشده (کد: {$code})"; 
}

?>
