<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\MainBundle\Tests\Controller;

use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Repository\UserRepositoryInterface;
use Chill\MainBundle\Test\PrepareClientTrait;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;

/**
 * @internal
 *
 * @coversNothing
 */
final class UserControllerTest extends WebTestCase
{
    use PrepareClientTrait;

    public function testList()
    {
        $client = $this->getClientAuthenticatedAsAdmin();

        // get the list
        $client->request('GET', '/fr/admin/main/user');
        self::assertResponseIsSuccessful();
    }

    public function testNew()
    {
        $client = $this->getClientAuthenticated('admin');

        $crawler = $client->request('GET', '/fr/admin/main/user/new');

        self::assertResponseIsSuccessful();

        $username = 'Test_user'.uniqid();
        $password = 'Password_1234!';

        // Fill in the form and submit it

        $form = $crawler->selectButton('Créer & fermer')->form([
            'chill_mainbundle_user[username]' => $username,
            'chill_mainbundle_user[plainPassword][first]' => $password,
            'chill_mainbundle_user[plainPassword][second]' => $password,
            'chill_mainbundle_user[email]' => $username.'@gmail.com',
            'chill_mainbundle_user[label]' => $username,
        ]);

        $client->submit($form);
        $crawler = $client->followRedirect();

        // Check data in the show view
        $this->assertStringContainsString(
            $username,
            $crawler->text(),
            'page contains the name of the user'
        );

        // test the auth of the new client
        $this->isPasswordValid($username, $password);
    }

    /**
     * @dataProvider dataGenerateUserId
     */
    public function testUpdate(int $userId, string $username)
    {
        $client = $this->getClientAuthenticatedAsAdmin();
        $crawler = $client->request('GET', "/fr/admin/main/user/{$userId}/edit");

        self::assertResponseIsSuccessful();

        $username = 'Foo bar '.uniqid();
        $form = $crawler->selectButton('Enregistrer & fermer')->form([
            'chill_mainbundle_user[username]' => $username,
        ]);

        $client->submit($form);
        $client->followRedirect();
        // Check the element contains an attribute with value equals "Foo"
        $this->assertResponseIsSuccessful();
    }

    /**
     * @dataProvider dataGenerateUserId
     */
    public function testUpdatePassword(int $userId, mixed $username)
    {
        $client = $this->getClientAuthenticatedAsAdmin();
        $crawler = $client->request('GET', "/fr/admin/user/{$userId}/edit_password");
        $newPassword = '1234_Password!';

        $form = $crawler->selectButton('Changer le mot de passe')->form([
            'chill_mainbundle_user_password[new_password][first]' => $newPassword,
            'chill_mainbundle_user_password[new_password][second]' => $newPassword,
        ]);

        $client->submit($form);

        $this->assertTrue(
            $client->getResponse()->isRedirect(),
            'the response is a redirection'
        );

        $this->isPasswordValid($username, $newPassword);
    }

    public static function dataGenerateUserId()
    {
        self::bootKernel();
        $em = self::getContainer()->get(EntityManagerInterface::class);
        /** @var UserPasswordHasherInterface::class $passwordHasher */
        $passwordHasher = self::getContainer()->get(UserPasswordHasherInterface::class);

        $user = new User();
        $user->setUsername('Test_user '.uniqid());
        $user->setPassword($passwordHasher->hashPassword($user, 'password'));

        $em->persist($user);
        $em->flush();

        self::ensureKernelShutdown();

        yield [$user->getId(), $user->getUsername()];
    }

    protected function isPasswordValid($username, $password)
    {
        /** @var \Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher $passwordEncoder */
        $passwordEncoder = self::getContainer()
            ->get(UserPasswordHasherInterface::class);

        $user = self::getContainer()->get(UserRepositoryInterface::class)
            ->findOneBy(['username' => $username]);

        $this->assertTrue($passwordEncoder->isPasswordValid($user, $password));
    }
}
