<?php

declare(strict_types=1);

/*
 * PaypalServerSDKLib
 *
 * This file was automatically generated by APIMATIC v3.0 ( https://www.apimatic.io ).
 */

namespace PaypalServerSDKLib\Tests\E2E;

use Exception;
use PaypalServerSDKLib\Controllers\OrdersController;
use PaypalServerSDKLib\Controllers\VaultController;
use PaypalServerSDKLib\Models\Builders\AddressBuilder;
use PaypalServerSDKLib\Models\Builders\AmountBreakdownBuilder;
use PaypalServerSDKLib\Models\Builders\AmountWithBreakdownBuilder;
use PaypalServerSDKLib\Models\Builders\ItemBuilder;
use PaypalServerSDKLib\Models\Builders\MoneyBuilder;
use PaypalServerSDKLib\Models\Builders\OrderRequestBuilder;
use PaypalServerSDKLib\Models\Builders\PaymentSourceBuilder;
use PaypalServerSDKLib\Models\Builders\PaymentTokenRequestBuilder;
use PaypalServerSDKLib\Models\Builders\PaymentTokenRequestPaymentSourceBuilder;
use PaypalServerSDKLib\Models\Builders\PayPalWalletBuilder;
use PaypalServerSDKLib\Models\Builders\PurchaseUnitRequestBuilder;
use PaypalServerSDKLib\Models\Builders\SetupTokenRequestBuilder;
use PaypalServerSDKLib\Models\Builders\SetupTokenRequestPaymentSourceBuilder;
use PaypalServerSDKLib\Models\Builders\ShippingDetailsBuilder;
use PaypalServerSDKLib\Models\Builders\VaultExperienceContextBuilder;
use PaypalServerSDKLib\Models\Builders\VaultPayPalWalletRequestBuilder;
use PaypalServerSDKLib\Models\Builders\VaultTokenRequestBuilder;
use PaypalServerSDKLib\Models\CheckoutPaymentIntent;
use PaypalServerSDKLib\Models\PaymentTokenResponse;
use PaypalServerSDKLib\Models\SetupTokenResponse;
use PaypalServerSDKLib\Models\TokenRequestType;
use PaypalServerSDKLib\Tests\Controllers\BaseTestController;
use PaypalServerSDKLib\Tests\WebDriverUtilities;

class PaymentMethodWithoutPurchaseFlowTest extends BaseTestController
{
    /**
     * @var OrdersController OrdersController instance
     */
    protected static $ordersController;

    /**
     * @var VaultController VaultController instance
     */
    protected static $vaultController;

    /**
     * Setup test class
     */
    public static function setUpBeforeClass(): void
    {
        $client = parent::getClient();
        self::$ordersController = $client->getOrdersController();
        self::$vaultController = $client->getVaultController();
    }

    public function testCreateSetupToken(): SetupTokenResponse
    {
        $request = [
            'payPalRequestId' => strval(rand(1, 99999999999)),
            'body' => SetupTokenRequestBuilder::init(
                SetupTokenRequestPaymentSourceBuilder::init()
                    ->paypal(
                        VaultPayPalWalletRequestBuilder::init()
                            ->description('Description for PayPal to be shown to PayPal payer')
                            ->permitMultiplePaymentTokens(true)
                            ->usageType('MERCHANT')
                            ->customerType('CONSUMER')
                            ->experienceContext(
                                VaultExperienceContextBuilder::init()
                                    ->returnUrl('https://example.com/returnUrl')
                                    ->cancelUrl('https://example.com/cancelUrl')
                                    ->build()
                            )
                            ->build()
                    )->build()
            )->build()
        ];

        $response = self::$vaultController->setupTokensCreate($request);

        $this->assertTrue($response->isSuccess());
        $this->assertEquals(201, $response->getStatusCode());

        return $response->getResult();
    }

    /**
     * @depends testCreateSetupToken
     * @throws Exception
     */
    public function testSavePaymentMethod(SetupTokenResponse $setupTokenDetail): void
    {
        $links = $setupTokenDetail->getLinks();
        $url = null;
        if (isset($links)) {
            $url = $links[1]->getHref();
        }
        $this->assertNotNull($url);
        WebDriverUtilities::savePaymentMethod($url ?? '');
    }

    /**
     * @depends testCreateSetupToken
     * @depends testSavePaymentMethod
     */
    public function testCreatePaymentToken(SetupTokenResponse $setupTokenResponse): PaymentTokenResponse
    {
        $request = [
            'payPalRequestId' => strval(rand(1, 99999999999)),
            'body' => PaymentTokenRequestBuilder::init(
                PaymentTokenRequestPaymentSourceBuilder::init()
                    ->token(
                        VaultTokenRequestBuilder::init(
                            $setupTokenResponse->getId() ?? '',
                            TokenRequestType::SETUP_TOKEN
                        )->build()
                    )->build()
            )->build()
        ];

        $response = self::$vaultController->paymentTokensCreate($request);

        $this->assertTrue($response->isSuccess());
        $this->assertEquals(201, $response->getStatusCode());

        return $response->getResult();
    }

    /**
     * @depends testCreatePaymentToken
     */
    public function testCreateOrder(PaymentTokenResponse $paymentToken): void
    {
        $request = [
            'body' => OrderRequestBuilder::init(
                CheckoutPaymentIntent::CAPTURE,
                [
                    PurchaseUnitRequestBuilder::init(
                        AmountWithBreakdownBuilder::init(
                            'USD',
                            '10.00'
                        )
                            ->breakdown(
                                AmountBreakdownBuilder::init()
                                    ->itemTotal(
                                        MoneyBuilder::init(
                                            'USD',
                                            '10.00'
                                        )->build()
                                    )->build()
                            )->build()
                    )
                        ->description('Camera Shop')
                        ->items([
                            ItemBuilder::init(
                                'Camera',
                                MoneyBuilder::init(
                                    'USD',
                                    '10.00'
                                )->build(),
                                '1'
                            )->build(),
                        ])
                        ->shipping(
                            ShippingDetailsBuilder::init()
                                ->address(
                                    AddressBuilder::init(
                                        'US'
                                    )
                                        ->addressLine1('500 Main Street')
                                        ->addressLine2('#1000')
                                        ->adminArea1('CA')
                                        ->adminArea2('San Jose')
                                        ->postalCode('95131')
                                        ->build()
                                )->build()
                        )->build()
                ]
            )
                ->paymentSource(
                    PaymentSourceBuilder::init()
                        ->paypal(
                            PayPalWalletBuilder::init()
                                ->vaultId($paymentToken->getId())
                                ->build()
                        )
                        ->build()
                )
                ->build(),
            'payPalRequestId' => strval(rand(1, 99999999999)),
            'prefer' => 'return=representation'
        ];

        $response = self::$ordersController->ordersCreate($request);

        $this->assertTrue($response->isSuccess());
        $this->assertEquals(201, $response->getStatusCode());
    }

    /**
     * @depends testCreateSetupToken
     * @depends testCreateOrder
     */
    public function testGetSetupToken(SetupTokenResponse $setupTokenDetail): void
    {
        $response = self::$vaultController->setupTokensGet($setupTokenDetail->getId() ?? '');

        $this->assertTrue($response->isSuccess());
        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('VAULTED', $response->getResult()->getStatus());
    }

    /**
     * @depends testCreatePaymentToken
     * @depends testGetSetupToken
     */
    public function testGetPaymentToken(PaymentTokenResponse $paymentToken): void
    {
        $response = self::$vaultController->paymentTokensGet($paymentToken->getId() ?? '');

        $this->assertTrue($response->isSuccess());
        $this->assertEquals(200, $response->getStatusCode());
        $this->assertNotNull($response);
    }
}
