<?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 Service\DocGenerator;

use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Service\DocGenerator\PersonContextInterface;
use Chill\PersonBundle\Service\DocGenerator\PersonContextWithThirdParty;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

/**
 * @internal
 *
 * @coversNothing
 */
final class PersonContextWithThirdPartyTest extends KernelTestCase
{
    use ProphecyTrait;

    public function testAdminFormReverseTransform()
    {
        $personContext = $this->buildPersonContextWithThirdParty();

        $actual = $personContext->adminFormReverseTransform(['label' => 'bloup']);

        $this->assertArrayHasKey('category', $actual);
        $this->assertArrayHasKey('label', $actual);
        $this->assertEquals('bloup', $actual['label']);
    }

    public function testAdminFormTransform()
    {
        $personContext = $this->buildPersonContextWithThirdParty();

        $actual = $personContext->adminFormTransform(['label' => 'bloup']);

        $this->assertArrayHasKey('from_person', $actual);
        $this->assertArrayHasKey('label', $actual);
        $this->assertEquals('bloup', $actual['label']);
    }

    public function testGetData()
    {
        $personContext = $this->buildPersonContextWithThirdParty();

        $actual = $personContext->getData(
            (new DocGeneratorTemplate())->setOptions(['label' => 'bloup']),
            new Person(),
            ['thirdParty' => $tp = new ThirdParty()]
        );

        $this->assertArrayHasKey('person', $actual);
        $this->assertArrayHasKey('thirdParty', $actual);
        $this->assertEquals(spl_object_hash($tp), $actual['thirdParty']['hash']);
    }

    private function buildPersonContextWithThirdParty(): PersonContextWithThirdParty
    {
        $normalizer = $this->prophesize(NormalizerInterface::class);
        $normalizer->normalize(Argument::type(ThirdParty::class), 'docgen', Argument::type('array'))
            ->will(static fn ($args): array => ['class' => '3party', 'hash' => spl_object_hash($args[0])]);

        $personContext = $this->prophesize(PersonContextInterface::class);

        $personContext->adminFormReverseTransform(Argument::type('array'))->willReturn(
            ['category' => ['idInsideBundle' => 1, 'bundleId' => 'abc']]
        );
        $personContext->adminFormTransform(Argument::type('array'))->willReturn(
            ['from_person' => 'kept']
        );
        $personContext->getData(Argument::type(DocGeneratorTemplate::class), Argument::type(Person::class), Argument::type('array'))
            ->willReturn(['person' => 'data']);

        $thirdPartyRepository = $this->prophesize(ThirdPartyRepository::class);
        $thirdPartyRepository->find(Argument::type('int'))->willReturn(new class () extends ThirdParty {
            public function getId(): ?int
            {
                return 1;
            }
        });

        return new PersonContextWithThirdParty(
            $personContext->reveal(),
            $normalizer->reveal(),
            $thirdPartyRepository->reveal(),
        );
    }
}
