<?php

// this file is @generated
declare(strict_types=1);

namespace Svix\Api;

use Svix\Exception\ApiException;
use Svix\Models\BulkReplayIn;
use Svix\Models\EndpointHeadersIn;
use Svix\Models\EndpointHeadersOut;
use Svix\Models\EndpointHeadersPatchIn;
use Svix\Models\EndpointIn;
use Svix\Models\EndpointOut;
use Svix\Models\EndpointPatch;
use Svix\Models\EndpointSecretOut;
use Svix\Models\EndpointSecretRotateIn;
use Svix\Models\EndpointStats;
use Svix\Models\EndpointTransformationIn;
use Svix\Models\EndpointUpsertIn;
use Svix\Models\EventExampleIn;
use Svix\Models\ListResponseEndpointOut;
use Svix\Models\MessageOut;
use Svix\Models\RecoverIn;
use Svix\Models\RecoverOut;
use Svix\Models\ReplayIn;
use Svix\Models\ReplayOut;
use Svix\Request\SvixHttpClient;

class Endpoint
{
    public EndpointTransformation $transformation;

    public function __construct(
        private readonly SvixHttpClient $client,
    ) {
        $this->transformation = new EndpointTransformation($client);
    }

    /**
     * List the application's endpoints.
     *
     * @throws ApiException
     */
    public function list(
        string $appId,
        EndpointListOptions $options = new EndpointListOptions(),
    ): ListResponseEndpointOut {
        $request = $this->client->newReq('GET', "/api/v1/app/{$appId}/endpoint");
        $request->setQueryParam('limit', $options->limit);
        $request->setQueryParam('iterator', $options->iterator);
        $request->setQueryParam('order', $options->order);
        $res = $this->client->send($request);

        return ListResponseEndpointOut::fromJson($res);
    }

    /**
     * Create a new endpoint for the application.
     *
     * When `secret` is `null` the secret is automatically generated (recommended).
     *
     * @throws ApiException
     */
    public function create(
        string $appId,
        EndpointIn $endpointIn,
        EndpointCreateOptions $options = new EndpointCreateOptions(),
    ): EndpointOut {
        $request = $this->client->newReq('POST', "/api/v1/app/{$appId}/endpoint");
        $request->setHeaderParam('idempotency-key', $options->idempotencyKey);
        $request->setBody(json_encode($endpointIn));
        $res = $this->client->send($request);

        return EndpointOut::fromJson($res);
    }

    /**
     * Get an endpoint.
     *
     * @throws ApiException
     */
    public function get(
        string $appId,
        string $endpointId,
    ): EndpointOut {
        $request = $this->client->newReq('GET', "/api/v1/app/{$appId}/endpoint/{$endpointId}");
        $res = $this->client->send($request);

        return EndpointOut::fromJson($res);
    }

    /**
     * Create or update an endpoint.
     *
     * @throws ApiException
     */
    public function upsert(
        string $appId,
        string $endpointId,
        EndpointUpsertIn $endpointUpsertIn,
    ): EndpointOut {
        $request = $this->client->newReq('PUT', "/api/v1/app/{$appId}/endpoint/{$endpointId}");
        $request->setBody(json_encode($endpointUpsertIn));
        $res = $this->client->send($request);

        return EndpointOut::fromJson($res);
    }

    /**
     * Delete an endpoint.
     *
     * @throws ApiException
     */
    public function delete(
        string $appId,
        string $endpointId,
    ): void {
        $request = $this->client->newReq('DELETE', "/api/v1/app/{$appId}/endpoint/{$endpointId}");
        $res = $this->client->sendNoResponseBody($request);
    }

    /**
     * Partially update an endpoint.
     *
     * @throws ApiException
     */
    public function patch(
        string $appId,
        string $endpointId,
        EndpointPatch $endpointPatch,
    ): EndpointOut {
        $request = $this->client->newReq('PATCH', "/api/v1/app/{$appId}/endpoint/{$endpointId}");
        $request->setBody(json_encode($endpointPatch));
        $res = $this->client->send($request);

        return EndpointOut::fromJson($res);
    }

    /**
     * Get the endpoint's signing secret.
     *
     * This is used to verify the authenticity of the webhook.
     * For more information please refer to [the consuming webhooks docs](https://docs.svix.com/consuming-webhooks/).
     *
     * @throws ApiException
     */
    public function getSecret(
        string $appId,
        string $endpointId,
    ): EndpointSecretOut {
        $request = $this->client->newReq('GET', "/api/v1/app/{$appId}/endpoint/{$endpointId}/secret");
        $res = $this->client->send($request);

        return EndpointSecretOut::fromJson($res);
    }

    /**
     * Rotates the endpoint's signing secret.
     *
     * The previous secret will remain valid for the specified grace period (default 24 hours).
     *
     * @throws ApiException
     */
    public function rotateSecret(
        string $appId,
        string $endpointId,
        EndpointSecretRotateIn $endpointSecretRotateIn,
        EndpointRotateSecretOptions $options = new EndpointRotateSecretOptions(),
    ): void {
        $request = $this->client->newReq('POST', "/api/v1/app/{$appId}/endpoint/{$endpointId}/secret/rotate");
        $request->setHeaderParam('idempotency-key', $options->idempotencyKey);
        $request->setBody(json_encode($endpointSecretRotateIn));
        $res = $this->client->sendNoResponseBody($request);
    }

    /**
     * Get the additional headers to be sent with the webhook.
     *
     * @throws ApiException
     */
    public function getHeaders(
        string $appId,
        string $endpointId,
    ): EndpointHeadersOut {
        $request = $this->client->newReq('GET', "/api/v1/app/{$appId}/endpoint/{$endpointId}/headers");
        $res = $this->client->send($request);

        return EndpointHeadersOut::fromJson($res);
    }

    /**
     * Set the additional headers to be sent with the webhook.
     *
     * @throws ApiException
     */
    public function setHeaders(
        string $appId,
        string $endpointId,
        EndpointHeadersIn $endpointHeadersIn,
    ): void {
        $request = $this->client->newReq('PUT', "/api/v1/app/{$appId}/endpoint/{$endpointId}/headers");
        $request->setBody(json_encode($endpointHeadersIn));
        $res = $this->client->sendNoResponseBody($request);
    }

    /**
     * Partially set the additional headers to be sent with the webhook.
     *
     * @throws ApiException
     */
    public function patchHeaders(
        string $appId,
        string $endpointId,
        EndpointHeadersPatchIn $endpointHeadersPatchIn,
    ): void {
        $request = $this->client->newReq('PATCH', "/api/v1/app/{$appId}/endpoint/{$endpointId}/headers");
        $request->setBody(json_encode($endpointHeadersPatchIn));
        $res = $this->client->sendNoResponseBody($request);
    }

    /**
     * Replays messages to the endpoint.
     *
     * Only messages that were created after `since` will be sent.
     * Messages that were previously sent to the endpoint are not resent.
     *
     * A completed task will return a payload like the following:
     * ```json
     * {
     *   "id": "qtask_33qen93MNuelBAq1T9G7eHLJRsF",
     *   "status": "finished",
     *   "task": "endpoint.replay",
     *   "data": {
     *     "messagesSent": 2
     *   }
     * }
     * ```
     *
     * @throws ApiException
     */
    public function replayMissing(
        string $appId,
        string $endpointId,
        ReplayIn $replayIn,
        EndpointReplayMissingOptions $options = new EndpointReplayMissingOptions(),
    ): ReplayOut {
        $request = $this->client->newReq('POST', "/api/v1/app/{$appId}/endpoint/{$endpointId}/replay-missing");
        $request->setHeaderParam('idempotency-key', $options->idempotencyKey);
        $request->setBody(json_encode($replayIn));
        $res = $this->client->send($request);

        return ReplayOut::fromJson($res);
    }

    /**
     * Bulk replay messages sent to the endpoint.
     *
     * Only messages that were created after `since` will be sent.
     * This will replay both successful, and failed messages
     *
     * A completed task will return a payload like the following:
     * ```json
     * {
     *   "id": "qtask_33qen93MNuelBAq1T9G7eHLJRsF",
     *   "status": "finished",
     *   "task": "endpoint.bulk-replay",
     *   "data": {
     *     "messagesSent": 2
     *   }
     * }
     * ```
     *
     * @throws ApiException
     */
    public function bulkReplay(
        string $appId,
        string $endpointId,
        BulkReplayIn $bulkReplayIn,
        EndpointBulkReplayOptions $options = new EndpointBulkReplayOptions(),
    ): ReplayOut {
        $request = $this->client->newReq('POST', "/api/v1/app/{$appId}/endpoint/{$endpointId}/bulk-replay");
        $request->setHeaderParam('idempotency-key', $options->idempotencyKey);
        $request->setBody(json_encode($bulkReplayIn));
        $res = $this->client->send($request);

        return ReplayOut::fromJson($res);
    }

    /**
     * Get basic statistics for the endpoint.
     *
     * @throws ApiException
     */
    public function getStats(
        string $appId,
        string $endpointId,
        EndpointGetStatsOptions $options = new EndpointGetStatsOptions(),
    ): EndpointStats {
        $request = $this->client->newReq('GET', "/api/v1/app/{$appId}/endpoint/{$endpointId}/stats");
        $request->setQueryParam('since', $options->since);
        $request->setQueryParam('until', $options->until);
        $res = $this->client->send($request);

        return EndpointStats::fromJson($res);
    }

    /**
     * Resend all failed messages since a given time.
     *
     * Messages that were sent successfully, even if failed initially, are not resent.
     *
     * A completed task will return a payload like the following:
     * ```json
     * {
     *   "id": "qtask_33qen93MNuelBAq1T9G7eHLJRsF",
     *   "status": "finished",
     *   "task": "endpoint.recover",
     *   "data": {
     *     "messagesSent": 2
     *   }
     * }
     * ```
     *
     * @throws ApiException
     */
    public function recover(
        string $appId,
        string $endpointId,
        RecoverIn $recoverIn,
        EndpointRecoverOptions $options = new EndpointRecoverOptions(),
    ): RecoverOut {
        $request = $this->client->newReq('POST', "/api/v1/app/{$appId}/endpoint/{$endpointId}/recover");
        $request->setHeaderParam('idempotency-key', $options->idempotencyKey);
        $request->setBody(json_encode($recoverIn));
        $res = $this->client->send($request);

        return RecoverOut::fromJson($res);
    }

    /**
     * Send an example message for an event.
     *
     * @throws ApiException
     */
    public function sendExample(
        string $appId,
        string $endpointId,
        EventExampleIn $eventExampleIn,
        EndpointSendExampleOptions $options = new EndpointSendExampleOptions(),
    ): MessageOut {
        $request = $this->client->newReq('POST', "/api/v1/app/{$appId}/endpoint/{$endpointId}/send-example");
        $request->setHeaderParam('idempotency-key', $options->idempotencyKey);
        $request->setBody(json_encode($eventExampleIn));
        $res = $this->client->send($request);

        return MessageOut::fromJson($res);
    }

    /**
     * This operation was renamed to `set-transformation`.
     *
     * @throws ApiException
     */
    public function transformationPartialUpdate(
        string $appId,
        string $endpointId,
        EndpointTransformationIn $endpointTransformationIn,
    ): void {
        $request = $this->client->newReq('PATCH', "/api/v1/app/{$appId}/endpoint/{$endpointId}/transformation");
        $request->setBody(json_encode($endpointTransformationIn));
        $res = $this->client->sendNoResponseBody($request);
    }
}
