<?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 App\Module\ProjectManagement\Domain\Entity\Workflow;
use App\Module\ProjectManagement\Domain\Repository\WorkflowRepositoryInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

/**
 * Vérifie que la création d'un projet fonctionne avec ou sans workflow fourni :
 * - sans workflow → le workflow par défaut est assigné par le listener prePersist
 * - avec workflow → le workflow choisi est conservé.
 *
 * @internal
 */
final class ProjectCreationWorkflowTest extends WebTestCase
{
    public function testCreateProjectWithoutWorkflowAssignsDefault(): void
    {
        $client = self::createClient();
        $em     = self::getContainer()->get(EntityManagerInterface::class);

        $client->loginUser($this->createManager($em));

        $client->request('POST', '/api/projects', server: [
            'CONTENT_TYPE' => 'application/ld+json',
        ], content: json_encode([
            'code' => $this->randomCode(),
            'name' => 'Projet sans workflow',
        ]));

        self::assertResponseStatusCodeSame(201);
        $data = json_decode($client->getResponse()->getContent(), true);
        self::assertArrayHasKey('workflow', $data);
        self::assertNotNull($data['workflow'], 'Un workflow par défaut doit avoir été assigné.');
    }

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

        $workflow = self::getContainer()->get(WorkflowRepositoryInterface::class)->findDefault()
            ?? $em->getRepository(Workflow::class)->findOneBy([]);
        self::assertInstanceOf(Workflow::class, $workflow, 'Les fixtures doivent fournir au moins un workflow.');

        $client->loginUser($this->createManager($em));

        $client->request('POST', '/api/projects', server: [
            'CONTENT_TYPE' => 'application/ld+json',
        ], content: json_encode([
            'code'     => $this->randomCode(),
            'name'     => 'Projet avec workflow',
            'workflow' => '/api/workflows/'.$workflow->getId(),
        ]));

        self::assertResponseStatusCodeSame(201);
        $data = json_decode($client->getResponse()->getContent(), true);
        self::assertSame($workflow->getId(), $data['workflow']['id'] ?? null);
    }

    private function createManager(EntityManagerInterface $em): User
    {
        $permission = $em->getRepository(Permission::class)->findOneBy(['code' => 'project-management.projects.manage']);
        self::assertInstanceOf(Permission::class, $permission, 'Lancer app:sync-permissions pour project-management.projects.manage.');

        $user = new User();
        $user->setUsername('proj-create-'.uniqid());
        $user->setPassword('x');
        $user->setRoles(['ROLE_USER']);
        $user->addDirectPermission($permission);
        $em->persist($user);
        $em->flush();

        return $user;
    }

    private function randomCode(): string
    {
        $letters = '';
        for ($i = 0; $i < 6; ++$i) {
            $letters .= chr(random_int(65, 90));
        }

        return $letters;
    }
}
