<?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\AccompanyingPeriod;

use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Test\PrepareClientTrait;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

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

    private KernelBrowser $client;

    /**
     * Setup before each test method (see phpunit doc).
     */
    protected function setUp(): void
    {
        $this->client = $this->getClientAuthenticated();
    }

    protected function tearDown(): void
    {
        self::ensureKernelShutdown();
    }

    /**
     * @doesNotPerformAssertions
     */
    public function testConfidentialInvalid()
    {
        $this->markTestSkipped('test not written fully');

        // Disabling this dataprovider to avoid having errors while running the test.
        return yield from [];
        $maxGenerated = 3;
        $maxResults = $maxGenerated * 8;

        self::bootKernel();
        $em = self::$kernel->getContainer()->get('doctrine.orm.entity_manager');

        $qb = $em->createQueryBuilder();
        $personIds = $qb
            ->select('p.id')
            ->distinct(true)
            ->from(Person::class, 'p')
            ->join('p.accompanyingPeriodParticipations', 'participation')
            ->join('participation.accompanyingPeriod', 'ap')
            ->andWhere(
                $qb->expr()->eq('ap.step', ':step')
            )
            ->andWhere(
                $qb->expr()->eq('ap.confidential', ':confidential')
            )
            ->setParameter('step', AccompanyingPeriod::STEP_CONFIRMED)
            ->setParameter('confidential', true)
            ->setMaxResults($maxResults)
            ->getQuery()
            ->getScalarResult();

        // create a random order
        shuffle($personIds);

        $nbGenerated = 0;

        while ($nbGenerated < $maxGenerated) {
            $id = array_pop($personIds)['id'];

            $person = $em->getRepository(Person::class)->find($id);
            $periods = $person->getAccompanyingPeriods();

            yield [array_pop($personIds)['id'], $periods[array_rand($periods)]->getId()];

            ++$nbGenerated;
        }
    }

    public function testConfidentialValid(): never
    {
        $this->markTestIncomplete(
            'Marked as incomplete because of a problem in the dataprovider, at line 81.'
        );

        $period = self::getContainer()->get(AccompanyingPeriodRepository::class)
            ->find($periodId);
        $em = self::$kernel->getContainer()->get('doctrine.orm.entity_manager');

        $violations = self::$validator->validate($period, null, ['confirmed']);

        $initialUser = $period->getUser();

        $user = new stdClass();
        $user->id = 0;
        $user->type = 'user';

        $this->client->request(
            Request::METHOD_PATCH,
            sprintf('/api/1.0/person/accompanying-course/%d.json', $periodId),
            [], // parameters
            [], // files
            [], // server parameters
            json_encode(['type' => 'accompanying_period', 'user' => $user], JSON_THROW_ON_ERROR)
        );
        $response = $this->client->getResponse();

        // if ($isConfidential === true && $step === 'CONFIRMED') {
        $this->assertEquals(422, $response->getStatusCode());
        // }

        $this->assertEquals(200, $response->getStatusCode());
        $period = $em->getRepository(AccompanyingPeriod::class)
            ->find($periodId);
        $this->assertEquals($user, $period->getUser());

        // assign initial user again
        $period->setUser($initialUser);
        $em->flush();
    }
}
