<?php

namespace Slovocast\Tests\Controller\User;

use Slovocast\Tests\TestCase;
use Slovocast\Domain\Repository\User\UserRepositoryInterface;
use Slovocast\Domain\Entity\User;
use Odan\Session\SessionInterface;
use Psr\Http\Message\ServerRequestInterface as Request;

class RegisterUserActionTest extends TestCase
{
    protected function getUser(): User
    {
        return User::fromArray([
            'email' => 'dave@slovocast.com',
            'name' => 'Dave SH',
            'password' => 'hashed_password'
        ]);
    }

    protected function createNewUserRequest(): Request
    {
        $user = $this->getUser();
        return $this->createRequest('POST', '/users/register')
                    ->withParsedBody([
                        'email' => $user->getEmail(),
                        'name' => $user->getName(),
                        'password' => $user->getPassword(),
                        'checked_password' => $user->getPassword()
                    ]);
    }

    protected function createNewUserRequestWithMismatchedPasswords(): Request
    {
        $user = $this->getUser();
        return $this->createRequest('POST', '/users/register')
                    ->withParsedBody([
                        'email' => $user->getEmail(),
                        'name' => $user->getName(),
                        'password' => $user->getPassword(),
                        'checked_password' => 'no-math'
                    ]);
    }


    /**
     * Set up the Application, the DI Container, and the Repository mock
     */
    protected function setUp(): void
    {

    }

    public function testSuccessfulRegistration(): void
    {
        $user = $this->getUser();
        $app = $this->getAppInstance();

        /** @var \DI\Container */
        $container = $app->getContainer();
        $userRepository = $this->prophesize(UserRepositoryInterface::class);
        $userRepository->save($user)->willReturn(true);
        $container->set(
            UserRepositoryInterface::class,
            $userRepository->reveal()
        );

        $request = $this->createNewUserRequest(); 

        $response = $app->handle($request);
        $this->assertEquals(200, $response->getStatusCode());
    }

    public function testFailingRegistration(): void
    {
        $user = $this->getUser();
        $app = $this->getAppInstance();

        /** @var $container \DI\Container */
        $container = $app->getContainer();

        $userRepository = $this->prophesize(UserRepositoryInterface::class);
        $userRepository->save($user)->willReturn(false);
        $container->set(
            UserRepositoryInterface::class, 
            $userRepository->reveal()
        );

        $request = $this->createNewUserRequest();

        $response = $app->handle($request);
        $this->assertEquals(400, $response->getStatusCode());

        $responseBody = $response->getBody();
        // get the class of the flash on the rendered page
        $this->assertTrue((bool)preg_match('/flash error/', $responseBody));
        // get the text inside the flash
        $this->assertTrue((bool)preg_match('/Unable to register user\./', $responseBody));

        /**
         * The Flash messages are already exhausted while rendering the
         * templates. We should check the template for the error.
         */
        $flash = $container->get(SessionInterface::class)->getFlash();
        $errorMessages = $flash->get('error');
        $this->assertIsArray($errorMessages);
        //$this->assertNotEmpty($errorMessages);
        //$this->assertEquals('Unable to register user.', $errorMessages[0]);
    }

    public function testMismatchPassword(): void
    {
        $user = $this->getUser();
        $app = $this->getAppInstance();

        /** @var $container \DI\Cotnainer */
        $container = $app->getContainer();

        $userRepository = $this->prophesize(UserRepositoryInterface::class);
        $userRepository->save($user)->willReturn(true);

        $container->set(
            UserRepositoryInterface::class,
            $userRepository->reveal()
        );

        $request = $this->createNewUserRequestWithMismatchedPasswords();

        $response = $app->handle($request);
        $this->assertEquals(400, $response->getStatusCode());
    }
}