<?php

declare(strict_types=1);

namespace Paysera\CheckoutSdk\Service\Validator;

use Paysera\CheckoutSdk\Entity\RefundCallback;
use Paysera\CheckoutSdk\Exception\ValidationException;

class RefundCallbackValidator
{
    public const CALLBACK_MAX_AGE_SECONDS = 300;

    private RefundStatusValidator $refundStatusValidator;

    public function __construct(
        RefundStatusValidator $refundStatusValidator
    ) {
        $this->refundStatusValidator = $refundStatusValidator;
    }

    /**
     * @throws ValidationException
     */
    public function validate(RefundCallback $refundCallback): void
    {
        $errors = [];

        if (trim($refundCallback->getOrderId()) === '') {
            $errors['order_id'] = 'order ID is required.';
        }

        if (trim($refundCallback->getReference()) === '') {
            $errors['reference'] = 'reference is required.';
        }

        if ($refundCallback->getAmount() <= 0) {
            $errors['amount'] = 'amount must be greater than 0.';
        }

        if (trim($refundCallback->getCurrency()) === '') {
            $errors['currency'] = 'currency is required.';
        }

        if ((time() - $refundCallback->getTimestamp()) > self::CALLBACK_MAX_AGE_SECONDS) {
            $errors['timestamp'] = 'The request timestamp is older than ' . self::CALLBACK_MAX_AGE_SECONDS . ' seconds.';
        }

        if ($refundCallback->getTimestamp() > time()) {
            $errors['timestamp'] = 'The request timestamp is in the future.';
        }

        try {
            $this->refundStatusValidator->validate($refundCallback->getRefundStatus()->getValue());
        } catch (ValidationException $exception) {
            $errors['status'] = $exception->getContext();
        }

        if ($errors !== []) {
            throw (new ValidationException())
                ->setContext($errors)
            ;
        }
    }
}
