<?php

declare(strict_types=1);

namespace KupShop\LuigisBoxBundle\Api;

use Answear\LuigisBoxBundle\Exception\BadRequestException;
use Answear\LuigisBoxBundle\Exception\MalformedResponseException;
use Answear\LuigisBoxBundle\Service\SearchClient;
use KupShop\LuigisBoxBundle\Api\Builder\TopItemsUrlBuilder;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\HttpFoundation\Response;
use Webmozart\Assert\Assert;

class TopItemsRequest
{
    /**
     * @var SearchClient
     */
    private $client;

    private TopItemsFactory $topItemsFactory;

    public function __construct(
        SearchClient $client,
        TopItemsFactory $topItemsFactory,
    ) {
        $this->client = $client;
        $this->topItemsFactory = $topItemsFactory;
    }

    public function search(TopItemsUrlBuilder $searchUrlBuilder): array
    {
        $request = $this->topItemsFactory->prepareRequest($searchUrlBuilder);

        $url = $searchUrlBuilder->toUrlQuery();

        return $this->handleResponse($request, $this->client->request($request));
    }

    private function handleResponse(\GuzzleHttp\Psr7\Request $request, ResponseInterface $response): array
    {
        if (\in_array($response->getStatusCode(), [Response::HTTP_NOT_FOUND, Response::HTTP_BAD_REQUEST], true)) {
            throw new BadRequestException($response, $request);
        }

        if ($response->getBody()->isSeekable()) {
            $response->getBody()->rewind();
        }

        $responseText = $response->getBody()->getContents();

        try {
            if (empty($responseText)) {
                throw new \RuntimeException('Empty response.');
            }
            $decoded = \json_decode($responseText, true, 512, JSON_THROW_ON_ERROR);
            Assert::isArray($decoded);
        } catch (\Throwable $e) {
            throw new MalformedResponseException($e->getMessage(), $response, $request, $e);
        }

        return $decoded;
    }
}
