<?php

declare(strict_types=1);

namespace App\Tests\Functional\Module\ProjectManagement;

use App\Module\Core\Domain\Entity\Permission;
use App\Module\Core\Domain\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

/**
 * Vérifie que les ressources métier sont bien gardées par les permissions RBAC
 * granulaires et non plus par le simple ROLE_USER.
 *
 * @internal
 */
final class ProjectAccessControlTest extends WebTestCase
{
    public function testAuthenticatedUserWithoutPermissionIsForbidden(): void
    {
        $client = self::createClient();
        $em     = self::getContainer()->get(EntityManagerInterface::class);

        $user = $this->createPlainUser($em, 'proj-noperm-'.uniqid());
        $em->flush();
        $client->loginUser($user);

        $client->request('GET', '/api/projects');

        self::assertResponseStatusCodeSame(403);
    }

    public function testUserWithViewPermissionCanListProjects(): void
    {
        $client = self::createClient();
        $em     = self::getContainer()->get(EntityManagerInterface::class);

        $permission = $em->getRepository(Permission::class)->findOneBy(['code' => 'project-management.projects.view']);
        self::assertInstanceOf(Permission::class, $permission, 'Le catalogue de permissions doit contenir project-management.projects.view (lancer app:sync-permissions).');

        $user = $this->createPlainUser($em, 'proj-view-'.uniqid());
        $user->addDirectPermission($permission);
        $em->flush();
        $client->loginUser($user);

        $client->request('GET', '/api/projects');

        self::assertResponseIsSuccessful();
    }

    public function testViewPermissionDoesNotGrantWrite(): void
    {
        $client = self::createClient();
        $em     = self::getContainer()->get(EntityManagerInterface::class);

        $permission = $em->getRepository(Permission::class)->findOneBy(['code' => 'project-management.projects.view']);
        self::assertInstanceOf(Permission::class, $permission);

        $user = $this->createPlainUser($em, 'proj-noWrite-'.uniqid());
        $user->addDirectPermission($permission);
        $em->flush();
        $client->loginUser($user);

        $client->request('POST', '/api/projects', server: [
            'CONTENT_TYPE' => 'application/ld+json',
        ], content: json_encode(['name' => 'Should be denied']));

        self::assertResponseStatusCodeSame(403);
    }

    private function createPlainUser(EntityManagerInterface $em, string $username): User
    {
        $user = new User();
        $user->setUsername($username);
        $user->setPassword('x');
        $user->setRoles(['ROLE_USER']);
        $em->persist($user);

        return $user;
    }
}
