<?php

declare(strict_types=1);

namespace App\Tests\Functional\Module\Reporting;

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

/**
 * @internal
 */
final class ReportingApiTest extends WebTestCase
{
    public function testGetCollectionRequiresAuthentication(): void
    {
        $client = self::createClient();

        $client->request('GET', '/api/reports/time-per-project?from=2026-01-01&to=2027-01-01');

        self::assertResponseStatusCodeSame(401);
    }

    public function testAdminCanListTimePerProject(): void
    {
        $client = self::createClient();
        $this->loginUser($client, 'admin');

        $client->request('GET', '/api/reports/time-per-project?from=2026-01-01&to=2027-01-01');

        self::assertResponseIsSuccessful();
        $data = json_decode($client->getResponse()->getContent(), true);
        self::assertArrayHasKey('member', $data);

        // Le rapport est non pagine : la structure hydra expose tout de meme un
        // tableau `member`. Si des projets ont du temps logge, chaque membre
        // porte au minimum projectId et hours.
        foreach ($data['member'] as $row) {
            self::assertArrayHasKey('projectId', $row);
            self::assertArrayHasKey('hours', $row);
            self::assertIsInt($row['projectId']);
        }
    }

    public function testValidProjectIdFilterIsAccepted(): void
    {
        $client = self::createClient();
        $this->loginUser($client, 'admin');

        // projectId arrive en chaine ("1") : la validation doit l'accepter (200),
        // garde-fou contre une regression de type-juggling sur le filtre entier.
        $client->request('GET', '/api/reports/time-per-project?from=2026-01-01&to=2027-01-01&projectId=1');

        self::assertResponseIsSuccessful();
    }

    public function testInvalidProjectIdFilterIsRejected(): void
    {
        $client = self::createClient();
        $this->loginUser($client, 'admin');

        $client->request('GET', '/api/reports/time-per-project?projectId=abc');

        self::assertResponseStatusCodeSame(400);
    }

    public function testInvalidDateFilterIsRejected(): void
    {
        $client = self::createClient();
        $this->loginUser($client, 'admin');

        $client->request('GET', '/api/reports/time-per-project?from=not-a-date');

        self::assertResponseStatusCodeSame(400);
    }

    public function testUserWithoutPermissionIsForbidden(): void
    {
        $client = self::createClient();
        $this->loginUser($client, 'alice');

        $client->request('GET', '/api/reports/time-per-project?from=2026-01-01&to=2027-01-01');

        self::assertResponseStatusCodeSame(403);
    }

    private function loginUser(KernelBrowser $client, string $username): void
    {
        $em   = self::getContainer()->get(EntityManagerInterface::class);
        $user = $em->getRepository(User::class)->findOneBy(['username' => $username]);
        self::assertInstanceOf(User::class, $user);
        $client->loginUser($user);
    }
}
