<?php
require_once 'config.php';
require_once 'paypal_api.php';

header('Content-Type: application/json');

function rfSendTelegramPaymentMessage($chatId, $message) {
    global $BOT_TOKEN;

    if (empty($BOT_TOKEN) || empty($chatId)) return false;

    $url = "https://api.telegram.org/bot{$BOT_TOKEN}/sendMessage";
    $payload = [
        'chat_id' => $chatId,
        'text' => $message,
        'parse_mode' => 'HTML'
    ];

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $payload,
        CURLOPT_TIMEOUT => 20
    ]);

    $response = curl_exec($ch);
    curl_close($ch);

    @file_put_contents(__DIR__ . "/telegram_payment_notify.log", "[" . date("Y-m-d H:i:s") . "] " . $response . PHP_EOL, FILE_APPEND);
    return true;
}

function rfGetPaymentByReference($reference) {
    global $pdo;

    if (!preg_match('/RF-PAY-(\d+)/', $reference, $m)) return null;

    $id = (int)$m[1];

    try {
        $stmt = $pdo->prepare("SELECT * FROM payment_requests WHERE id = :id LIMIT 1");
        $stmt->execute([':id' => $id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row ?: null;
    } catch (Throwable $e) {
        @file_put_contents(__DIR__ . "/payment_db_error.log", "[" . date("Y-m-d H:i:s") . "] " . $e->getMessage() . PHP_EOL, FILE_APPEND);
        return null;
    }
}

function rfExtractCardMeta($response) {
    $card = $response['payment_source']['card'] ?? [];

    $brand = $card['brand'] ?? null;
    $last4 = $card['last_digits'] ?? null;
    $first6 = $card['bin_details']['bin'] ?? null;

    if (!empty($first6)) {
        $first6 = substr(preg_replace('/\D/', '', $first6), 0, 6);
    }

    if (!empty($last4)) {
        $last4 = substr(preg_replace('/\D/', '', $last4), -4);
    }

    $networkRef = null;

    if (isset($response['purchase_units']) && is_array($response['purchase_units'])) {
        foreach ($response['purchase_units'] as $unit) {
            if (isset($unit['payments']['captures']) && is_array($unit['payments']['captures'])) {
                foreach ($unit['payments']['captures'] as $cap) {
                    if (isset($cap['network_transaction_reference']['id'])) {
                        $networkRef = $cap['network_transaction_reference']['id'];
                    }
                    if (!$brand && isset($cap['network_transaction_reference']['network'])) {
                        $brand = $cap['network_transaction_reference']['network'];
                    }
                }
            }
        }
    }

    return [
        'card_brand' => $brand,
        'card_first6' => $first6 ?: null,
        'card_last4' => $last4 ?: null,
        'network_reference' => $networkRef
    ];
}

function rfProcessorCodes($processorResponse) {
    return [
        'processor_code' => $processorResponse['response_code'] ?? null,
        'cvv_code' => $processorResponse['cvv_code'] ?? null,
        'avs_code' => $processorResponse['avs_code'] ?? null
    ];
}

function rfFriendlyDeclineReason($processorCode) {
    if ($processorCode === 'PPAX') {
        return 'Issuer authorization declined. Possible reasons: insufficient balance, card limit, online/international restriction, or bank security decline.';
    }
    if ($processorCode === 'INSUFFICIENT_FUNDS') return 'Insufficient available balance.';
    if ($processorCode === 'INVALID_CVV') return 'Invalid CVV/security code.';
    if ($processorCode === 'EXPIRED_CARD') return 'Expired card.';
    if ($processorCode === 'TRANSACTION_NOT_ALLOWED') return 'Transaction type not allowed by card issuer.';
    return 'Payment authorization declined.';
}

function rfUpdatePaymentStatus($reference, $status, $orderId, $captureId, $response, $declineReason = null, $processorResponse = null) {
    global $pdo;

    if (!preg_match('/RF-PAY-(\d+)/', $reference, $m)) return false;

    $id = (int)$m[1];
    $meta = rfExtractCardMeta($response);
    $codes = rfProcessorCodes($processorResponse ?: []);

    try {
        if ($status === 'paid') {
            $stmt = $pdo->prepare("
                UPDATE payment_requests
                SET status = 'paid',
                    paypal_order_id = :paypal_order_id,
                    capture_id = :capture_id,
                    card_brand = :card_brand,
                    card_first6 = :card_first6,
                    card_last4 = :card_last4,
                    network_reference = :network_reference,
                    decline_reason = NULL,
                    processor_code = :processor_code,
                    cvv_code = :cvv_code,
                    avs_code = :avs_code,
                    paid_at = NOW()
                WHERE id = :id
            ");

            $stmt->execute([
                ':paypal_order_id' => $orderId,
                ':capture_id' => $captureId,
                ':card_brand' => $meta['card_brand'],
                ':card_first6' => $meta['card_first6'],
                ':card_last4' => $meta['card_last4'],
                ':network_reference' => $meta['network_reference'],
                ':processor_code' => $codes['processor_code'],
                ':cvv_code' => $codes['cvv_code'],
                ':avs_code' => $codes['avs_code'],
                ':id' => $id
            ]);

        } else {
            $stmt = $pdo->prepare("
                UPDATE payment_requests
                SET status = 'declined',
                    paypal_order_id = :paypal_order_id,
                    capture_id = :capture_id,
                    card_brand = :card_brand,
                    card_first6 = :card_first6,
                    card_last4 = :card_last4,
                    network_reference = :network_reference,
                    decline_reason = :decline_reason,
                    processor_code = :processor_code,
                    cvv_code = :cvv_code,
                    avs_code = :avs_code
                WHERE id = :id
            ");

            $stmt->execute([
                ':paypal_order_id' => $orderId,
                ':capture_id' => $captureId,
                ':card_brand' => $meta['card_brand'],
                ':card_first6' => $meta['card_first6'],
                ':card_last4' => $meta['card_last4'],
                ':network_reference' => $meta['network_reference'],
                ':decline_reason' => $declineReason,
                ':processor_code' => $codes['processor_code'],
                ':cvv_code' => $codes['cvv_code'],
                ':avs_code' => $codes['avs_code'],
                ':id' => $id
            ]);
        }

        @file_put_contents(__DIR__ . "/payment_db_success.log", "[" . date("Y-m-d H:i:s") . "] Updated {$reference} to {$status}" . PHP_EOL, FILE_APPEND);
        return true;

    } catch (Throwable $e) {
        @file_put_contents(__DIR__ . "/payment_db_error.log", "[" . date("Y-m-d H:i:s") . "] " . $e->getMessage() . PHP_EOL, FILE_APPEND);
        return false;
    }
}

function rfCardText($cardMeta) {
    if (!empty($cardMeta['card_first6']) && !empty($cardMeta['card_last4'])) {
        return strtoupper($cardMeta['card_brand'] ?? 'CARD') . ' ' . $cardMeta['card_first6'] . '******' . $cardMeta['card_last4'];
    }
    if (!empty($cardMeta['card_last4'])) {
        return strtoupper($cardMeta['card_brand'] ?? 'CARD') . ' ****' . $cardMeta['card_last4'];
    }
    return '';
}

$input = json_decode(file_get_contents("php://input"), true) ?: [];

$orderID = trim($input['orderID'] ?? '');
$reference = trim($input['reference'] ?? '');

if ($orderID === '') {
    echo json_encode(['ok' => false, 'status' => 'ERROR', 'error' => 'PayPal Order ID not received']);
    exit;
}

$before = paypalRequest("GET", "/v2/checkout/orders/" . urlencode($orderID));
paypalLog("ORDER_BEFORE_CAPTURE", $before['json']);

$capture = paypalRequest("POST", "/v2/checkout/orders/" . urlencode($orderID) . "/capture", new stdClass());
$response = $capture['json'] ?: [];

$captureData = extractPayPalCaptureData($response);

$orderStatus = $response['status'] ?? null;
$captureId = $captureData['capture_id'];
$captureStatus = $captureData['capture_status'];
$processorResponse = $captureData['processor_response'] ?: [];
$processorCode = $processorResponse['response_code'] ?? null;
$cardMeta = rfExtractCardMeta($response);

$isRealCaptured = (
    $capture['ok'] &&
    $orderStatus === 'COMPLETED' &&
    !empty($captureId) &&
    $captureStatus === 'COMPLETED'
);

if ($isRealCaptured) {
    $updated = rfUpdatePaymentStatus($reference, 'paid', $orderID, $captureId, $response, null, $processorResponse);

    $payment = rfGetPaymentByReference($reference);
    $chatId = $payment['chat_id'] ?? null;
    $amountValue = $captureData['amount']['value'] ?? ($payment['amount'] ?? '');
    $currencyCode = $captureData['amount']['currency_code'] ?? ($payment['currency'] ?? 'EUR');

    if ($chatId) {
        $cardLine = rfCardText($cardMeta);
        $cardText = $cardLine ? "\nCard: <b>" . htmlspecialchars($cardLine) . "</b>" : "";

        $msg =
            "✅ <b>Payment Approved Successfully</b>\n\n" .
            "Reference: <b>" . htmlspecialchars($reference) . "</b>\n" .
            "Amount: <b>" . htmlspecialchars($amountValue . " " . $currencyCode) . "</b>\n" .
            "Status: <b>COMPLETED</b>" .
            $cardText . "\n" .
            "Order ID: <code>" . htmlspecialchars($orderID) . "</code>\n" .
            "Capture ID: <code>" . htmlspecialchars($captureId) . "</code>\n" .
            "Date & Time: <b>" . date("d M Y, H:i:s") . "</b>";

        rfSendTelegramPaymentMessage($chatId, $msg);
    }

    echo json_encode([
        'ok' => true,
        'status' => 'COMPLETED',
        'db_updated' => $updated,
        'message' => 'Payment captured successfully',
        'order_id' => $orderID,
        'capture_id' => $captureId,
        'capture_status' => $captureStatus,
        'amount' => $captureData['amount'],
        'processor_response' => $processorResponse,
        'processor_summary' => safeProcessorSummary($processorResponse),
        'card_meta' => $cardMeta,
        'success_url' => 'success.php?ref=' . urlencode($reference) . '&order_id=' . urlencode($orderID) . '&capture_id=' . urlencode($captureId) . '&amount=' . urlencode($amountValue) . '&currency=' . urlencode($currencyCode),
        'paypal_response' => $response
    ]);
    exit;
}

$declineReason = rfFriendlyDeclineReason($processorCode);
$updated = rfUpdatePaymentStatus($reference, 'declined', $orderID, $captureId, $response, $declineReason, $processorResponse);

$payment = rfGetPaymentByReference($reference);
$chatId = $payment['chat_id'] ?? null;
$amountValue = $captureData['amount']['value'] ?? ($payment['amount'] ?? '');
$currencyCode = $captureData['amount']['currency_code'] ?? ($payment['currency'] ?? 'EUR');

if ($chatId) {
    $msg =
        "❌ <b>Payment Failed / Declined</b>\n\n" .
        "Your payment could not be completed. No successful charge was captured.\n\n" .
        "Reference: <b>" . htmlspecialchars($reference) . "</b>\n" .
        "Amount: <b>" . htmlspecialchars($amountValue . " " . $currencyCode) . "</b>\n" .
        "Status: <b>DECLINED</b>\n" .
        "Reason: <b>" . htmlspecialchars($declineReason) . "</b>\n" .
        "Order ID: <code>" . htmlspecialchars($orderID) . "</code>\n" .
        "Capture ID: <code>" . htmlspecialchars($captureId ?: '-') . "</code>\n" .
        "Processor: <code>" . htmlspecialchars(($processorCode ?: '-') . " / CVV: " . ($processorResponse['cvv_code'] ?? '-')) . "</code>\n" .
        "Date & Time: <b>" . date("d M Y, H:i:s") . "</b>\n\n" .
        "Please verify your card balance, card limits, and online/international payment permissions, or try another card.";

    rfSendTelegramPaymentMessage($chatId, $msg);
}

paypalLog("REAL_CAPTURE_DECLINED_RECORDED", [
    'order_id' => $orderID,
    'reference' => $reference,
    'db_updated' => $updated,
    'capture_id' => $captureId,
    'capture_status' => $captureStatus,
    'decline_reason' => $declineReason,
    'processor_response' => $processorResponse,
    'card_meta' => $cardMeta
]);

echo json_encode([
    'ok' => false,
    'status' => $orderStatus ?: 'DECLINED',
    'db_updated' => $updated,
    'error' => $declineReason,
    'order_id' => $orderID,
    'capture_id' => $captureId,
    'capture_status' => $captureStatus ?: 'DECLINED',
    'processor_response' => $processorResponse,
    'processor_summary' => safeProcessorSummary($processorResponse),
    'card_meta' => $cardMeta,
    'http_code' => $capture['http_code'],
    'order_before_capture' => $before['json'],
    'paypal_response' => $response,
    'raw_response' => $capture['raw']
]);
