<?php

declare(strict_types=1);

namespace Paysera\CheckoutSdk\Service;

use Paysera\CheckoutSdk\Entity\PaymentCallback;
use Paysera\CheckoutSdk\Entity\RefundCallback;
use Paysera\CheckoutSdk\Exception\BaseException;
use Paysera\CheckoutSdk\Service\Normalizer\PaymentCallbackNormalizer;
use Paysera\CheckoutSdk\Service\Normalizer\RefundCallbackNormalizer;
use Paysera\CheckoutSdk\Service\Serializer\JsonSerializer;
use Paysera\CheckoutSdk\Service\Validator\PaymentCallbackValidator;
use Paysera\CheckoutSdk\Service\Validator\RefundCallbackValidator;
use Paysera\CheckoutSdk\Util\MessagePayloadExtractor;
use Psr\Http\Message\RequestInterface;

class PaymentApiCallbackBuilder
{
    private JsonSerializer $jsonSerializer;
    private MessagePayloadExtractor $messagePayloadExtractor;
    private RefundCallbackNormalizer $refundCallbackNormalizer;
    private RefundCallbackValidator $refundCallbackValidator;
    private PaymentCallbackValidator $paymentCallbackValidator;
    private PaymentCallbackNormalizer $paymentCallbackNormalizer;

    public function __construct(
        JsonSerializer $jsonSerializer,
        MessagePayloadExtractor $messagePayloadExtractor,
        PaymentCallbackNormalizer $paymentCallbackNormalizer,
        PaymentCallbackValidator $paymentCallbackValidator,
        RefundCallbackNormalizer $refundCallbackNormalizer,
        RefundCallbackValidator $refundCallbackValidator
    ) {
        $this->jsonSerializer = $jsonSerializer;
        $this->messagePayloadExtractor = $messagePayloadExtractor;
        $this->paymentCallbackValidator = $paymentCallbackValidator;
        $this->paymentCallbackNormalizer = $paymentCallbackNormalizer;
        $this->refundCallbackNormalizer = $refundCallbackNormalizer;
        $this->refundCallbackValidator = $refundCallbackValidator;
    }

    /**
     * @throws BaseException
     */
    public function buildPaymentCallback(RequestInterface $request): PaymentCallback
    {
        $requestPayload = $this->messagePayloadExtractor->getPayload($request);
        $requestData = $this->jsonSerializer->deserialize($requestPayload);
        $paymentCallback = $this->paymentCallbackNormalizer->denormalize($requestData);

        $this->paymentCallbackValidator->validate($paymentCallback);

        return $paymentCallback;
    }

    /**
     * @throws BaseException
     */
    public function buildRefundCallback(RequestInterface $request): RefundCallback
    {
        $requestPayload = $this->messagePayloadExtractor->getPayload($request);
        $requestData = $this->jsonSerializer->deserialize($requestPayload);
        $refundCallback = $this->refundCallbackNormalizer->denormalize($requestData);

        $this->refundCallbackValidator->validate($refundCallback);

        return $refundCallback;
    }
}
