<?php

use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Facades\Http;
use Modules\Payment\Data\PaymentRequestData;
use Modules\Payment\Enums\PaymentMethod;
use Modules\Payment\Enums\PaymentStatus;
use Modules\Payment\Gateways\KbzMiniAppGateway;
use Modules\Payment\Support\KbzSignature;

$config = [
    'app_id' => 'APPID123',
    'merchant_code' => 'MERCH001',
    'merchant_key' => 'test-merchant-key',
    'base_url' => 'https://kbz.test/gateway',
    'notify_url' => 'https://app.test/api/v1/webhooks/kbz',
];

$paymentRequest = new PaymentRequestData(
    bookingId: 1,
    merchantOrderId: 'EVB-FIXTURE-001',
    amount: '15000',
    currency: 'MMK',
    method: PaymentMethod::KbzMiniApp,
);

test('initiate posts a correctly signed precreate request to the configured base_url', function () use ($config, $paymentRequest) {
    Http::fake(['kbz.test/*' => Http::response(['Response' => ['result' => 'SUCCESS', 'prepay_id' => 'PREPAY123']])]);

    (new KbzMiniAppGateway($config))->initiate($paymentRequest);

    Http::assertSent(function ($request) {
        $body = $request->data()['Request'];

        return $request->url() === 'https://kbz.test/gateway'
            && $body['method'] === 'kbz.payment.precreate'
            && $body['sign_type'] === 'SHA256'
            && $body['biz_content']['appid'] === 'APPID123'
            && $body['biz_content']['merch_code'] === 'MERCH001'
            && $body['biz_content']['merch_order_id'] === 'EVB-FIXTURE-001'
            && $body['biz_content']['trade_type'] === 'MINIAPP'
            && $body['biz_content']['total_amount'] === '15000'
            && $body['biz_content']['trans_currency'] === 'MMK'
            && $body['sign'] === KbzSignature::sign($body, 'test-merchant-key');
    });
});

test('initiate returns a pending PaymentResultData on a successful precreate', function () use ($config, $paymentRequest) {
    Http::fake(['kbz.test/*' => Http::response(['Response' => ['result' => 'SUCCESS', 'prepay_id' => 'PREPAY123']])]);

    $result = (new KbzMiniAppGateway($config))->initiate($paymentRequest);
    logger()->info('Payment initiation result', ['result' => $result]);
    expect($result->status)->toBe(PaymentStatus::Pending)
        ->and($result->gatewayTransactionId)->toBe('EVB-FIXTURE-001')
        ->and($result->gatewayPayload['prepayId'])->toBe('PREPAY123');
});

test('initiate returns a failed PaymentResultData when KBZ rejects the request', function () use ($config, $paymentRequest) {
    Http::fake(['kbz.test/*' => Http::response(['Response' => ['result' => 'FAIL', 'msg' => 'Invalid merchant']])]);

    $result = (new KbzMiniAppGateway($config))->initiate($paymentRequest);

    expect($result->status)->toBe(PaymentStatus::Failed)
        ->and($result->gatewayTransactionId)->toBeNull()
        ->and($result->message)->toBe('Invalid merchant');
});

test('initiate returns a failed PaymentResultData when the connection fails', function () use ($config, $paymentRequest) {
    Http::fake(['kbz.test/*' => fn () => throw new ConnectionException('Connection refused')]);

    $result = (new KbzMiniAppGateway($config))->initiate($paymentRequest);

    expect($result->status)->toBe(PaymentStatus::Failed)
        ->and($result->gatewayTransactionId)->toBeNull()
        ->and($result->gatewayPayload)->toBe([])
        ->and($result->message)->toBe('Connection refused');
});
