<?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\Serializer\Normalizer;

use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Household\Position;
use Chill\PersonBundle\Entity\Person;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

/**
 * @internal
 *
 * @coversNothing
 */
final class HouseholdNormalizerTest extends KernelTestCase
{
    private EntityManagerInterface $entityManager;

    private ?NormalizerInterface $normalizer;

    private readonly array $toDelete;

    protected function setUp(): void
    {
        self::bootKernel();
        $this->normalizer = self::getContainer()->get(NormalizerInterface::class);
        $this->entityManager = self::getContainer()->get(EntityManagerInterface::class);
    }

    public function testNormalizationRecursive(): void
    {
        $person = new Person();
        $person->setFirstName('ok')->setLastName('ok');
        $this->entityManager->persist($person);
        $member = new HouseholdMember();
        $household = new Household();
        $position = (new Position())
            ->setShareHousehold(true)
            ->setAllowHolder(true);

        $member->setPerson($person)
            ->setStartDate(new \DateTimeImmutable('1 year ago'))
            ->setEndDate(new \DateTimeImmutable('1 month ago'))
            ->setPosition($position);

        $household->addMember($member);

        $normalized = $this->normalizer->normalize(
            $household,
            'json',
            ['groups' => ['read']]
        );

        $this->assertIsArray($normalized);
        $this->assertArrayHasKey('type', $normalized);
        $this->assertEquals('household', $normalized['type']);
    }

    /**
     * When a household have old members (members which are not "current"),
     * the indexes of the household must be reset to numerical and contiguous
     * indexes. This ensure that it will be mapped as a list, not as an associative
     * array.
     */
    public function testHouseholdDocGenNormalizationWithOldMembers(): void
    {
        $previousPerson = new Person();
        $previousPerson->setFirstName('ok')->setLastName('ok');
        $this->entityManager->persist($previousPerson);
        $member = new HouseholdMember();
        $household = new Household();
        $position = (new Position())
            ->setShareHousehold(true)
            ->setAllowHolder(true);

        $member->setPerson($previousPerson)
            ->setStartDate(new \DateTimeImmutable('1 year ago'))
            ->setEndDate(new \DateTimeImmutable('1 month ago'))
            ->setPosition($position);

        $household->addMember($member);

        $currentPerson1 = new Person();
        $currentPerson1->setFirstName('p1')->setLastName('p1');
        $this->entityManager->persist($currentPerson1);
        $member = new HouseholdMember();
        $member->setPerson($currentPerson1)
            ->setStartDate(new \DateTimeImmutable('1 year ago'))
            ->setPosition($position);
        $household->addMember($member);

        $normalized = $this->normalizer->normalize(
            $household,
            'docgen',
            [
                AbstractNormalizer::GROUPS => ['docgen:read'],
                'docgen:expects' => Household::class,
                'docgen:person:with-household' => false,
                'docgen:person:with-relations' => false,
                'docgen:person:with-budget' => false,
            ]
        );

        self::assertIsArray($normalized);
        self::assertArrayHasKey(0, $normalized['currentMembers']);
    }
}
