<?php

namespace WPDesk\FakturyKSEF\Api\Middleware;

use WPDeskKSEFVendor\GuzzleHttp\Exception\ConnectException;
use WPDeskKSEFVendor\GuzzleHttp\Exception\ServerException;
use WPDeskKSEFVendor\GuzzleHttp\Exception\TransferException;
use WPDeskKSEFVendor\GuzzleHttp\Middleware;
use WPDeskKSEFVendor\GuzzleHttp\Psr7\Request;
use WPDeskKSEFVendor\GuzzleHttp\Psr7\Response;

class KsefRetryMiddleware {

	private const DELAY_IN_MS    = 2000;
	private const MAX_RETRIES    = 10;
	public const MIDDLEWARE_NAME = 'ksef_retry';

	public static function create(): callable {
		return Middleware::retry(
			self::decider(),
			self::delay()
		);
	}

	private static function decider(): callable {
		return function (
			$retries,
			Request $request,
			?Response $response = null,
			?TransferException $exception = null
		) {
			if ( $retries >= self::MAX_RETRIES ) {
				return false;
			}

			if ( $exception instanceof ServerException ) {
				return true;
			}

			if ( $exception instanceof ConnectException ) {
				return true;
			}

			if ( $response && $response->getStatusCode() >= 500 ) {
				return true;
			}

			if ( $response ) {
				$body = (string) $response->getBody();

				$response->getBody()->rewind();

				$json = json_decode( $body, true );

				if ( isset( $json['status']['code'] ) && $json['status']['code'] === 100 ) {
					return true;
				}
			}

			return false;
		};
	}

	private static function delay(): callable {
		return function ( $number_of_retries ) { //phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
			return self::DELAY_IN_MS;
		};
	}
}
