<?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\ReportBundle\Tests\Controller;

use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
use Chill\PersonBundle\Entity\Person;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

/**
 * This class is much well writtend than ReportControllerTest class, and will
 * replace ReportControllerTest in the future.
 *
 * @internal
 *
 * @coversNothing
 */
final class ReportControllerNextTest extends WebTestCase
{
    /**
     * @var CustomFieldsGroup
     */
    protected $group;

    /**
     * @var Person
     */
    protected $person;

    protected function setUp(): void
    {
        self::bootKernel();
        // get person from fixture
        $em = self::$kernel->getContainer()
            ->get('doctrine.orm.entity_manager');

        $this->person = $em
            ->getRepository(Person::class)
            ->findOneBy(
                [
                    'lastName' => 'Charline',
                    'firstName' => 'Depardieu',
                ]
            );

        if (null === $this->person) {
            throw new \RuntimeException('The expected person is not present in the database. Did you run `php app/console doctrine:fixture:load` before launching tests ? '."(expecting person is 'Charline Depardieu'");
        }

        // get custom fields group from fixture
        $customFieldsGroups = self::$kernel->getContainer()
            ->get('doctrine.orm.entity_manager')
            ->getRepository(CustomFieldsGroup::class)
            ->findBy(['entity' => \Chill\ReportBundle\Entity\Report::class]);
        // filter customFieldsGroup to get only "situation de logement"
        $filteredCustomFieldsGroupHouse = array_filter(
            $customFieldsGroups,
            static fn (CustomFieldsGroup $group) => \in_array('Situation de logement', $group->getName(), true)
        );
        $this->group = $filteredCustomFieldsGroupHouse[0];
    }

    public function testUngrantedUserIsDeniedAccessOnListReports()
    {
        $client = $this->getAuthenticatedClient('center b_social');
        $client->request('GET', sprintf(
            '/fr/person/%d/report/list',
            $this->person->getId()
        ));

        $this->assertEquals(
            403,
            $client->getResponse()->getStatusCode(),
            'assert that user for center b has a 403 status code when listing'
                .'reports on person from center a'
        );
    }

    public function testUngrantedUserIsDeniedAccessOnReport()
    {
        $client = $this->getAuthenticatedClient('center b_social');
        $reports = self::$kernel->getContainer()->get('doctrine.orm.entity_manager')
            ->getRepository('ChillReportBundle:Report')
            ->findBy(['person' => $this->person]);
        $report = $reports[0];

        $client->request('GET', sprintf(
            '/fr/person/%d/report/%d/view',
            $this->person->getId(),
            $report->getId()
        ));

        $this->assertEquals(
            403,
            $client->getResponse()->getStatusCode(),
            'assert that user for center b has a 403 status code when '
                .'trying to watch a report from person from center a'
        );
    }

    public function testUngrantedUserIsDeniedReportCreate()
    {
        $clientCenterA = $this->getAuthenticatedClient('center a_social');

        $form = $this->getReportForm($this->person, $this->group, $clientCenterA);

        $clientCenterB = $this->getAuthenticatedClient('center b_social');
        $clientCenterB->submit($form);

        $this->assertEquals(
            403,
            $clientCenterB->getResponse()->getStatusCode(),
            'assert that user is denied on trying to show a form "new" for'
                .' a person on another center'
        );
    }

    public function testUngrantedUserIsDeniedReportNew()
    {
        $client = $this->getAuthenticatedClient('center b_social');

        $client->request('GET', sprintf(
            'fr/person/%d/report/cfgroup/%d/new',
            $this->person->getId(),
            $this->group->getId()
        ));

        $this->assertEquals(
            403,
            $client->getResponse()->getStatusCode(),
            'assert that user is denied on trying to show a form "new" for'
                .' a person on another center'
        );
    }

    public function testValidCreate()
    {
        $client = $this->getAuthenticatedClient();
        $form = $this->getReportForm($this->person, $this->group, $client);

        $form->get('chill_reportbundle_report[date]')->setValue(
            (new \DateTime())->format('d-m-Y')
        );

        $client->submit($form);

        $this->assertTrue(
            $client->getResponse()->isRedirect(),
            "The next page is a redirection to the new report's view page"
        );
    }

    protected function getAuthenticatedClient($username = 'center a_social')
    {
        return self::createClient([], [
            'PHP_AUTH_USER' => $username,
            'PHP_AUTH_PW' => 'password',
        ]);
    }

    /**
     * @return \Symfony\Component\DomCrawler\Form
     */
    protected function getReportForm(Person $person, CustomFieldsGroup $group, \Symfony\Component\BrowserKit\AbstractBrowser $client)
    {
        $url = sprintf(
            'fr/person/%d/report/cfgroup/%d/new',
            $person->getId(),
            $group->getId()
        );
        $crawler = $client->request('GET', $url);

        return $crawler->selectButton('Ajouter le rapport')
            ->form();
    }
}
