<?php /** @noinspection PhpUnhandledExceptionInspection */

namespace App\Tests\Unit\Service\Mobyt;

use App\Service\Mobyt\MobytService;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class TestableMobytService extends MobytService {
    public function connect(string $login, string $password): void { parent::connect($login, $password); }
    public function getUserId(): string { return parent::getUserId(); }
    public function getSessionKey(): string { return parent::getSessionKey(); }
}

class MobytServiceTest extends TestCase
{
    private HttpClientInterface $client;

    public function setUp():void
    {
        $this->client = $this->getMockBuilder(HttpClientInterface::class)
            ->disableOriginalConstructor()
            ->getMock();
    }

    /**
     * @see MobytService::connect()
     * @see MobytService::getUserId()
     * @see MobytService::getSessionKey()
     */
    public function testConnect(): void {

        $mobytService = $this->getMockBuilder(TestableMobytService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['connect', 'getUserId', 'getSessionKey'])
            ->getMock();

        $login = 'foo';
        $password = 'bar';

        $mobytService
            ->expects(self::once())
            ->method('getContent')
            ->with(
                'login',
                [],
                [
                    'headers' => [
                        'Content-Type: application/json',
                        'Authorization: Basic ' . base64_encode($login.':'.$password),
                    ]
                ]
            )
            ->willReturn('123;456');

        $mobytService->connect($login, $password);

        $this->assertEquals(
            '123',
            $mobytService->getUserId()
        );

        $this->assertEquals(
            '456',
            $mobytService->getSessionKey()
        );
    }

    /**
     * @see MobytService::getUserStatus()
     */
    public function testGetUserStatus(): void {

        $mobytService = $this->getMockBuilder(TestableMobytService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['getUserStatus'])
            ->getMock();

        $login = 'foo';
        $password = 'bar';

        $mobytService->expects(self::once())->method('connect')->with($login, $password);

        $mobytService->method('getUserId')->willReturn('123');
        $mobytService->method('getSessionKey')->willReturn('456');

        $mobytService
            ->expects(self::once())
            ->method('getJsonContent')
            ->with(
                'status',
                ['getMoney' => 'true', 'typeAliases' => 'true'],
                [
                    'headers' => [ 'user_key' => '123', 'Session_key' => '456' ]
                ]
            );

        $mobytService->getUserStatus($login, $password);
    }

    /**
     * @see MobytService::hasCredentialsCorrect()
     */
    public function testHasCredentialsCorrect(): void {
        $mobytService = $this->getMockBuilder(TestableMobytService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['hasCredentialsCorrect'])
            ->getMock();

        $login = 'foo';
        $password = 'bar';

        $mobytService->expects(self::once())->method('connect')->with($login, $password);

        $this->assertTrue($mobytService->hasCredentialsCorrect($login, $password));
    }

    /**
     * @see MobytService::hasCredentialsCorrect()
     */
    public function testHasCredentialsNotCorrect(): void {
        $mobytService = $this->getMockBuilder(TestableMobytService::class)
            ->setConstructorArgs([$this->client])
            ->setMethodsExcept(['hasCredentialsCorrect'])
            ->getMock();

        $login = 'foo';
        $password = 'bar';

        $mobytService->expects(self::once())->method('connect')->with($login, $password)->willThrowException(new NotFoundHttpException());

        $this->assertFalse($mobytService->hasCredentialsCorrect($login, $password));
    }
}
