<?php

function bayarvip_default_services_url(): string
{
    return 'https://api.bayar.vip/services';
}

function bayarvip_normalize_services_url(string $value): string
{
    $value = trim($value);

    if ($value === '') {
        return '';
    }

    if (!preg_match('/^https?:\/\//i', $value)) {
        return rtrim(bayarvip_default_services_url(), '/') . '/' . rawurlencode($value);
    }

    $value = rtrim($value, '/');
    $value = preg_replace('#/service/#i', '/services/', $value) ?? $value;
    $value = preg_replace('#/(CreatePayment|GetStatus)\.php$#i', '', $value) ?? $value;

    return $value;
}

function bayarvip_get_config(mysqli $db): array
{
    $query = mysqli_query(
        $db,
        "SELECT api_url, agent_code, secret_key FROM tb_api_config WHERE api_name = 'BAYARVIP' LIMIT 1"
    );

    if (!$query || mysqli_num_rows($query) === 0) {
        return [
            'configured' => false,
            'services_url' => '',
            'merchant' => '',
            'secret_key' => '',
        ];
    }

    $row = mysqli_fetch_assoc($query) ?: [];
    $servicesUrl = bayarvip_normalize_services_url((string)($row['api_url'] ?? ''));
    $merchant = trim((string)($row['agent_code'] ?? ''));
    $secretKey = trim((string)($row['secret_key'] ?? ''));

    $hasPlaceholder = stripos($servicesUrl, 'YOUR_API_KEY') !== false
        || stripos($merchant, 'YOUR_MERCHANT') !== false
        || stripos($secretKey, 'YOUR_OPERATOR') !== false;

    return [
        'configured' => $servicesUrl !== '' && $merchant !== '' && $secretKey !== '' && !$hasPlaceholder,
        'services_url' => $servicesUrl,
        'merchant' => $merchant,
        'secret_key' => $secretKey,
    ];
}

function bayarvip_is_configured(mysqli $db): bool
{
    $config = bayarvip_get_config($db);
    return !empty($config['configured']);
}

function bayarvip_endpoint(mysqli $db, string $action): string
{
    $config = bayarvip_get_config($db);
    return rtrim((string)$config['services_url'], '/') . '/' . $action . '.php';
}

function bayarvip_public_base_url(mysqli $db): string
{
    $config = bayarvip_get_config($db);
    $servicesUrl = (string)($config['services_url'] ?? '');

    if ($servicesUrl === '') {
        return 'https://api.bayar.vip';
    }

    $parts = parse_url($servicesUrl);

    if (!is_array($parts) || empty($parts['scheme']) || empty($parts['host'])) {
        return 'https://api.bayar.vip';
    }

    $base = $parts['scheme'] . '://' . $parts['host'];

    if (!empty($parts['port'])) {
        $base .= ':' . $parts['port'];
    }

    return $base;
}

function bayarvip_qr_url(mysqli $db, string $transactionId): string
{
    return rtrim(bayarvip_public_base_url($db), '/') . '/qris-image/' . rawurlencode($transactionId);
}

function bayarvip_create_signature(string $username, int $amount, string $secretKey): string
{
    return md5($username . $amount . $secretKey);
}

function bayarvip_callback_signature(string $transactionId, int $amount, string $secretKey): string
{
    return md5($transactionId . $amount . $secretKey);
}

function bayarvip_http_request(string $method, string $url, array $payload = []): array
{
    if (!function_exists('curl_init')) {
        return [
            'ok' => false,
            'status' => 0,
            'json' => null,
            'raw' => '',
            'error' => 'PHP cURL extension is not available.',
        ];
    }

    $method = strtoupper($method);
    $ch = curl_init($url);
    $headers = ['Accept: application/json'];

    $options = [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
    ];

    if ($method === 'POST') {
        $headers[] = 'Content-Type: application/json';
        $options[CURLOPT_POST] = true;
        $options[CURLOPT_POSTFIELDS] = json_encode($payload, JSON_UNESCAPED_SLASHES);
    }

    $options[CURLOPT_HTTPHEADER] = $headers;
    curl_setopt_array($ch, $options);

    $raw = curl_exec($ch);
    $error = curl_error($ch);
    $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $decoded = json_decode((string)$raw, true);

    return [
        'ok' => $error === '' && $status >= 200 && $status < 300 && is_array($decoded),
        'status' => $status,
        'json' => is_array($decoded) ? $decoded : null,
        'raw' => (string)$raw,
        'error' => $error,
    ];
}

function bayarvip_create_payment(mysqli $db, string $username, int $amount): array
{
    $config = bayarvip_get_config($db);

    if (empty($config['configured'])) {
        return ['ok' => false, 'code' => 'bayarvip_not_configured'];
    }

    $payload = [
        'merchant' => (string)$config['merchant'],
        'username' => $username,
        'amount' => $amount,
        'client_signature' => bayarvip_create_signature($username, $amount, (string)$config['secret_key']),
    ];

    $response = bayarvip_http_request('POST', bayarvip_endpoint($db, 'CreatePayment'), $payload);

    if (!$response['ok']) {
        if (function_exists('wa_log')) {
            $json = is_array($response['json'] ?? null) ? $response['json'] : [];
            wa_log('bayarvip_create_failed', [
                'http_status' => $response['status'] ?? 0,
                'api_code' => $json['code'] ?? null,
                'api_message' => $json['message'] ?? null,
                'curl_error' => $response['error'] ?? '',
                'endpoint' => preg_replace('#/services/([^/]+)#', '/services/***', bayarvip_endpoint($db, 'CreatePayment')),
                'merchant' => (string)$config['merchant'],
                'username' => $username,
                'amount' => $amount,
            ]);
        }

        return [
            'ok' => false,
            'code' => 'bayarvip_failed',
            'message' => $response['error'] !== '' ? $response['error'] : 'BayarVIP request failed.',
            'response' => $response,
        ];
    }

    $json = $response['json'] ?? [];
    $data = is_array($json['data'] ?? null) ? $json['data'] : [];

    if ((int)($json['code'] ?? 0) !== 200 || trim((string)($data['transaction_id'] ?? '')) === '') {
        if (function_exists('wa_log')) {
            wa_log('bayarvip_create_invalid_response', [
                'http_status' => $response['status'] ?? 0,
                'api_code' => $json['code'] ?? null,
                'api_message' => $json['message'] ?? null,
                'data_keys' => array_keys($data),
                'endpoint' => preg_replace('#/services/([^/]+)#', '/services/***', bayarvip_endpoint($db, 'CreatePayment')),
                'merchant' => (string)$config['merchant'],
                'username' => $username,
                'amount' => $amount,
            ]);
        }

        return [
            'ok' => false,
            'code' => 'bayarvip_invalid_response',
            'message' => trim((string)($json['message'] ?? 'BayarVIP response is invalid.')),
            'response' => $response,
        ];
    }

    return [
        'ok' => true,
        'data' => $data,
        'response' => $response,
    ];
}

function bayarvip_get_status(mysqli $db, string $transactionId): array
{
    $config = bayarvip_get_config($db);

    if (empty($config['configured'])) {
        return ['ok' => false, 'code' => 'bayarvip_not_configured'];
    }

    $url = bayarvip_endpoint($db, 'GetStatus')
        . '?merchant=' . rawurlencode((string)$config['merchant'])
        . '&transaction_id=' . rawurlencode($transactionId);

    $response = bayarvip_http_request('GET', $url);

    if (!$response['ok']) {
        return [
            'ok' => false,
            'code' => 'bayarvip_failed',
            'message' => $response['error'] !== '' ? $response['error'] : 'BayarVIP status request failed.',
            'response' => $response,
        ];
    }

    $json = $response['json'] ?? [];
    $data = is_array($json['data'] ?? null) ? $json['data'] : [];

    if ((int)($json['code'] ?? 0) !== 200 || trim((string)($data['transaction_id'] ?? '')) === '') {
        return [
            'ok' => false,
            'code' => 'bayarvip_invalid_response',
            'message' => trim((string)($json['message'] ?? 'BayarVIP status response is invalid.')),
            'response' => $response,
        ];
    }

    return [
        'ok' => true,
        'data' => $data,
        'response' => $response,
    ];
}

function bayarvip_callback_url(): string
{
    if (function_exists('wa_app_url')) {
        return wa_app_url('function/bayarvip_callback.php');
    }

    $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
        || (($_SERVER['SERVER_PORT'] ?? '') === '443');
    $scheme = $https ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'localhost';

    return $scheme . '://' . $host . '/function/bayarvip_callback.php';
}

function bayarvip_verify_callback(mysqli $db, array $payload): bool
{
    $config = bayarvip_get_config($db);

    if (empty($config['configured'])) {
        return false;
    }

    $transactionId = trim((string)($payload['transaction_id'] ?? ''));
    $amount = (int)($payload['amount'] ?? 0);
    $signature = trim((string)($payload['signature'] ?? ''));

    if ($transactionId === '' || $amount <= 0 || $signature === '') {
        return false;
    }

    $expected = bayarvip_callback_signature($transactionId, $amount, (string)$config['secret_key']);

    return hash_equals($expected, $signature);
}

function bayarvip_status_action(array $payload): ?string
{
    $status = (string)($payload['status'] ?? '');
    $statusText = strtolower(trim((string)(
        $payload['provider_status']
        ?? $payload['status_text']
        ?? $payload['local_status']
        ?? ''
    )));

    $successTexts = ['settlement', 'paid', 'success', 'completed'];
    $failedTexts = ['cancel', 'canceled', 'cancelled', 'failed', 'denied', 'expire', 'expired', 'timeout'];

    if ((int)$status === 1 || in_array($statusText, $successTexts, true)) {
        return 'Success';
    }

    if ((int)$status === 2 || in_array($statusText, $failedTexts, true)) {
        return 'Cancel';
    }

    return null;
}
