<?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 Form\Type;

use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Form\Type\ScopePickerType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\Persistence\ManagerRegistry;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\PreloadedExtension;
use Symfony\Component\Form\Test\TypeTestCase;
use Symfony\Component\Security\Core\Security;

/**
 * @internal
 *
 * @coversNothing
 */
final class ScopePickerTypeTest extends TypeTestCase
{
    use ProphecyTrait;

    public function testBuildOneScopeIsSuccessful()
    {
        $form = $this->factory->create(ScopePickerType::class, null, [
            'role' => 'ONE_SCOPE',
            'center' => [],
        ]);

        $view = $form->createView();

        $this->assertContains('hidden', $view['scope']->vars['block_prefixes']);
    }

    public function testBuildThreeScopesIsSuccessful()
    {
        $form = $this->factory->create(ScopePickerType::class, null, [
            'role' => 'THREE_SCOPE',
            'center' => [],
        ]);

        $view = $form->createView();

        $this->assertContains('entity', $view['scope']->vars['block_prefixes']);
    }

    public function testBuildTwoScopesIsSuccessful()
    {
        $form = $this->factory->create(ScopePickerType::class, null, [
            'role' => 'TWO_SCOPE',
            'center' => [],
        ]);

        $view = $form->createView();

        $this->assertContains('entity', $view['scope']->vars['block_prefixes']);
    }

    protected function getExtensions()
    {
        $user = new User();
        $role1Scope = 'ONE_SCOPE';
        $role2Scope = 'TWO_SCOPE';
        $role3Scope = 'THREE_SCOPE';
        $scopeA = (new Scope())->setName(['fr' => 'scope a']);
        $scopeB = (new Scope())->setName(['fr' => 'scope b']);
        $scopeC = (new Scope())->setName(['fr' => 'scope b'])->setActive(false);

        $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class);
        $authorizationHelper->getReachableScopes($user, $role1Scope, Argument::any())
            ->willReturn([$scopeA]);
        $authorizationHelper->getReachableScopes($user, $role2Scope, Argument::any())
            ->willReturn([$scopeA, $scopeB]);
        $authorizationHelper->getReachableScopes($user, $role3Scope, Argument::any())
            ->willReturn([$scopeA, $scopeB, $scopeC]);

        $security = $this->prophesize(Security::class);
        $security->getUser()->willReturn($user);

        $translatableStringHelper = $this->prophesize(TranslatableStringHelperInterface::class);
        $translatableStringHelper->localize(Argument::type('array'))->will(
            static fn ($args) => $args[0]['fr']
        );

        $centerResolverManager = $this->prophesize(CenterResolverManagerInterface::class);

        $type = new ScopePickerType(
            $translatableStringHelper->reveal(),
            $authorizationHelper->reveal(),
            $security->reveal(),
            $centerResolverManager->reveal()
        );

        // add the mocks for creating EntityType
        $em = $this->prophesize(EntityManagerInterface::class);
        $em->getClassMetadata(Scope::class)->will(function (array $args) {
            $classMetadata = new ClassMetadataBuilder(
                new ClassMetadataInfo(Scope::class)
            );

            return $classMetadata->getClassMetadata();
        });
        $em->contains(Argument::type(Scope::class))->willReturn(true);
        $em->initializeObject(Argument::type(Scope::class))->will(static fn ($o) => $o);
        $emRevealed = $em->reveal();
        $managerRegistry = $this->prophesize(ManagerRegistry::class);
        $managerRegistry->getManager(Argument::any())->willReturn($emRevealed);
        $managerRegistry->getManagerForClass(Scope::class)->willReturn($emRevealed);

        $entityType = $this->prophesize(EntityType::class);
        $entityType->getParent()->willReturn(ChoiceType::class);

        return [
            new PreloadedExtension([$type], []),
            new DoctrineOrmExtension($managerRegistry->reveal()),
        ];
    }
}
