<?php declare(strict_types=1);

namespace AmazonPHP\SellingPartner\Api\VendorOrdersApi;

use AmazonPHP\SellingPartner\AccessToken;
use AmazonPHP\SellingPartner\Configuration;
use AmazonPHP\SellingPartner\Exception\ApiException;
use AmazonPHP\SellingPartner\Exception\InvalidArgumentException;
use AmazonPHP\SellingPartner\HttpFactory;
use AmazonPHP\SellingPartner\HttpSignatureHeaders;
use AmazonPHP\SellingPartner\ObjectSerializer;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Log\LoggerInterface;

/**
 * This class was auto-generated by https://github.com/OpenAPITools/openapi-generator/.
 * Do not change it, it will be overwritten with next execution of /bin/generate.sh.
 */
final class VendorOrdersSDK
{
    public const API_NAME = 'VendorOrders';

    public const OPERATION_GETPURCHASEORDER = 'getPurchaseOrder';

    public const OPERATION_GETPURCHASEORDER_PATH = '/vendor/orders/v1/purchaseOrders/{purchaseOrderNumber}';

    public const OPERATION_GETPURCHASEORDERS = 'getPurchaseOrders';

    public const OPERATION_GETPURCHASEORDERS_PATH = '/vendor/orders/v1/purchaseOrders';

    public const OPERATION_GETPURCHASEORDERSSTATUS = 'getPurchaseOrdersStatus';

    public const OPERATION_GETPURCHASEORDERSSTATUS_PATH = '/vendor/orders/v1/purchaseOrdersStatus';

    public const OPERATION_SUBMITACKNOWLEDGEMENT = 'submitAcknowledgement';

    public const OPERATION_SUBMITACKNOWLEDGEMENT_PATH = '/vendor/orders/v1/acknowledgements';

    private ClientInterface $client;

    private HttpFactory $httpFactory;

    private Configuration $configuration;

    private LoggerInterface $logger;

    public function __construct(ClientInterface $client, HttpFactory $requestFactory, Configuration $configuration, LoggerInterface $logger)
    {
        $this->client = $client;
        $this->httpFactory = $requestFactory;
        $this->configuration = $configuration;
        $this->logger = $logger;
    }

    /**
     * Operation getPurchaseOrder.
     *
     * @param AccessToken $accessToken
     * @param string $purchase_order_number The purchase order identifier for the order that you want. Formatting Notes: 8-character alpha-numeric code. (required)
     *
     * @throws \AmazonPHP\SellingPartner\Exception\ApiException on non-2xx response
     * @throws \AmazonPHP\SellingPartner\Exception\InvalidArgumentException
     */
    public function getPurchaseOrder(AccessToken $accessToken, string $region, string $purchase_order_number) : \AmazonPHP\SellingPartner\Model\VendorOrders\GetPurchaseOrderResponse
    {
        $request = $this->getPurchaseOrderRequest($accessToken, $region, $purchase_order_number);

        $this->configuration->extensions()->preRequest('VendorOrders', 'getPurchaseOrder', $request);

        try {
            $correlationId = \uuid_create(UUID_TYPE_RANDOM);

            if ($this->configuration->loggingEnabled('VendorOrders', 'getPurchaseOrder')) {
                $sanitizedRequest = $request;

                foreach ($this->configuration->loggingSkipHeaders() as $sensitiveHeader) {
                    $sanitizedRequest = $sanitizedRequest->withoutHeader($sensitiveHeader);
                }

                $this->logger->log(
                    $this->configuration->logLevel('VendorOrders', 'getPurchaseOrder'),
                    'Amazon Selling Partner API pre request',
                    [
                        'api' => 'VendorOrders',
                        'operation' => 'getPurchaseOrder',
                        'request_correlation_id' => $correlationId,
                        'request_body' => (string) $sanitizedRequest->getBody(),
                        'request_headers' => $sanitizedRequest->getHeaders(),
                        'request_uri' => (string) $sanitizedRequest->getUri(),
                    ]
                );
            }

            $response = $this->client->sendRequest($request);

            $this->configuration->extensions()->postRequest('VendorOrders', 'getPurchaseOrder', $request, $response);

            if ($this->configuration->loggingEnabled('VendorOrders', 'getPurchaseOrder')) {
                $sanitizedResponse = $response;

                foreach ($this->configuration->loggingSkipHeaders() as $sensitiveHeader) {
                    $sanitizedResponse = $sanitizedResponse->withoutHeader($sensitiveHeader);
                }

                $this->logger->log(
                    $this->configuration->logLevel('VendorOrders', 'getPurchaseOrder'),
                    'Amazon Selling Partner API post request',
                    [
                        'api' => 'VendorOrders',
                        'operation' => 'getPurchaseOrder',
                        'response_correlation_id' => $correlationId,
                        'response_body' => (string) $sanitizedResponse->getBody(),
                        'response_headers' => $sanitizedResponse->getHeaders(),
                        'response_status_code' => $sanitizedResponse->getStatusCode(),
                    ]
                );
            }
        } catch (ClientExceptionInterface $e) {
            throw new ApiException(
                "[{$e->getCode()}] {$e->getMessage()}",
                (int) $e->getCode(),
                null,
                null,
                $e
            );
        }

        $statusCode = $response->getStatusCode();

        if ($statusCode < 200 || $statusCode > 299) {
            throw new ApiException(
                \sprintf(
                    '[%d] Error connecting to the API (%s)',
                    $statusCode,
                    (string) $request->getUri()
                ),
                $statusCode,
                $response->getHeaders(),
                (string) $response->getBody()
            );
        }

        return ObjectSerializer::deserialize(
            $this->configuration,
            (string) $response->getBody(),
            '\AmazonPHP\SellingPartner\Model\VendorOrders\GetPurchaseOrderResponse',
            []
        );
    }

    /**
     * Create request for operation 'getPurchaseOrder'.
     *
     * @param AccessToken $accessToken
     * @param string $purchase_order_number The purchase order identifier for the order that you want. Formatting Notes: 8-character alpha-numeric code. (required)
     *
     * @throws \AmazonPHP\SellingPartner\Exception\InvalidArgumentException
     */
    public function getPurchaseOrderRequest(AccessToken $accessToken, string $region, string $purchase_order_number) : RequestInterface
    {
        // verify the required parameter 'purchase_order_number' is set
        if ($purchase_order_number === null || (\is_array($purchase_order_number) && \count($purchase_order_number) === 0)) {
            throw new InvalidArgumentException(
                'Missing the required parameter $purchase_order_number when calling getPurchaseOrder'
            );
        }

        $resourcePath = '/vendor/orders/v1/purchaseOrders/{purchaseOrderNumber}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $multipart = false;
        $query = '';

        if (\count($queryParams)) {
            $query = \http_build_query($queryParams);
        }

        // path params
        if ($purchase_order_number !== null) {
            $resourcePath = \str_replace(
                '{' . 'purchaseOrderNumber' . '}',
                ObjectSerializer::toPathValue($purchase_order_number),
                $resourcePath
            );
        }

        if ($multipart) {
            $headers = [
                'accept' => ['application/json'],
                'host' => [$this->configuration->apiHost($region)],
                'user-agent' => [$this->configuration->userAgent()],
            ];
        } else {
            $headers = [
                'content-type' => ['application/json'],
                'accept' => ['application/json'],
                'host' => [$this->configuration->apiHost($region)],
                'user-agent' => [$this->configuration->userAgent()],
            ];
        }

        $request = $this->httpFactory->createRequest(
            'GET',
            $this->configuration->apiURL($region) . $resourcePath . '?' . $query
        );

        // for model (json/xml)
        if (\count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [];

                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = \is_array($formParamValue) ? $formParamValue : [$formParamValue];

                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem,
                        ];
                    }
                }
                $request = $request->withParsedBody($multipartContents);
            } elseif ($headers['content-type'] === ['application/json']) {
                $request = $request->withBody($this->httpFactory->createStreamFromString(\json_encode($formParams, JSON_THROW_ON_ERROR)));
            } else {
                $request = $request->withParsedBody($formParams);
            }
        }

        foreach (\array_merge($headerParams, $headers) as $name => $header) {
            $request = $request->withHeader($name, $header);
        }

        return HttpSignatureHeaders::forConfig(
            $this->configuration,
            $accessToken,
            $region,
            $request
        );
    }

    /**
     * Operation getPurchaseOrders.
     *
     * @param AccessToken $accessToken
     * @param int $limit The limit to the number of records returned. Default value is 100 records. (optional)
     * @param \DateTime $created_after Purchase orders that became available after this time will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param \DateTime $created_before Purchase orders that became available before this time will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param string $sort_order Sort in ascending or descending order by purchase order creation date. (optional)
     * @param string $next_token Used for pagination when there is more purchase orders than the specified result size limit. The token value is returned in the previous API call (optional)
     * @param bool $include_details When true, returns purchase orders with complete details. Otherwise, only purchase order numbers are returned. Default value is true. (optional)
     * @param \DateTime $changed_after Purchase orders that changed after this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param \DateTime $changed_before Purchase orders that changed before this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param string $po_item_state Current state of the purchase order item. If this value is Cancelled, this API will return purchase orders which have one or more items cancelled by Amazon with updated item quantity as zero. (optional)
     * @param bool $is_po_changed When true, returns purchase orders which were modified after the order was placed. Vendors are required to pull the changed purchase order and fulfill the updated purchase order and not the original one. Default value is false. (optional)
     * @param string $purchase_order_state Filters purchase orders based on the purchase order state. (optional)
     * @param string $ordering_vendor_code Filters purchase orders based on the specified ordering vendor code. This value should be same as &#39;sellingParty.partyId&#39; in the purchase order. If not included in the filter, all purchase orders for all of the vendor codes that exist in the vendor group used to authorize the API client application are returned. (optional)
     *
     * @throws \AmazonPHP\SellingPartner\Exception\ApiException on non-2xx response
     * @throws \AmazonPHP\SellingPartner\Exception\InvalidArgumentException
     */
    public function getPurchaseOrders(AccessToken $accessToken, string $region, int $limit = null, \DateTimeInterface $created_after = null, \DateTimeInterface $created_before = null, string $sort_order = null, string $next_token = null, bool $include_details = null, \DateTimeInterface $changed_after = null, \DateTimeInterface $changed_before = null, string $po_item_state = null, bool $is_po_changed = null, string $purchase_order_state = null, string $ordering_vendor_code = null) : \AmazonPHP\SellingPartner\Model\VendorOrders\GetPurchaseOrdersResponse
    {
        $request = $this->getPurchaseOrdersRequest($accessToken, $region, $limit, $created_after, $created_before, $sort_order, $next_token, $include_details, $changed_after, $changed_before, $po_item_state, $is_po_changed, $purchase_order_state, $ordering_vendor_code);

        $this->configuration->extensions()->preRequest('VendorOrders', 'getPurchaseOrders', $request);

        try {
            $correlationId = \uuid_create(UUID_TYPE_RANDOM);

            if ($this->configuration->loggingEnabled('VendorOrders', 'getPurchaseOrders')) {
                $sanitizedRequest = $request;

                foreach ($this->configuration->loggingSkipHeaders() as $sensitiveHeader) {
                    $sanitizedRequest = $sanitizedRequest->withoutHeader($sensitiveHeader);
                }

                $this->logger->log(
                    $this->configuration->logLevel('VendorOrders', 'getPurchaseOrders'),
                    'Amazon Selling Partner API pre request',
                    [
                        'api' => 'VendorOrders',
                        'operation' => 'getPurchaseOrders',
                        'request_correlation_id' => $correlationId,
                        'request_body' => (string) $sanitizedRequest->getBody(),
                        'request_headers' => $sanitizedRequest->getHeaders(),
                        'request_uri' => (string) $sanitizedRequest->getUri(),
                    ]
                );
            }

            $response = $this->client->sendRequest($request);

            $this->configuration->extensions()->postRequest('VendorOrders', 'getPurchaseOrders', $request, $response);

            if ($this->configuration->loggingEnabled('VendorOrders', 'getPurchaseOrders')) {
                $sanitizedResponse = $response;

                foreach ($this->configuration->loggingSkipHeaders() as $sensitiveHeader) {
                    $sanitizedResponse = $sanitizedResponse->withoutHeader($sensitiveHeader);
                }

                $this->logger->log(
                    $this->configuration->logLevel('VendorOrders', 'getPurchaseOrders'),
                    'Amazon Selling Partner API post request',
                    [
                        'api' => 'VendorOrders',
                        'operation' => 'getPurchaseOrders',
                        'response_correlation_id' => $correlationId,
                        'response_body' => (string) $sanitizedResponse->getBody(),
                        'response_headers' => $sanitizedResponse->getHeaders(),
                        'response_status_code' => $sanitizedResponse->getStatusCode(),
                    ]
                );
            }
        } catch (ClientExceptionInterface $e) {
            throw new ApiException(
                "[{$e->getCode()}] {$e->getMessage()}",
                (int) $e->getCode(),
                null,
                null,
                $e
            );
        }

        $statusCode = $response->getStatusCode();

        if ($statusCode < 200 || $statusCode > 299) {
            throw new ApiException(
                \sprintf(
                    '[%d] Error connecting to the API (%s)',
                    $statusCode,
                    (string) $request->getUri()
                ),
                $statusCode,
                $response->getHeaders(),
                (string) $response->getBody()
            );
        }

        return ObjectSerializer::deserialize(
            $this->configuration,
            (string) $response->getBody(),
            '\AmazonPHP\SellingPartner\Model\VendorOrders\GetPurchaseOrdersResponse',
            []
        );
    }

    /**
     * Create request for operation 'getPurchaseOrders'.
     *
     * @param AccessToken $accessToken
     * @param int $limit The limit to the number of records returned. Default value is 100 records. (optional)
     * @param \DateTime $created_after Purchase orders that became available after this time will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param \DateTime $created_before Purchase orders that became available before this time will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param string $sort_order Sort in ascending or descending order by purchase order creation date. (optional)
     * @param string $next_token Used for pagination when there is more purchase orders than the specified result size limit. The token value is returned in the previous API call (optional)
     * @param bool $include_details When true, returns purchase orders with complete details. Otherwise, only purchase order numbers are returned. Default value is true. (optional)
     * @param \DateTime $changed_after Purchase orders that changed after this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param \DateTime $changed_before Purchase orders that changed before this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param string $po_item_state Current state of the purchase order item. If this value is Cancelled, this API will return purchase orders which have one or more items cancelled by Amazon with updated item quantity as zero. (optional)
     * @param bool $is_po_changed When true, returns purchase orders which were modified after the order was placed. Vendors are required to pull the changed purchase order and fulfill the updated purchase order and not the original one. Default value is false. (optional)
     * @param string $purchase_order_state Filters purchase orders based on the purchase order state. (optional)
     * @param string $ordering_vendor_code Filters purchase orders based on the specified ordering vendor code. This value should be same as &#39;sellingParty.partyId&#39; in the purchase order. If not included in the filter, all purchase orders for all of the vendor codes that exist in the vendor group used to authorize the API client application are returned. (optional)
     *
     * @throws \AmazonPHP\SellingPartner\Exception\InvalidArgumentException
     */
    public function getPurchaseOrdersRequest(AccessToken $accessToken, string $region, int $limit = null, \DateTimeInterface $created_after = null, \DateTimeInterface $created_before = null, string $sort_order = null, string $next_token = null, bool $include_details = null, \DateTimeInterface $changed_after = null, \DateTimeInterface $changed_before = null, string $po_item_state = null, bool $is_po_changed = null, string $purchase_order_state = null, string $ordering_vendor_code = null) : RequestInterface
    {
        if ($limit !== null && $limit > 100) {
            throw new InvalidArgumentException('invalid value for "$limit" when calling VendorOrdersApi.getPurchaseOrders, must be smaller than or equal to 100.');
        }

        if ($limit !== null && $limit < 1) {
            throw new InvalidArgumentException('invalid value for "$limit" when calling VendorOrdersApi.getPurchaseOrders, must be bigger than or equal to 1.');
        }

        $resourcePath = '/vendor/orders/v1/purchaseOrders';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $multipart = false;
        $query = '';

        // query params
        if (\is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }

        if ($limit !== null) {
            $queryParams['limit'] = ObjectSerializer::toString($limit);
        }
        // query params
        if (\is_array($created_after)) {
            $created_after = ObjectSerializer::serializeCollection($created_after, '', true);
        }

        if ($created_after !== null) {
            $queryParams['createdAfter'] = ObjectSerializer::toString($created_after);
        }
        // query params
        if (\is_array($created_before)) {
            $created_before = ObjectSerializer::serializeCollection($created_before, '', true);
        }

        if ($created_before !== null) {
            $queryParams['createdBefore'] = ObjectSerializer::toString($created_before);
        }
        // query params
        if (\is_array($sort_order)) {
            $sort_order = ObjectSerializer::serializeCollection($sort_order, '', true);
        }

        if ($sort_order !== null) {
            $queryParams['sortOrder'] = ObjectSerializer::toString($sort_order);
        }
        // query params
        if (\is_array($next_token)) {
            $next_token = ObjectSerializer::serializeCollection($next_token, '', true);
        }

        if ($next_token !== null) {
            $queryParams['nextToken'] = ObjectSerializer::toString($next_token);
        }
        // query params
        if (\is_array($include_details)) {
            $include_details = ObjectSerializer::serializeCollection($include_details, '', true);
        }

        if ($include_details !== null) {
            $queryParams['includeDetails'] = ObjectSerializer::toString($include_details);
        }
        // query params
        if (\is_array($changed_after)) {
            $changed_after = ObjectSerializer::serializeCollection($changed_after, '', true);
        }

        if ($changed_after !== null) {
            $queryParams['changedAfter'] = ObjectSerializer::toString($changed_after);
        }
        // query params
        if (\is_array($changed_before)) {
            $changed_before = ObjectSerializer::serializeCollection($changed_before, '', true);
        }

        if ($changed_before !== null) {
            $queryParams['changedBefore'] = ObjectSerializer::toString($changed_before);
        }
        // query params
        if (\is_array($po_item_state)) {
            $po_item_state = ObjectSerializer::serializeCollection($po_item_state, '', true);
        }

        if ($po_item_state !== null) {
            $queryParams['poItemState'] = ObjectSerializer::toString($po_item_state);
        }
        // query params
        if (\is_array($is_po_changed)) {
            $is_po_changed = ObjectSerializer::serializeCollection($is_po_changed, '', true);
        }

        if ($is_po_changed !== null) {
            $queryParams['isPOChanged'] = ObjectSerializer::toString($is_po_changed);
        }
        // query params
        if (\is_array($purchase_order_state)) {
            $purchase_order_state = ObjectSerializer::serializeCollection($purchase_order_state, '', true);
        }

        if ($purchase_order_state !== null) {
            $queryParams['purchaseOrderState'] = ObjectSerializer::toString($purchase_order_state);
        }
        // query params
        if (\is_array($ordering_vendor_code)) {
            $ordering_vendor_code = ObjectSerializer::serializeCollection($ordering_vendor_code, '', true);
        }

        if ($ordering_vendor_code !== null) {
            $queryParams['orderingVendorCode'] = ObjectSerializer::toString($ordering_vendor_code);
        }

        if (\count($queryParams)) {
            $query = \http_build_query($queryParams);
        }

        if ($multipart) {
            $headers = [
                'accept' => ['application/json'],
                'host' => [$this->configuration->apiHost($region)],
                'user-agent' => [$this->configuration->userAgent()],
            ];
        } else {
            $headers = [
                'content-type' => ['application/json'],
                'accept' => ['application/json'],
                'host' => [$this->configuration->apiHost($region)],
                'user-agent' => [$this->configuration->userAgent()],
            ];
        }

        $request = $this->httpFactory->createRequest(
            'GET',
            $this->configuration->apiURL($region) . $resourcePath . '?' . $query
        );

        // for model (json/xml)
        if (\count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [];

                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = \is_array($formParamValue) ? $formParamValue : [$formParamValue];

                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem,
                        ];
                    }
                }
                $request = $request->withParsedBody($multipartContents);
            } elseif ($headers['content-type'] === ['application/json']) {
                $request = $request->withBody($this->httpFactory->createStreamFromString(\json_encode($formParams, JSON_THROW_ON_ERROR)));
            } else {
                $request = $request->withParsedBody($formParams);
            }
        }

        foreach (\array_merge($headerParams, $headers) as $name => $header) {
            $request = $request->withHeader($name, $header);
        }

        return HttpSignatureHeaders::forConfig(
            $this->configuration,
            $accessToken,
            $region,
            $request
        );
    }

    /**
     * Operation getPurchaseOrdersStatus.
     *
     * @param AccessToken $accessToken
     * @param int $limit The limit to the number of records returned. Default value is 100 records. (optional)
     * @param string $sort_order Sort in ascending or descending order by purchase order creation date. (optional)
     * @param string $next_token Used for pagination when there are more purchase orders than the specified result size limit. (optional)
     * @param \DateTime $created_after Purchase orders that became available after this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param \DateTime $created_before Purchase orders that became available before this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param \DateTime $updated_after Purchase orders for which the last purchase order update happened after this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param \DateTime $updated_before Purchase orders for which the last purchase order update happened before this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param string $purchase_order_number Provides purchase order status for the specified purchase order number. (optional)
     * @param string $purchase_order_status Filters purchase orders based on the specified purchase order status. If not included in filter, this will return purchase orders for all statuses. (optional)
     * @param string $item_confirmation_status Filters purchase orders based on their item confirmation status. If the item confirmation status is not included in the filter, purchase orders for all confirmation statuses are included. (optional)
     * @param string $item_receive_status Filters purchase orders based on the purchase order&#39;s item receive status. If the item receive status is not included in the filter, purchase orders for all receive statuses are included. (optional)
     * @param string $ordering_vendor_code Filters purchase orders based on the specified ordering vendor code. This value should be same as &#39;sellingParty.partyId&#39; in the purchase order. If not included in filter, all purchase orders for all the vendor codes that exist in the vendor group used to authorize API client application are returned. (optional)
     * @param string $ship_to_party_id Filters purchase orders for a specific buyer&#39;s Fulfillment Center/warehouse by providing ship to location id here. This value should be same as &#39;shipToParty.partyId&#39; in the purchase order. If not included in filter, this will return purchase orders for all the buyer&#39;s warehouses used for vendor group purchase orders. (optional)
     *
     * @throws \AmazonPHP\SellingPartner\Exception\ApiException on non-2xx response
     * @throws \AmazonPHP\SellingPartner\Exception\InvalidArgumentException
     */
    public function getPurchaseOrdersStatus(AccessToken $accessToken, string $region, int $limit = null, string $sort_order = null, string $next_token = null, \DateTimeInterface $created_after = null, \DateTimeInterface $created_before = null, \DateTimeInterface $updated_after = null, \DateTimeInterface $updated_before = null, string $purchase_order_number = null, string $purchase_order_status = null, string $item_confirmation_status = null, string $item_receive_status = null, string $ordering_vendor_code = null, string $ship_to_party_id = null) : \AmazonPHP\SellingPartner\Model\VendorOrders\GetPurchaseOrdersStatusResponse
    {
        $request = $this->getPurchaseOrdersStatusRequest($accessToken, $region, $limit, $sort_order, $next_token, $created_after, $created_before, $updated_after, $updated_before, $purchase_order_number, $purchase_order_status, $item_confirmation_status, $item_receive_status, $ordering_vendor_code, $ship_to_party_id);

        $this->configuration->extensions()->preRequest('VendorOrders', 'getPurchaseOrdersStatus', $request);

        try {
            $correlationId = \uuid_create(UUID_TYPE_RANDOM);

            if ($this->configuration->loggingEnabled('VendorOrders', 'getPurchaseOrdersStatus')) {
                $sanitizedRequest = $request;

                foreach ($this->configuration->loggingSkipHeaders() as $sensitiveHeader) {
                    $sanitizedRequest = $sanitizedRequest->withoutHeader($sensitiveHeader);
                }

                $this->logger->log(
                    $this->configuration->logLevel('VendorOrders', 'getPurchaseOrdersStatus'),
                    'Amazon Selling Partner API pre request',
                    [
                        'api' => 'VendorOrders',
                        'operation' => 'getPurchaseOrdersStatus',
                        'request_correlation_id' => $correlationId,
                        'request_body' => (string) $sanitizedRequest->getBody(),
                        'request_headers' => $sanitizedRequest->getHeaders(),
                        'request_uri' => (string) $sanitizedRequest->getUri(),
                    ]
                );
            }

            $response = $this->client->sendRequest($request);

            $this->configuration->extensions()->postRequest('VendorOrders', 'getPurchaseOrdersStatus', $request, $response);

            if ($this->configuration->loggingEnabled('VendorOrders', 'getPurchaseOrdersStatus')) {
                $sanitizedResponse = $response;

                foreach ($this->configuration->loggingSkipHeaders() as $sensitiveHeader) {
                    $sanitizedResponse = $sanitizedResponse->withoutHeader($sensitiveHeader);
                }

                $this->logger->log(
                    $this->configuration->logLevel('VendorOrders', 'getPurchaseOrdersStatus'),
                    'Amazon Selling Partner API post request',
                    [
                        'api' => 'VendorOrders',
                        'operation' => 'getPurchaseOrdersStatus',
                        'response_correlation_id' => $correlationId,
                        'response_body' => (string) $sanitizedResponse->getBody(),
                        'response_headers' => $sanitizedResponse->getHeaders(),
                        'response_status_code' => $sanitizedResponse->getStatusCode(),
                    ]
                );
            }
        } catch (ClientExceptionInterface $e) {
            throw new ApiException(
                "[{$e->getCode()}] {$e->getMessage()}",
                (int) $e->getCode(),
                null,
                null,
                $e
            );
        }

        $statusCode = $response->getStatusCode();

        if ($statusCode < 200 || $statusCode > 299) {
            throw new ApiException(
                \sprintf(
                    '[%d] Error connecting to the API (%s)',
                    $statusCode,
                    (string) $request->getUri()
                ),
                $statusCode,
                $response->getHeaders(),
                (string) $response->getBody()
            );
        }

        return ObjectSerializer::deserialize(
            $this->configuration,
            (string) $response->getBody(),
            '\AmazonPHP\SellingPartner\Model\VendorOrders\GetPurchaseOrdersStatusResponse',
            []
        );
    }

    /**
     * Create request for operation 'getPurchaseOrdersStatus'.
     *
     * @param AccessToken $accessToken
     * @param int $limit The limit to the number of records returned. Default value is 100 records. (optional)
     * @param string $sort_order Sort in ascending or descending order by purchase order creation date. (optional)
     * @param string $next_token Used for pagination when there are more purchase orders than the specified result size limit. (optional)
     * @param \DateTime $created_after Purchase orders that became available after this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param \DateTime $created_before Purchase orders that became available before this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param \DateTime $updated_after Purchase orders for which the last purchase order update happened after this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param \DateTime $updated_before Purchase orders for which the last purchase order update happened before this timestamp will be included in the result. Must be in ISO-8601 date/time format. (optional)
     * @param string $purchase_order_number Provides purchase order status for the specified purchase order number. (optional)
     * @param string $purchase_order_status Filters purchase orders based on the specified purchase order status. If not included in filter, this will return purchase orders for all statuses. (optional)
     * @param string $item_confirmation_status Filters purchase orders based on their item confirmation status. If the item confirmation status is not included in the filter, purchase orders for all confirmation statuses are included. (optional)
     * @param string $item_receive_status Filters purchase orders based on the purchase order&#39;s item receive status. If the item receive status is not included in the filter, purchase orders for all receive statuses are included. (optional)
     * @param string $ordering_vendor_code Filters purchase orders based on the specified ordering vendor code. This value should be same as &#39;sellingParty.partyId&#39; in the purchase order. If not included in filter, all purchase orders for all the vendor codes that exist in the vendor group used to authorize API client application are returned. (optional)
     * @param string $ship_to_party_id Filters purchase orders for a specific buyer&#39;s Fulfillment Center/warehouse by providing ship to location id here. This value should be same as &#39;shipToParty.partyId&#39; in the purchase order. If not included in filter, this will return purchase orders for all the buyer&#39;s warehouses used for vendor group purchase orders. (optional)
     *
     * @throws \AmazonPHP\SellingPartner\Exception\InvalidArgumentException
     */
    public function getPurchaseOrdersStatusRequest(AccessToken $accessToken, string $region, int $limit = null, string $sort_order = null, string $next_token = null, \DateTimeInterface $created_after = null, \DateTimeInterface $created_before = null, \DateTimeInterface $updated_after = null, \DateTimeInterface $updated_before = null, string $purchase_order_number = null, string $purchase_order_status = null, string $item_confirmation_status = null, string $item_receive_status = null, string $ordering_vendor_code = null, string $ship_to_party_id = null) : RequestInterface
    {
        if ($limit !== null && $limit > 100) {
            throw new InvalidArgumentException('invalid value for "$limit" when calling VendorOrdersApi.getPurchaseOrdersStatus, must be smaller than or equal to 100.');
        }

        if ($limit !== null && $limit < 1) {
            throw new InvalidArgumentException('invalid value for "$limit" when calling VendorOrdersApi.getPurchaseOrdersStatus, must be bigger than or equal to 1.');
        }

        $resourcePath = '/vendor/orders/v1/purchaseOrdersStatus';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $multipart = false;
        $query = '';

        // query params
        if (\is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }

        if ($limit !== null) {
            $queryParams['limit'] = ObjectSerializer::toString($limit);
        }
        // query params
        if (\is_array($sort_order)) {
            $sort_order = ObjectSerializer::serializeCollection($sort_order, '', true);
        }

        if ($sort_order !== null) {
            $queryParams['sortOrder'] = ObjectSerializer::toString($sort_order);
        }
        // query params
        if (\is_array($next_token)) {
            $next_token = ObjectSerializer::serializeCollection($next_token, '', true);
        }

        if ($next_token !== null) {
            $queryParams['nextToken'] = ObjectSerializer::toString($next_token);
        }
        // query params
        if (\is_array($created_after)) {
            $created_after = ObjectSerializer::serializeCollection($created_after, '', true);
        }

        if ($created_after !== null) {
            $queryParams['createdAfter'] = ObjectSerializer::toString($created_after);
        }
        // query params
        if (\is_array($created_before)) {
            $created_before = ObjectSerializer::serializeCollection($created_before, '', true);
        }

        if ($created_before !== null) {
            $queryParams['createdBefore'] = ObjectSerializer::toString($created_before);
        }
        // query params
        if (\is_array($updated_after)) {
            $updated_after = ObjectSerializer::serializeCollection($updated_after, '', true);
        }

        if ($updated_after !== null) {
            $queryParams['updatedAfter'] = ObjectSerializer::toString($updated_after);
        }
        // query params
        if (\is_array($updated_before)) {
            $updated_before = ObjectSerializer::serializeCollection($updated_before, '', true);
        }

        if ($updated_before !== null) {
            $queryParams['updatedBefore'] = ObjectSerializer::toString($updated_before);
        }
        // query params
        if (\is_array($purchase_order_number)) {
            $purchase_order_number = ObjectSerializer::serializeCollection($purchase_order_number, '', true);
        }

        if ($purchase_order_number !== null) {
            $queryParams['purchaseOrderNumber'] = ObjectSerializer::toString($purchase_order_number);
        }
        // query params
        if (\is_array($purchase_order_status)) {
            $purchase_order_status = ObjectSerializer::serializeCollection($purchase_order_status, '', true);
        }

        if ($purchase_order_status !== null) {
            $queryParams['purchaseOrderStatus'] = ObjectSerializer::toString($purchase_order_status);
        }
        // query params
        if (\is_array($item_confirmation_status)) {
            $item_confirmation_status = ObjectSerializer::serializeCollection($item_confirmation_status, '', true);
        }

        if ($item_confirmation_status !== null) {
            $queryParams['itemConfirmationStatus'] = ObjectSerializer::toString($item_confirmation_status);
        }
        // query params
        if (\is_array($item_receive_status)) {
            $item_receive_status = ObjectSerializer::serializeCollection($item_receive_status, '', true);
        }

        if ($item_receive_status !== null) {
            $queryParams['itemReceiveStatus'] = ObjectSerializer::toString($item_receive_status);
        }
        // query params
        if (\is_array($ordering_vendor_code)) {
            $ordering_vendor_code = ObjectSerializer::serializeCollection($ordering_vendor_code, '', true);
        }

        if ($ordering_vendor_code !== null) {
            $queryParams['orderingVendorCode'] = ObjectSerializer::toString($ordering_vendor_code);
        }
        // query params
        if (\is_array($ship_to_party_id)) {
            $ship_to_party_id = ObjectSerializer::serializeCollection($ship_to_party_id, '', true);
        }

        if ($ship_to_party_id !== null) {
            $queryParams['shipToPartyId'] = ObjectSerializer::toString($ship_to_party_id);
        }

        if (\count($queryParams)) {
            $query = \http_build_query($queryParams);
        }

        if ($multipart) {
            $headers = [
                'accept' => ['application/json'],
                'host' => [$this->configuration->apiHost($region)],
                'user-agent' => [$this->configuration->userAgent()],
            ];
        } else {
            $headers = [
                'content-type' => ['application/json'],
                'accept' => ['application/json'],
                'host' => [$this->configuration->apiHost($region)],
                'user-agent' => [$this->configuration->userAgent()],
            ];
        }

        $request = $this->httpFactory->createRequest(
            'GET',
            $this->configuration->apiURL($region) . $resourcePath . '?' . $query
        );

        // for model (json/xml)
        if (\count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [];

                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = \is_array($formParamValue) ? $formParamValue : [$formParamValue];

                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem,
                        ];
                    }
                }
                $request = $request->withParsedBody($multipartContents);
            } elseif ($headers['content-type'] === ['application/json']) {
                $request = $request->withBody($this->httpFactory->createStreamFromString(\json_encode($formParams, JSON_THROW_ON_ERROR)));
            } else {
                $request = $request->withParsedBody($formParams);
            }
        }

        foreach (\array_merge($headerParams, $headers) as $name => $header) {
            $request = $request->withHeader($name, $header);
        }

        return HttpSignatureHeaders::forConfig(
            $this->configuration,
            $accessToken,
            $region,
            $request
        );
    }

    /**
     * Operation submitAcknowledgement.
     *
     * @param AccessToken $accessToken
     * @param \AmazonPHP\SellingPartner\Model\VendorOrders\SubmitAcknowledgementRequest $body body (required)
     *
     * @throws \AmazonPHP\SellingPartner\Exception\ApiException on non-2xx response
     * @throws \AmazonPHP\SellingPartner\Exception\InvalidArgumentException
     */
    public function submitAcknowledgement(AccessToken $accessToken, string $region, \AmazonPHP\SellingPartner\Model\VendorOrders\SubmitAcknowledgementRequest $body) : \AmazonPHP\SellingPartner\Model\VendorOrders\SubmitAcknowledgementResponse
    {
        $request = $this->submitAcknowledgementRequest($accessToken, $region, $body);

        $this->configuration->extensions()->preRequest('VendorOrders', 'submitAcknowledgement', $request);

        try {
            $correlationId = \uuid_create(UUID_TYPE_RANDOM);

            if ($this->configuration->loggingEnabled('VendorOrders', 'submitAcknowledgement')) {
                $sanitizedRequest = $request;

                foreach ($this->configuration->loggingSkipHeaders() as $sensitiveHeader) {
                    $sanitizedRequest = $sanitizedRequest->withoutHeader($sensitiveHeader);
                }

                $this->logger->log(
                    $this->configuration->logLevel('VendorOrders', 'submitAcknowledgement'),
                    'Amazon Selling Partner API pre request',
                    [
                        'api' => 'VendorOrders',
                        'operation' => 'submitAcknowledgement',
                        'request_correlation_id' => $correlationId,
                        'request_body' => (string) $sanitizedRequest->getBody(),
                        'request_headers' => $sanitizedRequest->getHeaders(),
                        'request_uri' => (string) $sanitizedRequest->getUri(),
                    ]
                );
            }

            $response = $this->client->sendRequest($request);

            $this->configuration->extensions()->postRequest('VendorOrders', 'submitAcknowledgement', $request, $response);

            if ($this->configuration->loggingEnabled('VendorOrders', 'submitAcknowledgement')) {
                $sanitizedResponse = $response;

                foreach ($this->configuration->loggingSkipHeaders() as $sensitiveHeader) {
                    $sanitizedResponse = $sanitizedResponse->withoutHeader($sensitiveHeader);
                }

                $this->logger->log(
                    $this->configuration->logLevel('VendorOrders', 'submitAcknowledgement'),
                    'Amazon Selling Partner API post request',
                    [
                        'api' => 'VendorOrders',
                        'operation' => 'submitAcknowledgement',
                        'response_correlation_id' => $correlationId,
                        'response_body' => (string) $sanitizedResponse->getBody(),
                        'response_headers' => $sanitizedResponse->getHeaders(),
                        'response_status_code' => $sanitizedResponse->getStatusCode(),
                    ]
                );
            }
        } catch (ClientExceptionInterface $e) {
            throw new ApiException(
                "[{$e->getCode()}] {$e->getMessage()}",
                (int) $e->getCode(),
                null,
                null,
                $e
            );
        }

        $statusCode = $response->getStatusCode();

        if ($statusCode < 200 || $statusCode > 299) {
            throw new ApiException(
                \sprintf(
                    '[%d] Error connecting to the API (%s)',
                    $statusCode,
                    (string) $request->getUri()
                ),
                $statusCode,
                $response->getHeaders(),
                (string) $response->getBody()
            );
        }

        return ObjectSerializer::deserialize(
            $this->configuration,
            (string) $response->getBody(),
            '\AmazonPHP\SellingPartner\Model\VendorOrders\SubmitAcknowledgementResponse',
            []
        );
    }

    /**
     * Create request for operation 'submitAcknowledgement'.
     *
     * @param AccessToken $accessToken
     * @param \AmazonPHP\SellingPartner\Model\VendorOrders\SubmitAcknowledgementRequest $body (required)
     *
     * @throws \AmazonPHP\SellingPartner\Exception\InvalidArgumentException
     */
    public function submitAcknowledgementRequest(AccessToken $accessToken, string $region, \AmazonPHP\SellingPartner\Model\VendorOrders\SubmitAcknowledgementRequest $body) : RequestInterface
    {
        // verify the required parameter 'body' is set
        if ($body === null || (\is_array($body) && \count($body) === 0)) {
            throw new InvalidArgumentException(
                'Missing the required parameter $body when calling submitAcknowledgement'
            );
        }

        $resourcePath = '/vendor/orders/v1/acknowledgements';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $multipart = false;
        $query = '';

        if (\count($queryParams)) {
            $query = \http_build_query($queryParams);
        }

        if ($multipart) {
            $headers = [
                'accept' => ['application/json'],
                'host' => [$this->configuration->apiHost($region)],
                'user-agent' => [$this->configuration->userAgent()],
            ];
        } else {
            $headers = [
                'content-type' => ['application/json'],
                'accept' => ['application/json'],
                'host' => [$this->configuration->apiHost($region)],
                'user-agent' => [$this->configuration->userAgent()],
            ];
        }

        $request = $this->httpFactory->createRequest(
            'POST',
            $this->configuration->apiURL($region) . $resourcePath . '?' . $query
        );

        // for model (json/xml)
        if (isset($body)) {
            if ($headers['content-type'] === ['application/json']) {
                $httpBody = \json_encode(ObjectSerializer::sanitizeForSerialization($body), JSON_THROW_ON_ERROR);
            } else {
                $httpBody = $body;
            }

            $request = $request->withBody($this->httpFactory->createStreamFromString($httpBody));
        } elseif (\count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [];

                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = \is_array($formParamValue) ? $formParamValue : [$formParamValue];

                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem,
                        ];
                    }
                }
                $request = $request->withParsedBody($multipartContents);
            } elseif ($headers['content-type'] === ['application/json']) {
                $request = $request->withBody($this->httpFactory->createStreamFromString(\json_encode($formParams, JSON_THROW_ON_ERROR)));
            } else {
                $request = $request->withParsedBody($formParams);
            }
        }

        foreach (\array_merge($headerParams, $headers) as $name => $header) {
            $request = $request->withHeader($name, $header);
        }

        return HttpSignatureHeaders::forConfig(
            $this->configuration,
            $accessToken,
            $region,
            $request
        );
    }
}
