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

use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Form\ActivityType;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;

/**
 * @internal
 *
 * @coversNothing
 */
final class ActivityTypeTest extends KernelTestCase
{
    /**
     * @var \Chill\MainBundle\Entity\Center
     */
    protected $center;

    /**
     * @var \Symfony\Component\Form\FormBuilderInterface
     */
    protected $formBuilder;

    /**
     * @var \Symfony\Component\Security\Core\User\UserInterface
     */
    protected $user;

    protected function setUp(): void
    {
        self::bootKernel();

        $this->container = self::$kernel->getContainer();

        $prophet = new \Prophecy\Prophet();

        $this->formBuilder = $this->container
            ->get('form.factory')
            ->createBuilder(FormType::class, null, [
                'csrf_protection' => false,
                'csrf_field_name' => '_token',
            ]);

        $request = new \Symfony\Component\HttpFoundation\Request();
        $request->setLocale('fr');

        self::$kernel->getContainer()
            ->get('request_stack')
            ->push($request);

        $this->user = $this->container->get('doctrine.orm.entity_manager')
            ->getRepository(\Chill\MainBundle\Entity\User::class)
            ->findOneBy(['username' => 'center a_social']);
        $this->center = $this->container->get('doctrine.orm.entity_manager')
            ->getRepository(\Chill\MainBundle\Entity\Center::class)
            ->findOneBy(['name' => 'Center A']);
        $token = $prophet->prophesize();
        $token->willExtend(AbstractToken::class);
        $token->getUser()->willReturn($this->user);
        $this->container->get('security.token_storage')
            ->setToken($token->reveal());
    }

    public function testForm()
    {
        $form = $this->formBuilder
            ->add('activity', ActivityType::class, [
                'center' => $this->center,
                'role' => 'CHILL_ACTIVITY_CREATE',
            ])
            ->getForm();

        $form->submit([]);

        $this->assertTrue($form->isSynchronized());
        $this->assertTrue($form->isValid());
        $this->assertInstanceOf(Activity::class, $form->getData()['activity']);
    }

    public function testFormSubmitting()
    {
        $form = $this->formBuilder
            ->add('activity', ActivityType::class, [
                'center' => $this->center,
                'role' => 'CHILL_ACTIVITY_CREATE',
            ])
            ->getForm();

        $form->submit(['activity' => [
            'date' => '9-3-2015',
            'durationTime' => 300,
            //  'remark' => 'blabla',
            'attendee' => true,
        ]]);

        //        var_dump($form->getErrors()->count()); var_dump($form->isValid());
        //        foreach($form->getErrors() as $e) { fwrite(STDOUT, var_dump($e->getMessage())); }
        //        var_dump($form->getErrors());

        $this->assertTrue($form->isSynchronized(), 'Test the form is synchronized');
        $this->assertTrue($form->isValid(), 'test the form is valid');
        $this->assertInstanceOf(Activity::class, $form->getData()['activity']);

        // test the activity
        /** @var Activity $activity */
        $activity = $form->getData()['activity'];

        $this->assertEquals(
            '09-03-2015',
            $activity->getDate()->format('d-m-Y'),
            'Test the date is correct'
        );
        $this->assertEquals(
            '00:05',
            $activity->getDurationTime()->format('H:i'),
            'Test the formatted hour is correct'
        );
        $this->assertEquals(true, $activity->getAttendee());
        //   $this->assertEquals('blabla', $activity->getRemark());
    }

    /**
     * Test that the form correctly build even with a durationTime which is not in
     * the listed in the possible durationTime.
     */
    public function testFormWithActivityHavingDifferentTime()
    {
        $activity = new Activity();
        $activity->setDurationTime(\DateTime::createFromFormat('U', 60));

        $builder = $this->container
            ->get('form.factory')
            ->createBuilder(FormType::class, ['activity' => $activity], [
                'csrf_protection' => false,
                'csrf_field_name' => '_token',
            ]);

        $form = $builder
            ->add('activity', ActivityType::class, [
                'center' => $this->center,
                'role' => 'CHILL_ACTIVITY_CREATE',
            ])
            ->getForm();

        $form->submit(['activity' => [
            'date' => '9-3-2015',
            'durationTime' => 60,
            //  'remark' => 'blabla',
            'attendee' => true,
        ]]);

        $this->assertTrue($form->isSynchronized());
        $this->assertTrue($form->isValid());

        // test the activity
        /** @var Activity $activity */
        $activity = $form->getData()['activity'];

        $this->assertEquals(
            '00:01',
            $activity->getDurationTime()->format('H:i'),
            'Test the formatted hour is correct'
        );

        // test the view : we want to be sure that the entry with 60 seconds exists
        $view = $form->createView();

        $this->assertTrue(isset($view['activity']['durationTime']));

        // map all the values in an array
        $values = array_map(
            static fn ($choice) => $choice->value,
            $view['activity']['durationTime']->vars['choices']
        );

        $this->assertContains(60, $values);
    }
}
