<?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\PersonBundle\Tests\Controller;

use Chill\MainBundle\Test\PrepareClientTrait;
use Chill\PersonBundle\Entity\Person;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\HttpFoundation\Request;

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

    /**
     * @dataProvider dataGetPersonFromCenterA
     */
    public function testPersonAddressSuggestion(int $personId): void
    {
        $client = $this->getClientAuthenticated();

        $client->request(Request::METHOD_GET, "/api/1.0/person/address/suggest/by-person/{$personId}.json");

        $this->assertResponseIsSuccessful();
    }

    /**
     * @dataProvider dataGetPersonFromCenterB
     */
    public function testPersonAddressSuggestionUnauthorized(mixed $personId): void
    {
        $client = $this->getClientAuthenticated();

        $client->request(Request::METHOD_GET, "/api/1.0/person/address/suggest/by-person/{$personId}.json");
        $response = $client->getResponse();

        $this->assertEquals(403, $response->getStatusCode());
    }

    /**
     * @dataProvider dataGetPersonFromCenterA
     */
    public function testPersonGet(int $personId): void
    {
        $client = $this->getClientAuthenticated();

        $client->request(Request::METHOD_GET, "/api/1.0/person/person/{$personId}.json");
        $response = $client->getResponse();

        $this->assertResponseIsSuccessful();

        $data = \json_decode($client->getResponse()->getContent(), true, 512, JSON_THROW_ON_ERROR);

        $this->assertArrayHasKey('type', $data);
        $this->assertArrayHasKey('id', $data);
        $this->assertEquals('person', $data['type']);
        $this->assertEquals($personId, $data['id']);
    }

    public static function dataGetPersonFromCenterA(): \Iterator
    {
        self::bootKernel();
        $em = self::getContainer()->get(EntityManagerInterface::class);
        $personIds = $em->createQuery(sprintf(
            'SELECT p.id FROM %s p JOIN p.centerCurrent pc JOIN pc.center c WHERE c.name = :center',
            Person::class
        ))
            ->setParameter('center', 'Center A')
            ->setMaxResults(100)
            ->getScalarResult();

        \shuffle($personIds);

        yield \array_pop($personIds);

        yield \array_pop($personIds);

        yield \array_pop($personIds);

        yield \array_pop($personIds);
    }

    /**
     * @dataProvider dataGetPersonFromCenterB
     */
    public function testPersonGetUnauthorized(mixed $personId): void
    {
        $client = $this->getClientAuthenticated();

        $client->request(Request::METHOD_GET, "/api/1.0/person/person/{$personId}.json");
        $response = $client->getResponse();

        $this->assertEquals(403, $response->getStatusCode());
    }

    public static function dataGetPersonFromCenterB(): \Iterator
    {
        self::bootKernel();
        $em = self::getContainer()->get(EntityManagerInterface::class);
        $personIds = $em->createQuery(
            sprintf('SELECT p.id FROM %s p JOIN p.centerCurrent pc JOIN pc.center c WHERE c.name = :center', Person::class)
        )
            ->setParameter('center', 'Center B')
            ->setMaxResults(100)
            ->getScalarResult();

        \shuffle($personIds);

        yield \array_pop($personIds);

        yield \array_pop($personIds);
    }
}
