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

use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Privacy\PrivacyEvent;
use Chill\PersonBundle\Repository\PersonRepository;
use Doctrine\ORM\EntityManagerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Validator\Validator\ValidatorInterface;

final class PersonController extends AbstractController
{
    public function __construct(
        private readonly EventDispatcherInterface $eventDispatcher,
        private readonly PersonRepository $personRepository,
        private readonly ConfigPersonAltNamesHelper $configPersonAltNameHelper,
        private readonly ValidatorInterface $validator,
        private readonly EntityManagerInterface $em,
    ) {}

    public function getCFGroup()
    {
        $cFGroup = null;

        $cFDefaultGroup = $this->em->getRepository(\Chill\CustomFieldsBundle\Entity\CustomFieldsDefaultGroup::class)
            ->findOneByEntity(Person::class);

        if ($cFDefaultGroup) {
            $cFGroup = $cFDefaultGroup->getCustomFieldsGroup();
        }

        return $cFGroup;
    }

    /**
     * @ParamConverter("person", options={"id": "person_id"})
     */
    #[Route(path: '/{_locale}/person/household/{person_id}/history', name: 'chill_person_household_person_history', methods: ['GET', 'POST'])]
    public function householdHistoryByPerson(Request $request, Person $person): Response
    {
        $this->denyAccessUnlessGranted(
            'CHILL_PERSON_SEE',
            $person,
            'You are not allowed to see this person.'
        );

        $event = new PrivacyEvent($person);
        $this->eventDispatcher->dispatch($event, PrivacyEvent::PERSON_PRIVACY_EVENT);

        return $this->render(
            '@ChillPerson/Person/household_history.html.twig',
            [
                'person' => $person,
            ]
        );
    }

    #[Route(path: '/{_locale}/person/{person_id}/general', name: 'chill_person_view')]
    public function viewAction(int $person_id)
    {
        $person = $this->_getPerson($person_id);

        if (null === $person) {
            throw $this->createNotFoundException("Person with id {$person_id} not".' found on this server');
        }

        $this->denyAccessUnlessGranted(
            'CHILL_PERSON_SEE',
            $person,
            'You are not allowed to see this person.'
        );

        $event = new PrivacyEvent($person);
        $this->eventDispatcher->dispatch($event, PrivacyEvent::PERSON_PRIVACY_EVENT);

        return $this->render(
            '@ChillPerson/Person/view.html.twig',
            [
                'person' => $person,
                'cFGroup' => $this->getCFGroup(),
                'alt_names' => $this->configPersonAltNameHelper->getChoices(),
            ]
        );
    }

    /**
     * easy getting a person by his id.
     *
     * @return Person
     */
    private function _getPerson(int $id)
    {
        return $this->personRepository->find($id);
    }

    /**
     * @return \Symfony\Component\Validator\ConstraintViolationListInterface
     */
    private function _validatePersonAndAccompanyingPeriod(Person $person)
    {
        $errors = $this->validator
            ->validate($person, null, ['creation']);

        // validate accompanying periods
        $periods = $person->getAccompanyingPeriods();

        foreach ($periods as $period) {
            $period_errors = $this->validator
                ->validate($period);

            // group errors :
            foreach ($period_errors as $error) {
                $errors->add($error);
            }
        }

        return $errors;
    }
}
