<?php

declare(strict_types=1);

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

namespace PaypalServerSdkLib\Controllers;

use Core\Request\Parameters\BodyParam;
use Core\Request\Parameters\HeaderParam;
use Core\Request\Parameters\QueryParam;
use Core\Request\Parameters\TemplateParam;
use Core\Response\Types\ErrorType;
use CoreInterfaces\Core\Request\RequestMethod;
use PaypalServerSdkLib\Exceptions\SubscriptionErrorException;
use PaypalServerSdkLib\Http\ApiResponse;
use PaypalServerSdkLib\Models\BillingPlan;
use PaypalServerSdkLib\Models\ModifySubscriptionResponse;
use PaypalServerSdkLib\Models\PlanCollection;
use PaypalServerSdkLib\Models\Subscription;
use PaypalServerSdkLib\Models\SubscriptionCollection;
use PaypalServerSdkLib\Models\SubscriptionTransactionDetails;
use PaypalServerSdkLib\Models\TransactionsList;

class SubscriptionsController extends BaseController
{
    /**
     * Creates a plan that defines pricing and billing cycle details for subscriptions.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function createBillingPlan(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::POST, '/v1/billing/plans')
            ->auth('Oauth2')
            ->parameters(
                HeaderParam::init('Content-Type', 'application/json'),
                HeaderParam::init('Prefer', $options)->extract('prefer', 'return=minimal'),
                HeaderParam::init('PayPal-Request-Id', $options)->extract('paypalRequestId'),
                BodyParam::init($options)->extract('body')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Bad Request. Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->type(BillingPlan::class)
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Lists billing plans.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function listBillingPlans(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::GET, '/v1/billing/plans')
            ->auth('Oauth2')
            ->parameters(
                HeaderParam::init('Prefer', $options)->extract('prefer', 'return=minimal'),
                QueryParam::init('product_id', $options)->extract('productId'),
                QueryParam::init('page_size', $options)->extract('pageSize', 10),
                QueryParam::init('page', $options)->extract('page', 1),
                QueryParam::init('total_required', $options)->extract('totalRequired', false)
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->type(PlanCollection::class)
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Shows details for a plan, by ID.
     *
     * @param string $id The ID of the plan.
     *
     * @return ApiResponse Response from the API call
     */
    public function getBillingPlan(string $id): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::GET, '/v1/billing/plans/{id}')
            ->auth('Oauth2')
            ->parameters(TemplateParam::init('id', $id));

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->type(BillingPlan::class)
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Updates a plan with the `CREATED` or `ACTIVE` status. For an `INACTIVE` plan, you can make only
     * status updates. You can patch these attributes and objects: Attribute or object Operations
     * description replace payment_preferences.auto_bill_outstanding replace taxes.percentage replace
     * payment_preferences.payment_failure_threshold replace payment_preferences.setup_fee replace
     * payment_preferences.setup_fee_failure_action replace name replace
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function patchBillingPlan(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::PATCH, '/v1/billing/plans/{id}')
            ->auth('Oauth2')
            ->parameters(
                TemplateParam::init('id', $options)->extract('id'),
                HeaderParam::init('Content-Type', 'application/json'),
                BodyParam::init($options)->extract('body')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Activates a plan, by ID.
     *
     * @param string $id The ID of the plan.
     *
     * @return ApiResponse Response from the API call
     */
    public function activateBillingPlan(string $id): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::POST, '/v1/billing/plans/{id}/activate')
            ->auth('Oauth2')
            ->parameters(TemplateParam::init('id', $id));

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Deactivates a plan, by ID.
     *
     * @param string $id The ID of the plan.
     *
     * @return ApiResponse Response from the API call
     */
    public function deactivateBillingPlan(string $id): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::POST, '/v1/billing/plans/{id}/deactivate')
            ->auth('Oauth2')
            ->parameters(TemplateParam::init('id', $id));

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Updates pricing for a plan. For example, you can update a regular billing cycle from $5 per month to
     * $7 per month.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function updateBillingPlanPricingSchemes(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::POST, '/v1/billing/plans/{id}/update-pricing-schemes')
            ->auth('Oauth2')
            ->parameters(
                TemplateParam::init('id', $options)->extract('id'),
                HeaderParam::init('Content-Type', 'application/json'),
                BodyParam::init($options)->extract('body')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Bad Request. Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Creates a subscription.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function createSubscription(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::POST, '/v1/billing/subscriptions')
            ->auth('Oauth2')
            ->parameters(
                HeaderParam::init('Content-Type', 'application/json'),
                HeaderParam::init('Prefer', $options)->extract('prefer', 'return=minimal'),
                HeaderParam::init('PayPal-Request-Id', $options)->extract('paypalRequestId'),
                HeaderParam::init('PayPal-Client-Metadata-Id', $options)->extract('paypalClientMetadataId'),
                BodyParam::init($options)->extract('body')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Bad Request. Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->type(Subscription::class)
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * List all subscriptions for merchant account.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function listSubscriptions(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::GET, '/v1/billing/subscriptions')
            ->auth('Oauth2')
            ->parameters(
                QueryParam::init('plan_ids', $options)->extract('planIds'),
                QueryParam::init('statuses', $options)->extract('statuses'),
                QueryParam::init('created_after', $options)->extract('createdAfter'),
                QueryParam::init('created_before', $options)->extract('createdBefore'),
                QueryParam::init('status_updated_before', $options)->extract('statusUpdatedBefore'),
                QueryParam::init('status_updated_after', $options)->extract('statusUpdatedAfter'),
                QueryParam::init('filter', $options)->extract('filter'),
                QueryParam::init('page_size', $options)->extract('pageSize', 10),
                QueryParam::init('page', $options)->extract('page', 1),
                QueryParam::init('customer_ids', $options)->extract('customerIds')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->type(SubscriptionCollection::class)
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Shows details for a subscription, by ID.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function getSubscription(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::GET, '/v1/billing/subscriptions/{id}')
            ->auth('Oauth2')
            ->parameters(
                TemplateParam::init('id', $options)->extract('id'),
                QueryParam::init('fields', $options)->extract('fields')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->type(Subscription::class)
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Updates a subscription which could be in ACTIVE or SUSPENDED status. You can override plan level
     * default attributes by providing customised values for plan path in the patch request. You cannot
     * update attributes that have already completed (Example - trial cycles can’t be updated if completed).
     * Once overridden, changes to plan resource will not impact subscription. Any price update will not
     * impact billing cycles within next 10 days (Applicable only for subscriptions funded by PayPal
     * account). Following are the fields eligible for patch. Attribute or object Operations billing_info.
     * outstanding_balance replace custom_id add,replace plan.billing_cycles[@sequence==n]. pricing_scheme.
     * fixed_price add,replace plan.billing_cycles[@sequence==n]. pricing_scheme.tiers replace plan.
     * billing_cycles[@sequence==n]. total_cycles replace plan.payment_preferences. auto_bill_outstanding
     * replace plan.payment_preferences. payment_failure_threshold replace plan.taxes.inclusive add,replace
     * plan.taxes.percentage add,replace shipping_amount add,replace start_time replace subscriber.
     * shipping_address add,replace subscriber.payment_source (for subscriptions funded by card payments)
     * replace
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function patchSubscription(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::PATCH, '/v1/billing/subscriptions/{id}')
            ->auth('Oauth2')
            ->parameters(
                TemplateParam::init('id', $options)->extract('id'),
                HeaderParam::init('Content-Type', 'application/json'),
                BodyParam::init($options)->extract('body')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Updates the quantity of the product or service in a subscription. You can also use this method to
     * switch the plan and update the `shipping_amount`, `shipping_address` values for the subscription.
     * This type of update requires the buyer's consent.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function reviseSubscription(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::POST, '/v1/billing/subscriptions/{id}/revise')
            ->auth('Oauth2')
            ->parameters(
                TemplateParam::init('id', $options)->extract('id'),
                HeaderParam::init('Content-Type', 'application/json'),
                BodyParam::init($options)->extract('body')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Bad Request. Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->type(ModifySubscriptionResponse::class)
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Suspends the subscription.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function suspendSubscription(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::POST, '/v1/billing/subscriptions/{id}/suspend')
            ->auth('Oauth2')
            ->parameters(
                TemplateParam::init('id', $options)->extract('id'),
                HeaderParam::init('Content-Type', 'application/json'),
                BodyParam::init($options)->extract('body')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Bad Request. Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Cancels the subscription.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function cancelSubscription(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::POST, '/v1/billing/subscriptions/{id}/cancel')
            ->auth('Oauth2')
            ->parameters(
                TemplateParam::init('id', $options)->extract('id'),
                HeaderParam::init('Content-Type', 'application/json'),
                BodyParam::init($options)->extract('body')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Bad Request. Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Activates the subscription.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function activateSubscription(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::POST, '/v1/billing/subscriptions/{id}/activate')
            ->auth('Oauth2')
            ->parameters(
                TemplateParam::init('id', $options)->extract('id'),
                HeaderParam::init('Content-Type', 'application/json'),
                BodyParam::init($options)->extract('body')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Bad Request. Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Captures an authorized payment from the subscriber on the subscription.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function captureSubscription(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::POST, '/v1/billing/subscriptions/{id}/capture')
            ->auth('Oauth2')
            ->parameters(
                TemplateParam::init('id', $options)->extract('id'),
                HeaderParam::init('Content-Type', 'application/json'),
                HeaderParam::init('PayPal-Request-Id', $options)->extract('paypalRequestId'),
                BodyParam::init($options)->extract('body')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Bad Request. Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '422',
                ErrorType::init(
                    'The requested action could not be performed, semantically incorrect, or fa' .
                    'iled business validation.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->nullableType()
            ->type(SubscriptionTransactionDetails::class)
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }

    /**
     * Lists transactions for a subscription.
     *
     * @param array $options Array with all options for search
     *
     * @return ApiResponse Response from the API call
     */
    public function listSubscriptionTransactions(array $options): ApiResponse
    {
        $_reqBuilder = $this->requestBuilder(RequestMethod::GET, '/v1/billing/subscriptions/{id}/transactions')
            ->auth('Oauth2')
            ->parameters(
                TemplateParam::init('id', $options)->extract('id'),
                QueryParam::init('start_time', $options)->extract('startTime'),
                QueryParam::init('end_time', $options)->extract('endTime')
            );

        $_resHandler = $this->responseHandler()
            ->throwErrorOn(
                '400',
                ErrorType::init(
                    'Bad Request. Request is not well-formed, syntactically incorrect, or violates schema.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '401',
                ErrorType::init(
                    'Authentication failed due to missing authorization header, or invalid auth' .
                    'entication credentials.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '403',
                ErrorType::init(
                    'Authorization failed due to insufficient permissions.',
                    SubscriptionErrorException::class
                )
            )
            ->throwErrorOn(
                '404',
                ErrorType::init('The specified resource does not exist.', SubscriptionErrorException::class)
            )
            ->throwErrorOn(
                '500',
                ErrorType::init('An internal server error has occurred.', SubscriptionErrorException::class)
            )
            ->throwErrorOn('0', ErrorType::init('The error response.', SubscriptionErrorException::class))
            ->type(TransactionsList::class)
            ->returnApiResponse();

        return $this->execute($_reqBuilder, $_resHandler);
    }
}
