<?php

namespace App\Tests\A_Unit\Stock;

use GuzzleHttp\ClientInterface;
use GuzzleHttp\Message\ResponseInterface;
use GuzzleHttp\Stream\StreamInterface;
use Myvetshop\Module\Clinique\Stock\CentravetStockApi;
use PHPUnit\Framework\TestCase;

class CentravetStockApiTest extends TestCase
{
    public function testGetTokenCached(): void
    {
        $cache = $this->getMockBuilder(\Cache::class)
            ->disableOriginalConstructor()
            ->getMock();

        $cache
            ->expects($this->once())
            ->method('get')
            ->with(CentravetStockApi::TOKEN_CACHE_KEY)
            ->willReturn('api_token');

        $httpClient = $this->getMockBuilder(ClientInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $api = new CentravetStockApi(
            $cache,
            $httpClient,
            'http://transnet.centravet.net',
            'login',
            'pass'
        );

        self::assertEquals('api_token', $api->getToken());
    }

    public function testGetTokenNotCached(): void
    {
        $cache = $this->getMockBuilder(\Cache::class)
            ->disableOriginalConstructor()
            ->getMock();

        $cache
            ->expects($this->once())
            ->method('get')
            ->with(CentravetStockApi::TOKEN_CACHE_KEY)
            ->willReturn(null);

        $httpClient = $this->getMockBuilder(ClientInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $response = $this->getMockBuilder(ResponseInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $response
            ->method('getStatusCode')
            ->willReturn(200);

        $bodyStream = $this->getMockBuilder(StreamInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $bodyStream
            ->method('getContents')
            ->willReturn('"api_token"');

        $response
            ->method('getBody')
            ->willReturn($bodyStream);

        $httpClient
            ->expects($this->once())
            ->method('post')
            ->with(
                'http://transnet.centravet.net/auth/V2/tokens/user',
                [
                    'body' => '{"email":"login","password":"pass"}',
                    'headers' => [
                        'Content-Type' => 'application/json',
                    ],
                ]
            )
            ->willReturn($response);

        $api = new CentravetStockApi(
            $cache,
            $httpClient,
            'http://transnet.centravet.net',
            'login',
            'pass'
        );

        self::assertEquals('api_token', $api->getToken());
    }

    public function testCheckStockInStock(): void
    {
        $cache = $this->getMockBuilder(\Cache::class)
            ->disableOriginalConstructor()
            ->getMock();

        $cache
            ->expects($this->once())
            ->method('get')
            ->with(CentravetStockApi::TOKEN_CACHE_KEY)
            ->willReturn('api_token');

        $httpClient = $this->getMockBuilder(ClientInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $response = $this->getMockBuilder(ResponseInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $response
            ->method('getStatusCode')
            ->willReturn(200);

        $bodyStream = $this->getMockBuilder(StreamInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $bodyStream
            ->method('getContents')
            ->willReturn('[{"available":true}]');

        $response
            ->method('getBody')
            ->willReturn($bodyStream);

        $httpClient
            ->expects($this->once())
            ->method('post')
            ->with(
                'http://transnet.centravet.net/openwebveto/V1/stocks/210633?codeClinique=123456&homeDelivery=false',
                [
                    'body' => '[{"articleCode":"1234","quantity":1}]',
                    'headers' => [
                        'Content-Type' => 'application/json',
                        'Authorization' => 'Bearer api_token',
                    ],
                ]
            )
            ->willReturn($response);

        $api = new CentravetStockApi(
            $cache,
            $httpClient,
            'http://transnet.centravet.net',
            'login',
            'pass'
        );

        self::assertEquals(true, $api->checkStock('123456', '1234', 1));
    }

    public function testCheckStockOutOfStock(): void
    {
        $cache = $this->getMockBuilder(\Cache::class)
            ->disableOriginalConstructor()
            ->getMock();

        $cache
            ->expects($this->once())
            ->method('get')
            ->with(CentravetStockApi::TOKEN_CACHE_KEY)
            ->willReturn('api_token');

        $httpClient = $this->getMockBuilder(ClientInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $response = $this->getMockBuilder(ResponseInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $response
            ->method('getStatusCode')
            ->willReturn(200);

        $bodyStream = $this->getMockBuilder(StreamInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $bodyStream
            ->method('getContents')
            ->willReturn('[{"available":false}]');

        $response
            ->method('getBody')
            ->willReturn($bodyStream);

        $httpClient
            ->expects($this->once())
            ->method('post')
            ->with(
                'http://transnet.centravet.net/openwebveto/V1/stocks/210633?codeClinique=123456&homeDelivery=false',
                [
                    'body' => '[{"articleCode":"1234","quantity":1}]',
                    'headers' => [
                        'Content-Type' => 'application/json',
                        'Authorization' => 'Bearer api_token',
                    ],
                ]
            )
            ->willReturn($response);

        $api = new CentravetStockApi(
            $cache,
            $httpClient,
            'http://transnet.centravet.net',
            'login',
            'pass'
        );

        self::assertEquals(false, $api->checkStock('123456', '1234', 1));
    }
}
