<?php

declare(strict_types=1);

namespace Myvetshop\Module\Clinique\Stock;

use GuzzleHttp\ClientInterface;

class CentravetStockApi
{
    public const TOKEN_CACHE_KEY = 'centravet_stock_jwt_token';

    private \Cache $cache;

    private ClientInterface $client;

    private string $apiUrl;

    private string $apiLogin;

    private string $apiPass;

    private ?string $apiJwtToken = null;

    /**
     * Génération d'un token JWT pour l'Api CentraVet (one-shot).
     *
     * @throws \Exception
     */
    public function getToken(): string
    {
        if (!$this->apiJwtToken) {
            $cachedToken = $this->cache->get(self::TOKEN_CACHE_KEY);
            if (!$cachedToken || !is_string($cachedToken)) {
                $response = $this->client->request(
                    'POST',
                    $this->apiUrl . '/auth/V2/tokens/user',
                    [
                        'body' => \json_encode(['email' => $this->apiLogin, 'password' => $this->apiPass]),
                        'headers' => [
                            'Content-Type' => 'application/json',
                        ],
                    ]
                );

                $statusCode = $response->getStatusCode();
                $body = $response->getBody();

                if ($statusCode < 200 || $statusCode >= 300 || !$body) {
                    throw new \Exception('Impossible de récupérer un token JWT');
                }

                $cachedToken = \trim($body->getContents(), ' "');
                // Token en cache pour 1500 secondes
                $this->cache->set(self::TOKEN_CACHE_KEY, $this->apiJwtToken, 1500);
            }

            $this->apiJwtToken = $cachedToken;
        }

        return $this->apiJwtToken;
    }

    public function checkStock(string $codeclinique, string $codeProduit, int $quantite): bool
    {
        $token = $this->getToken();

        $queryString = \http_build_query(
            [
                'codeClinique' => \str_pad($codeclinique, 6, '0', STR_PAD_LEFT),
                'homeDelivery' => 'false',
            ]
        );

        $response = $this->client->request(
            'POST',
            $this->apiUrl . '/openwebveto/V1/stocks/210633?' . $queryString,
            [
                'body' => \json_encode([['articleCode' => $codeProduit, 'quantity' => $quantite]]),
                'headers' => [
                    'Authorization' => 'Bearer ' . $token,
                    'Content-Type' => 'application/json',
                ],
            ]
        );

        $statusCode = $response->getStatusCode();
        $body = $response->getBody();

        if ($statusCode < 200 || $statusCode >= 300 || !$body) {
            throw new \Exception('Code HTTP invalide');
        }
        $lines = \json_decode($body->getContents(), true);
        if (!\is_array($lines)) {
            throw new \Exception('JSON invalide');
        }

        $nbManquants = \array_filter(
            $lines,
            fn ($line) => false === $line['available']
        );

        // Si au moins 1 produit manquant, alors on considère que le stock n'est pas bon
        return 0 === \count($nbManquants);
    }

    public function __construct(
        \Cache $cache,
        ClientInterface $client,
        string $apiUrl,
        string $apiLogin,
        string $apiPass
    ) {
        $this->cache = $cache;
        $this->client = $client;
        $this->apiUrl = $apiUrl;
        $this->apiLogin = $apiLogin;
        $this->apiPass = $apiPass;
    }
}
