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

use Chill\MainBundle\Entity\Scope;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

/**
 * @internal
 *
 * @coversNothing
 */
final class AccompanyingPeriodDocGenNormalizerTest extends KernelTestCase
{
    private NormalizerInterface $normalizer;

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

    public function testNormalizationNullOrNotNullHaveSameKeys()
    {
        $period = new AccompanyingPeriod();
        $notNullData = $this->normalizer->normalize($period, 'docgen', ['docgen:expects' => AccompanyingPeriod::class]);
        $nullData = $this->normalizer->normalize(null, 'docgen', ['docgen:expects' => AccompanyingPeriod::class]);

        $this->assertEqualsCanonicalizing(
            array_keys($notNullData),
            array_keys($nullData),
            'test that the data returned by null value and an accompanying period have the same keys'
        );
    }

    public function testNormalize()
    {
        $period = new AccompanyingPeriod();
        $period->setConfidential(true);
        $period->setEmergency(true);
        $period->setOrigin((new AccompanyingPeriod\Origin())->setLabel(['fr' => 'origin']));
        $period->setClosingMotive((new AccompanyingPeriod\ClosingMotive())->setName(['closing']));
        $period->addScope((new Scope())->setName(['fr' => 'scope1']));
        $period->addScope((new Scope())->setName(['fr' => 'scope2']));
        $period->addSocialIssue((new SocialIssue())->setTitle(['fr' => 'issue1']));
        $period->addSocialIssue((new SocialIssue())->setTitle(['fr' => 'issue2']));
        $period->addPerson(new Person());
        $period->addPerson(new Person());
        $data = $this->normalizer->normalize($period, 'docgen', ['docgen:expects' => AccompanyingPeriod::class]);

        $expected = [
            'id' => null,
            'type' => 'accompanying_period',
            'isNull' => false,
            'closingDate' => '@ignored',
            'closingMotive' => '@ignored',
            'confidential' => true,
            'confidentialText' => 'confidentiel',
            'comments' => '@ignored',
            'pinnedComment' => '@ignored',
            'createdAt' => '@ignored',
            'createdBy' => '@ignored',
            'emergency' => true,
            'emergencyText' => 'Urgent',
            'openingDate' => '@ignored',
            'originText' => 'origin',
            'origin' => '@ignored',
            'requestorAnonymous' => false,
            'resources' => [],
            'socialIssues' => '@ignored',
            'intensity' => 'ponctuel',
            'step' => 'Brouillon',
            'closingMotiveText' => 'closing',
            'socialIssuesText' => 'issue1, issue2',
            'scopes' => '@ignored',
            'scopesText' => 'scope1, scope2',
            'ref' => '@ignored',
            'participations' => '@ignored',
            'currentParticipations' => '@ignored',
            'isClosed' => false,
            'hasRef' => false,
            'hasRequestor' => false,
            'requestorKind' => 'none',
            'hasRequestorPerson' => false,
            'hasRequestorThirdParty' => false,
            'requestorPerson' => '@ignored',
            'requestorThirdParty' => '@ignored',
            'administrativeLocation' => '@ignored',
            'hasAdministrativeLocation' => false,
            'hasLocation' => false,
            'hasLocationPerson' => false,
            'location' => '@ignored',
            'locationPerson' => '@ignored',
            'works' => [],
        ];

        $this->assertIsArray($data);
        $this->assertEqualsCanonicalizing(array_keys($expected), array_keys($data));

        foreach ($expected as $key => $item) {
            if ('@ignored' === $item) {
                continue;
            }

            $this->assertEquals($item, $data[$key], "test key {$key}");
        }

        $this->assertCount(2, $data['participations']);
    }

    public function testNormalizeNull()
    {
        $data = $this->normalizer->normalize(null, 'docgen', ['docgen:expects' => AccompanyingPeriod::class]);

        $this->assertIsArray($data);
    }

    public function testNormalizeParticipations()
    {
        $period = new AccompanyingPeriod();
        $period->addPerson($person = new Person());
        $person->setFirstName('test');

        $data = $this->normalizer->normalize($period, 'docgen', ['docgen:expects' => AccompanyingPeriod::class]);

        $this->assertIsArray($data);
        $this->assertArrayHasKey('participations', $data);
        $this->assertCount(1, $data['participations']);

        $this->assertArrayHasKey('currentParticipations', $data);
        $this->assertCount(1, $data['currentParticipations']);
    }
}
