<?php

declare(strict_types=1);

namespace AmazonPHP\SellingPartner\Api\DefaultApi;

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;

/**
 * Selling Partner API for Finances.
 *
 * The Selling Partner API for Finances helps you obtain financial information relevant to a seller's business. You can obtain financial events for a given order, financial event group, or date range without having to wait until a statement period closes. You can also obtain financial event groups for a given date range.
 *
 * The version of the OpenAPI document: v0
 *
 * This class was auto-generated by https://openapi-generator.tech
 * Do not change it, it will be overwritten with next execution of /bin/generate.sh
 */
final class FinancialEventsSDK implements FinancialEventsSDKInterface
{
    public function __construct(private readonly ClientInterface $client, private readonly HttpFactory $httpFactory, private readonly Configuration $configuration, private readonly LoggerInterface $logger)
    {
    }

    /**
     * Operation listFinancialEventGroups.
     *
     * @param null|int $max_results_per_page The maximum number of results to return per page. If the response exceeds the maximum number of transactions or 10 MB, the API responds with &#39;InvalidInput&#39;. (optional, default to 10)
     * @param null|\DateTimeInterface $financial_event_group_started_before A date used for selecting financial event groups that opened before (but not at) a specified date and time, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) format. The date-time  must be later than FinancialEventGroupStartedAfter and no later than two minutes before the request was submitted. If FinancialEventGroupStartedAfter and FinancialEventGroupStartedBefore are more than 180 days apart, no financial event groups are returned. (optional)
     * @param null|\DateTimeInterface $financial_event_group_started_after A date used for selecting financial event groups that opened after (or at) a specified date and time, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) format. The date-time must be no later than two minutes before the request was submitted. (optional)
     * @param null|string $next_token A string token returned in the response of your previous request. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException
     */
    public function listFinancialEventGroups(AccessToken $accessToken, string $region, ?int $max_results_per_page = 10, ?\DateTimeInterface $financial_event_group_started_before = null, ?\DateTimeInterface $financial_event_group_started_after = null, ?string $next_token = null) : \AmazonPHP\SellingPartner\Model\Finances\FinancialEvents\ListFinancialEventGroupsResponse
    {
        $request = $this->listFinancialEventGroupsRequest($accessToken, $region, $max_results_per_page, $financial_event_group_started_before, $financial_event_group_started_after, $next_token);

        $this->configuration->extensions()->preRequest('FinancialEvents', 'listFinancialEventGroups', $request);

        try {
            $correlationId = $this->configuration->idGenerator()->generate();
            $sanitizedRequest = $request;

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

            if ($this->configuration->loggingEnabled('FinancialEvents', 'listFinancialEventGroups')) {
                $this->logger->log(
                    $this->configuration->logLevel('FinancialEvents', 'listFinancialEventGroups'),
                    'Amazon Selling Partner API pre request',
                    [
                        'api' => 'FinancialEvents',
                        'operation' => 'listFinancialEventGroups',
                        '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('FinancialEvents', 'listFinancialEventGroups', $request, $response);

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

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

                $this->logger->log(
                    $this->configuration->logLevel('FinancialEvents', 'listFinancialEventGroups'),
                    'Amazon Selling Partner API post request',
                    [
                        'api' => 'FinancialEvents',
                        'operation' => 'listFinancialEventGroups',
                        'response_correlation_id' => $correlationId,
                        'response_body' => (string) $sanitizedResponse->getBody(),
                        'response_headers' => $sanitizedResponse->getHeaders(),
                        'response_status_code' => $sanitizedResponse->getStatusCode(),
                        'request_uri' => (string) $sanitizedRequest->getUri(),
                        'request_body' => (string) $sanitizedRequest->getBody(),
                    ]
                );
            }
        } 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\Finances\FinancialEvents\ListFinancialEventGroupsResponse',
            []
        );
    }

    /**
     * Create request for operation 'listFinancialEventGroups'.
     *
     * @param null|int $max_results_per_page The maximum number of results to return per page. If the response exceeds the maximum number of transactions or 10 MB, the API responds with &#39;InvalidInput&#39;. (optional, default to 10)
     * @param null|\DateTimeInterface $financial_event_group_started_before A date used for selecting financial event groups that opened before (but not at) a specified date and time, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) format. The date-time  must be later than FinancialEventGroupStartedAfter and no later than two minutes before the request was submitted. If FinancialEventGroupStartedAfter and FinancialEventGroupStartedBefore are more than 180 days apart, no financial event groups are returned. (optional)
     * @param null|\DateTimeInterface $financial_event_group_started_after A date used for selecting financial event groups that opened after (or at) a specified date and time, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) format. The date-time must be no later than two minutes before the request was submitted. (optional)
     * @param null|string $next_token A string token returned in the response of your previous request. (optional)
     *
     * @throws InvalidArgumentException
     */
    public function listFinancialEventGroupsRequest(AccessToken $accessToken, string $region, ?int $max_results_per_page = 10, ?\DateTimeInterface $financial_event_group_started_before = null, ?\DateTimeInterface $financial_event_group_started_after = null, ?string $next_token = null) : RequestInterface
    {
        if ($max_results_per_page !== null && $max_results_per_page > 100) {
            throw new InvalidArgumentException('invalid value for "$max_results_per_page" when calling DefaultApi.listFinancialEventGroups, must be smaller than or equal to 100.');
        }

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

        $resourcePath = '/finances/v0/financialEventGroups';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $multipart = false;
        $query = '';

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

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

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

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

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

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

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

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

        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 listFinancialEvents.
     *
     * @param null|int $max_results_per_page The maximum number of results to return per page. If the response exceeds the maximum number of transactions or 10 MB, the API responds with &#39;InvalidInput&#39;. (optional, default to 100)
     * @param null|\DateTimeInterface $posted_after A date used for selecting financial events posted after (or at) a specified time. The date-time must be no later than two minutes before the request was submitted, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) date time format. (optional)
     * @param null|\DateTimeInterface $posted_before A date used for selecting financial events posted before (but not at) a specified time. The date-time must be later than PostedAfter and no later than two minutes before the request was submitted, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) date time format. If PostedAfter and PostedBefore are more than 180 days apart, no financial events are returned. You must specify the PostedAfter parameter if you specify the PostedBefore parameter. Default: Now minus two minutes. (optional)
     * @param null|string $next_token A string token returned in the response of your previous request. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException
     */
    public function listFinancialEvents(AccessToken $accessToken, string $region, ?int $max_results_per_page = 100, ?\DateTimeInterface $posted_after = null, ?\DateTimeInterface $posted_before = null, ?string $next_token = null) : \AmazonPHP\SellingPartner\Model\Finances\FinancialEvents\ListFinancialEventsResponse
    {
        $request = $this->listFinancialEventsRequest($accessToken, $region, $max_results_per_page, $posted_after, $posted_before, $next_token);

        $this->configuration->extensions()->preRequest('FinancialEvents', 'listFinancialEvents', $request);

        try {
            $correlationId = $this->configuration->idGenerator()->generate();
            $sanitizedRequest = $request;

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

            if ($this->configuration->loggingEnabled('FinancialEvents', 'listFinancialEvents')) {
                $this->logger->log(
                    $this->configuration->logLevel('FinancialEvents', 'listFinancialEvents'),
                    'Amazon Selling Partner API pre request',
                    [
                        'api' => 'FinancialEvents',
                        'operation' => 'listFinancialEvents',
                        '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('FinancialEvents', 'listFinancialEvents', $request, $response);

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

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

                $this->logger->log(
                    $this->configuration->logLevel('FinancialEvents', 'listFinancialEvents'),
                    'Amazon Selling Partner API post request',
                    [
                        'api' => 'FinancialEvents',
                        'operation' => 'listFinancialEvents',
                        'response_correlation_id' => $correlationId,
                        'response_body' => (string) $sanitizedResponse->getBody(),
                        'response_headers' => $sanitizedResponse->getHeaders(),
                        'response_status_code' => $sanitizedResponse->getStatusCode(),
                        'request_uri' => (string) $sanitizedRequest->getUri(),
                        'request_body' => (string) $sanitizedRequest->getBody(),
                    ]
                );
            }
        } 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\Finances\FinancialEvents\ListFinancialEventsResponse',
            []
        );
    }

    /**
     * Create request for operation 'listFinancialEvents'.
     *
     * @param null|int $max_results_per_page The maximum number of results to return per page. If the response exceeds the maximum number of transactions or 10 MB, the API responds with &#39;InvalidInput&#39;. (optional, default to 100)
     * @param null|\DateTimeInterface $posted_after A date used for selecting financial events posted after (or at) a specified time. The date-time must be no later than two minutes before the request was submitted, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) date time format. (optional)
     * @param null|\DateTimeInterface $posted_before A date used for selecting financial events posted before (but not at) a specified time. The date-time must be later than PostedAfter and no later than two minutes before the request was submitted, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) date time format. If PostedAfter and PostedBefore are more than 180 days apart, no financial events are returned. You must specify the PostedAfter parameter if you specify the PostedBefore parameter. Default: Now minus two minutes. (optional)
     * @param null|string $next_token A string token returned in the response of your previous request. (optional)
     *
     * @throws InvalidArgumentException
     */
    public function listFinancialEventsRequest(AccessToken $accessToken, string $region, ?int $max_results_per_page = 100, ?\DateTimeInterface $posted_after = null, ?\DateTimeInterface $posted_before = null, ?string $next_token = null) : RequestInterface
    {
        if ($max_results_per_page !== null && $max_results_per_page > 100) {
            throw new InvalidArgumentException('invalid value for "$max_results_per_page" when calling DefaultApi.listFinancialEvents, must be smaller than or equal to 100.');
        }

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

        $resourcePath = '/finances/v0/financialEvents';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $multipart = false;
        $query = '';

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

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

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

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

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

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

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

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

        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 listFinancialEventsByGroupId.
     *
     * @param string $event_group_id The identifier of the financial event group to which the events belong. (required)
     * @param null|int $max_results_per_page The maximum number of results to return per page. If the response exceeds the maximum number of transactions or 10 MB, the API responds with &#39;InvalidInput&#39;. (optional, default to 100)
     * @param null|\DateTimeInterface $posted_after A date used for selecting financial events posted after (or at) a specified time. The date-time **must** be more than two minutes before the time of the request, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) date time format. (optional)
     * @param null|\DateTimeInterface $posted_before A date used for selecting financial events posted before (but not at) a specified time. The date-time must be later than &#x60;PostedAfter&#x60; and no later than two minutes before the request was submitted, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) date time format. If &#x60;PostedAfter&#x60; and &#x60;PostedBefore&#x60; are more than 180 days apart, no financial events are returned. You must specify the &#x60;PostedAfter&#x60; parameter if you specify the &#x60;PostedBefore&#x60; parameter. Default: Now minus two minutes. (optional)
     * @param null|string $next_token A string token returned in the response of your previous request. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException
     */
    public function listFinancialEventsByGroupId(AccessToken $accessToken, string $region, string $event_group_id, ?int $max_results_per_page = 100, ?\DateTimeInterface $posted_after = null, ?\DateTimeInterface $posted_before = null, ?string $next_token = null) : \AmazonPHP\SellingPartner\Model\Finances\FinancialEvents\ListFinancialEventsResponse
    {
        $request = $this->listFinancialEventsByGroupIdRequest($accessToken, $region, $event_group_id, $max_results_per_page, $posted_after, $posted_before, $next_token);

        $this->configuration->extensions()->preRequest('FinancialEvents', 'listFinancialEventsByGroupId', $request);

        try {
            $correlationId = $this->configuration->idGenerator()->generate();
            $sanitizedRequest = $request;

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

            if ($this->configuration->loggingEnabled('FinancialEvents', 'listFinancialEventsByGroupId')) {
                $this->logger->log(
                    $this->configuration->logLevel('FinancialEvents', 'listFinancialEventsByGroupId'),
                    'Amazon Selling Partner API pre request',
                    [
                        'api' => 'FinancialEvents',
                        'operation' => 'listFinancialEventsByGroupId',
                        '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('FinancialEvents', 'listFinancialEventsByGroupId', $request, $response);

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

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

                $this->logger->log(
                    $this->configuration->logLevel('FinancialEvents', 'listFinancialEventsByGroupId'),
                    'Amazon Selling Partner API post request',
                    [
                        'api' => 'FinancialEvents',
                        'operation' => 'listFinancialEventsByGroupId',
                        'response_correlation_id' => $correlationId,
                        'response_body' => (string) $sanitizedResponse->getBody(),
                        'response_headers' => $sanitizedResponse->getHeaders(),
                        'response_status_code' => $sanitizedResponse->getStatusCode(),
                        'request_uri' => (string) $sanitizedRequest->getUri(),
                        'request_body' => (string) $sanitizedRequest->getBody(),
                    ]
                );
            }
        } 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\Finances\FinancialEvents\ListFinancialEventsResponse',
            []
        );
    }

    /**
     * Create request for operation 'listFinancialEventsByGroupId'.
     *
     * @param string $event_group_id The identifier of the financial event group to which the events belong. (required)
     * @param null|int $max_results_per_page The maximum number of results to return per page. If the response exceeds the maximum number of transactions or 10 MB, the API responds with &#39;InvalidInput&#39;. (optional, default to 100)
     * @param null|\DateTimeInterface $posted_after A date used for selecting financial events posted after (or at) a specified time. The date-time **must** be more than two minutes before the time of the request, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) date time format. (optional)
     * @param null|\DateTimeInterface $posted_before A date used for selecting financial events posted before (but not at) a specified time. The date-time must be later than &#x60;PostedAfter&#x60; and no later than two minutes before the request was submitted, in [ISO 8601](https://developer-docs.amazon.com/sp-api/docs/iso-8601) date time format. If &#x60;PostedAfter&#x60; and &#x60;PostedBefore&#x60; are more than 180 days apart, no financial events are returned. You must specify the &#x60;PostedAfter&#x60; parameter if you specify the &#x60;PostedBefore&#x60; parameter. Default: Now minus two minutes. (optional)
     * @param null|string $next_token A string token returned in the response of your previous request. (optional)
     *
     * @throws InvalidArgumentException
     */
    public function listFinancialEventsByGroupIdRequest(AccessToken $accessToken, string $region, string $event_group_id, ?int $max_results_per_page = 100, ?\DateTimeInterface $posted_after = null, ?\DateTimeInterface $posted_before = null, ?string $next_token = null) : RequestInterface
    {
        // verify the required parameter 'event_group_id' is set
        if ($event_group_id === null || (\is_array($event_group_id) && \count($event_group_id) === 0)) {
            throw new InvalidArgumentException(
                'Missing the required parameter $event_group_id when calling listFinancialEventsByGroupId'
            );
        }

        if ($max_results_per_page !== null && $max_results_per_page > 100) {
            throw new InvalidArgumentException('invalid value for "$max_results_per_page" when calling DefaultApi.listFinancialEventsByGroupId, must be smaller than or equal to 100.');
        }

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

        $resourcePath = '/finances/v0/financialEventGroups/{eventGroupId}/financialEvents';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $multipart = false;
        $query = '';

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

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

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

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

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

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

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

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

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

        // path params
        if ($event_group_id !== null) {
            $resourcePath = \str_replace(
                '{' . 'eventGroupId' . '}',
                ObjectSerializer::toPathValue($event_group_id),
                $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 listFinancialEventsByOrderId.
     *
     * @param string $order_id An Amazon-defined order identifier, in 3-7-7 format. (required)
     * @param null|int $max_results_per_page The maximum number of results to return per page. If the response exceeds the maximum number of transactions or 10 MB, the API responds with &#39;InvalidInput&#39;. (optional, default to 100)
     * @param null|string $next_token A string token returned in the response of your previous request. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException
     */
    public function listFinancialEventsByOrderId(AccessToken $accessToken, string $region, string $order_id, ?int $max_results_per_page = 100, ?string $next_token = null) : \AmazonPHP\SellingPartner\Model\Finances\FinancialEvents\ListFinancialEventsResponse
    {
        $request = $this->listFinancialEventsByOrderIdRequest($accessToken, $region, $order_id, $max_results_per_page, $next_token);

        $this->configuration->extensions()->preRequest('FinancialEvents', 'listFinancialEventsByOrderId', $request);

        try {
            $correlationId = $this->configuration->idGenerator()->generate();
            $sanitizedRequest = $request;

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

            if ($this->configuration->loggingEnabled('FinancialEvents', 'listFinancialEventsByOrderId')) {
                $this->logger->log(
                    $this->configuration->logLevel('FinancialEvents', 'listFinancialEventsByOrderId'),
                    'Amazon Selling Partner API pre request',
                    [
                        'api' => 'FinancialEvents',
                        'operation' => 'listFinancialEventsByOrderId',
                        '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('FinancialEvents', 'listFinancialEventsByOrderId', $request, $response);

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

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

                $this->logger->log(
                    $this->configuration->logLevel('FinancialEvents', 'listFinancialEventsByOrderId'),
                    'Amazon Selling Partner API post request',
                    [
                        'api' => 'FinancialEvents',
                        'operation' => 'listFinancialEventsByOrderId',
                        'response_correlation_id' => $correlationId,
                        'response_body' => (string) $sanitizedResponse->getBody(),
                        'response_headers' => $sanitizedResponse->getHeaders(),
                        'response_status_code' => $sanitizedResponse->getStatusCode(),
                        'request_uri' => (string) $sanitizedRequest->getUri(),
                        'request_body' => (string) $sanitizedRequest->getBody(),
                    ]
                );
            }
        } 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\Finances\FinancialEvents\ListFinancialEventsResponse',
            []
        );
    }

    /**
     * Create request for operation 'listFinancialEventsByOrderId'.
     *
     * @param string $order_id An Amazon-defined order identifier, in 3-7-7 format. (required)
     * @param null|int $max_results_per_page The maximum number of results to return per page. If the response exceeds the maximum number of transactions or 10 MB, the API responds with &#39;InvalidInput&#39;. (optional, default to 100)
     * @param null|string $next_token A string token returned in the response of your previous request. (optional)
     *
     * @throws InvalidArgumentException
     */
    public function listFinancialEventsByOrderIdRequest(AccessToken $accessToken, string $region, string $order_id, ?int $max_results_per_page = 100, ?string $next_token = null) : RequestInterface
    {
        // verify the required parameter 'order_id' is set
        if ($order_id === null || (\is_array($order_id) && \count($order_id) === 0)) {
            throw new InvalidArgumentException(
                'Missing the required parameter $order_id when calling listFinancialEventsByOrderId'
            );
        }

        if ($max_results_per_page !== null && $max_results_per_page > 100) {
            throw new InvalidArgumentException('invalid value for "$max_results_per_page" when calling DefaultApi.listFinancialEventsByOrderId, must be smaller than or equal to 100.');
        }

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

        $resourcePath = '/finances/v0/orders/{orderId}/financialEvents';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $multipart = false;
        $query = '';

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

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

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

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

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

        // path params
        if ($order_id !== null) {
            $resourcePath = \str_replace(
                '{' . 'orderId' . '}',
                ObjectSerializer::toPathValue($order_id),
                $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
        );
    }
}
