<?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\Person;
use Chill\PersonBundle\Repository\PersonRepository;
use Chill\PersonBundle\Serializer\Normalizer\PersonJsonReadDenormalizer;
use PHPUnit\Framework\TestCase;

/**
 * @internal
 *
 * @covers \Chill\PersonBundle\Serializer\Normalizer\PersonJsonReadDenormalizer
 */
final class PersonJsonReadDenormalizerTest extends TestCase
{
    public function testSupportsDenormalizationReturnsTrueForValidData(): void
    {
        $repository = $this->getMockBuilder(PersonRepository::class)
            ->disableOriginalConstructor()
            ->getMock();

        $denormalizer = new PersonJsonReadDenormalizer($repository);

        $data = [
            'type' => 'person',
            'id' => 123,
        ];

        self::assertTrue($denormalizer->supportsDenormalization($data, Person::class));
    }

    public function testSupportsDenormalizationReturnsFalseForInvalidData(): void
    {
        $repository = $this->getMockBuilder(PersonRepository::class)
            ->disableOriginalConstructor()
            ->getMock();

        $denormalizer = new PersonJsonReadDenormalizer($repository);

        // not an array
        self::assertFalse($denormalizer->supportsDenormalization('not-an-array', Person::class));

        // missing type
        self::assertFalse($denormalizer->supportsDenormalization(['id' => 1], Person::class));

        // wrong type value
        self::assertFalse($denormalizer->supportsDenormalization(['type' => 'not-person', 'id' => 1], Person::class));

        // missing id
        self::assertFalse($denormalizer->supportsDenormalization(['type' => 'person'], Person::class));

        // wrong target class
        self::assertFalse($denormalizer->supportsDenormalization(['type' => 'person', 'id' => 1], \stdClass::class));
    }

    public function testDenormalizeReturnsPersonFromRepository(): void
    {
        $person = new Person();

        $repository = $this->getMockBuilder(PersonRepository::class)
            ->disableOriginalConstructor()
            ->onlyMethods(['find'])
            ->getMock();

        $repository->expects(self::once())
            ->method('find')
            ->with(123)
            ->willReturn($person);

        $denormalizer = new PersonJsonReadDenormalizer($repository);

        $result = $denormalizer->denormalize(['id' => 123], Person::class);

        self::assertSame($person, $result);
    }
}
