<?php

use Modules\Payment\Contracts\PaymentGatewayInterface;
use Modules\Payment\Data\PaymentRequestData;
use Modules\Payment\Data\PaymentResultData;
use Modules\Payment\Data\RefundResultData;
use Modules\Payment\Enums\PaymentMethod;
use Modules\Payment\Enums\PaymentStatus;
use Modules\Payment\Enums\RefundStatus;
use Modules\Payment\Factories\PaymentGatewayFactory;
use Modules\Payment\Services\PaymentService;

test('initiate resolves the gateway for the request method and delegates to its initiate()', function () {
    $gateway = Mockery::mock(PaymentGatewayInterface::class);
    $data = new PaymentRequestData(
        bookingId: 1,
        merchantOrderId: 'EVB-001',
        amount: '15000',
        currency: 'MMK',
        method: PaymentMethod::KbzMiniApp,
    );
    $expected = new PaymentResultData(status: PaymentStatus::Pending, gatewayTransactionId: 'EVB-001', gatewayPayload: []);

    $gateway->shouldReceive('initiate')->once()->with($data)->andReturn($expected);

    $factory = Mockery::mock(PaymentGatewayFactory::class);
    $factory->shouldReceive('make')->once()->with(PaymentMethod::KbzMiniApp)->andReturn($gateway);

    $result = (new PaymentService($factory))->initiate($data);

    expect($result)->toBe($expected);
});

test('verify resolves the gateway for the given method and delegates to its verify()', function () {
    $gateway = Mockery::mock(PaymentGatewayInterface::class);
    $expected = new PaymentResultData(status: PaymentStatus::Completed, gatewayTransactionId: 'EVB-001', gatewayPayload: []);

    $gateway->shouldReceive('verify')->once()->with('EVB-001')->andReturn($expected);

    $factory = Mockery::mock(PaymentGatewayFactory::class);
    $factory->shouldReceive('make')->once()->with(PaymentMethod::KbzMiniApp)->andReturn($gateway);

    $result = (new PaymentService($factory))->verify(PaymentMethod::KbzMiniApp, 'EVB-001');

    expect($result)->toBe($expected);
});

test('refund resolves the gateway for the given method and delegates to its refund()', function () {
    $gateway = Mockery::mock(PaymentGatewayInterface::class);
    $expected = new RefundResultData(status: RefundStatus::Completed, gatewayRefundId: 'REFUND-1', gatewayPayload: []);

    $gateway->shouldReceive('refund')->once()->with('EVB-001', '8000', 'customer request')->andReturn($expected);

    $factory = Mockery::mock(PaymentGatewayFactory::class);
    $factory->shouldReceive('make')->once()->with(PaymentMethod::KbzMiniApp)->andReturn($gateway);

    $result = (new PaymentService($factory))->refund(PaymentMethod::KbzMiniApp, 'EVB-001', '8000', 'customer request');

    expect($result)->toBe($expected);
});
