<?php
/**
 * webhook_lib.php
 * One consistent way to send a merchant's webhook, whether it's a real
 * payment event or the "Test" button on API Details - both log to
 * webhook_deliveries so the merchant can see what actually happened.
 */

/**
 * @param array $payload associative array, sent as JSON
 * @return array ['ok' => bool, 'http_code' => int|null, 'response' => string]
 */
function send_webhook($conn, $userId, $webhookUrl, $event, $payload, $orderId = null) {
    $payloadJson = json_encode($payload);

    $webhookUrl = trim($webhookUrl ?? '');
    if ($webhookUrl !== '' && !preg_match('#^https?://#i', $webhookUrl)) {
        // Saved without a scheme (older data, or someone edited the DB
        // directly) - curl can't deliver to that, so add one rather than
        // silently failing every single time.
        $webhookUrl = 'https://' . $webhookUrl;
    }

    if (empty($webhookUrl)) {
        webhook_log($conn, $userId, $event, $orderId, '', $payloadJson, false, null, 'No webhook URL configured.');
        return ['ok' => false, 'http_code' => null, 'response' => 'No webhook URL configured.'];
    }

    $ch = curl_init($webhookUrl);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $payloadJson,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_TIMEOUT => 10,
        CURLOPT_CONNECTTIMEOUT => 5,
        // Do NOT follow redirects - a URL that just bounces (302 etc.)
        // isn't a real listening endpoint, and should count as a failed
        // delivery, not a false "success".
        CURLOPT_FOLLOWLOCATION => false,
    ]);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError = curl_error($ch);
    curl_close($ch);

    $ok = ($response !== false) && $httpCode >= 200 && $httpCode < 300;
    $responseSnippet = $response !== false ? substr($response, 0, 480) : ('cURL error: ' . $curlError);

    webhook_log($conn, $userId, $event, $orderId, $webhookUrl, $payloadJson, $ok, $httpCode ?: null, $responseSnippet);

    return ['ok' => $ok, 'http_code' => $httpCode ?: null, 'response' => $responseSnippet];
}

function webhook_log($conn, $userId, $event, $orderId, $url, $payloadJson, $ok, $httpCode, $responseSnippet) {
    $stmt = $conn->prepare("INSERT INTO webhook_deliveries (user_id, event, order_id, url, payload, status, http_code, response_snippet) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
    if (!$stmt) return; // table missing (migration not run) - fail silently, don't break the payment flow over logging
    $status = $ok ? 'Delivered' : 'Failed';
    $stmt->bind_param("isssssis", $userId, $event, $orderId, $url, $payloadJson, $status, $httpCode, $responseSnippet);
    $stmt->execute();
}

/**
 * Sends a realistic sample payload to the merchant's configured webhook -
 * this is what the "Test" button calls.
 */
function send_test_webhook($conn, $userId, $webhookUrl) {
    $payload = [
        'order_id'    => 'TEST_' . strtoupper(substr(md5(uniqid()), 0, 8)),
        'txn_id'      => 'TESTTXN' . time(),
        'status'      => 'Success',
        'amount'      => '1000.00',
        'pay_amount'  => '1000.00',
        'utr'         => '434554555',
        'test'        => true,
    ];
    return send_webhook($conn, $userId, $webhookUrl, 'payment.success (test)', $payload);
}
