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

use Chill\MainBundle\Entity\Gender;
use Chill\MainBundle\Entity\GenderEnum;
use Chill\MainBundle\Entity\GenderIconEnum;
use Chill\MainBundle\Repository\UserRepositoryInterface;
use Chill\MainBundle\Test\PrepareClientTrait;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

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

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

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

    /**
     * @dataProvider generateAccompanyingPeriodWork
     *
     * @throws \JsonException
     */
    public function testWhenEditionAccompanyingPeriodWorkWithCurrentVersionNoConflictOccurs(AccompanyingPeriod\AccompanyingPeriodWork $work, int $personId): void
    {
        $client = $this->getClientAuthenticated();

        $currentVersion = $work->getVersion();

        $client->request(
            'PUT',
            "/api/1.0/person/accompanying-course/work/{$work->getid()}.json?entity_version={$currentVersion}",
            content: json_encode([
                'type' => 'accompanying_period_work',
                'id' => $work->getId(),
                'startDate' => [
                    'datetime' => '2023-12-15T00:00:00+01:00',
                ],
                'endDate' => null,
                'note' => 'This is a note',
                'accompanyingPeriodWorkEvaluations' => [],
                'goals' => [],
                'handlingThirdParty' => null,
                'persons' => [[
                    'type' => 'person',
                    'id' => $personId,
                ],
                ],
                'privateComment' => '',
                'refferers' => [],
                'results' => [],
                'thirdParties' => [],
            ], JSON_THROW_ON_ERROR)
        );

        self::assertResponseIsSuccessful();
        $w = json_decode($client->getResponse()->getContent(), true, 512, JSON_THROW_ON_ERROR);

        self::assertEquals($work->getVersion() + 1, $w['version']);
    }

    /**
     * @dataProvider generateAccompanyingPeriodWork
     */
    public function testWhenEditingAccompanyingPeriodWorkWithPreviousVersionAnHttpConflictResponseOccurs(AccompanyingPeriod\AccompanyingPeriodWork $work, int $personId): void
    {
        $client = $this->getClientAuthenticated();

        $previous = $work->getVersion() - 1;

        $client->request(
            'PUT',
            "/api/1.0/person/accompanying-course/work/{$work->getid()}.json?entity_version={$previous}",
            content: json_encode([
                'type' => 'accompanying_period_work',
                'id' => $work->getId(),
                'startDate' => [
                    'datetime' => '2023-12-15T00:00:00+01:00',
                ],
                'endDate' => null,
                'note' => 'This is a note',
                'accompanyingPeriodWorkEvaluations' => [],
                'goals' => [],
                'handlingThirdParty' => null,
                'persons' => [[
                    'type' => 'person',
                    'id' => $personId,
                ],
                ],
                'privateComment' => '',
                'refferers' => [],
                'results' => [],
                'thirdParties' => [],
            ], JSON_THROW_ON_ERROR)
        );

        self::assertResponseStatusCodeSame(409);
    }

    public static function generateAccompanyingPeriodWork(): iterable
    {
        self::bootKernel();
        $em = self::getContainer()->get(EntityManagerInterface::class);
        $userRepository = self::getContainer()->get(UserRepositoryInterface::class);
        $user = $userRepository->findOneByUsernameOrEmail('center a_social');

        $period = new AccompanyingPeriod();
        $em->persist($period);

        $gender = new Gender();
        $gender->setGenderTranslation(GenderEnum::MALE);
        $gender->setLabel(['fr' => 'homme']);
        $gender->setIcon(GenderIconEnum::MALE);
        $em->persist($gender);

        $period->addPerson(($p = new Person())->setFirstName('test')->setLastName('test')
            ->setBirthdate(new \DateTime('1980-01-01'))->setGender($gender));
        $em->persist($p);
        $issue = (new SocialIssue())->setTitle(['fr' => 'test']);
        $em->persist($issue);
        $action = (new SocialAction())->setIssue($issue);
        $em->persist($action);

        $work = new AccompanyingPeriod\AccompanyingPeriodWork();
        $work
            ->setAccompanyingPeriod($period)
            ->setStartDate(new \DateTimeImmutable())
            ->addPerson($p)
            ->setSocialAction($action)
            ->setCreatedBy($user)
            ->setUpdatedBy($user)
        ;
        $em->persist($work);

        $em->flush();

        self::ensureKernelShutdown();

        yield [$work, $p->getId()];
    }
}
