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

use Chill\MainBundle\Repository\Workflow\EntityWorkflowStepSignatureACLAwareRepository;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Repository\ResidentialAddressRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Knp\Menu\MenuItem;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * Add menu entrie to person menu.
 *
 * Menu entries added :
 *
 * - person details ;
 * - accompanying period (if `visible`)
 *
 * @implements LocalMenuBuilderInterface<array{person: Person}>
 */
class PersonMenuBuilder implements LocalMenuBuilderInterface
{
    /**
     * @var string 'visible' or 'hidden'
     */
    protected $showAccompanyingPeriod;

    public function __construct(
        ParameterBagInterface $parameterBag,
        private readonly Security $security,
        protected TranslatorInterface $translator,
        private readonly ResidentialAddressRepository $residentialAddressRepo,
        private readonly EntityWorkflowStepSignatureACLAwareRepository $entityWorkflowStepSignatureRepository,
    ) {
        $this->showAccompanyingPeriod = $parameterBag->get('chill_person.accompanying_period');
    }

    /**
     * @param array{person: Person} $parameters
     *
     * @return void
     */
    public function buildMenu($menuId, MenuItem $menu, array $parameters)
    {
        $menu->addChild($this->translator->trans('Person details'), [
            'route' => 'chill_person_view',
            'routeParameters' => [
                'person_id' => $parameters['person']->getId(),
            ],
        ])
            ->setExtras([
                'order' => 50,
            ]);

        $menu->addChild($this->translator->trans('Residential addresses'), [
            'route' => 'chill_person_residential_address_list',
            'routeParameters' => [
                'id' => $parameters['person']->getId(),
            ],
        ])
            ->setExtras([
                'order' => 60,
                'counter' => 0 < ($nbResidentials = $this->residentialAddressRepo->countByPerson($parameters['person'])) ?
                    $nbResidentials : null,
            ]);

        $menu->addChild($this->translator->trans('person_resources_menu'), [
            'route' => 'chill_person_resource_list',
            'routeParameters' => [
                'person_id' => $parameters['person']->getId(),
            ],
        ])
            ->setExtras([
                'order' => 70,
                'counter' => 0 < ($nbResources = $parameters['person']->countResources()) ? $nbResources : null,
            ]);

        $menu->addChild($this->translator->trans('household.person history'), [
            'route' => 'chill_person_household_person_history',
            'routeParameters' => [
                'person_id' => $parameters['person']->getId(),
            ],
        ])
            ->setExtras([
                'order' => 99999,
            ]);

        if ($this->security->isGranted(PersonVoter::DUPLICATE, $parameters['person'])) {
            $menu->addChild($this->translator->trans('Person duplicate'), [
                'route' => 'chill_person_duplicate_view',
                'routeParameters' => [
                    'person_id' => $parameters['person']->getId(),
                ],
            ])
                ->setExtras([
                    'order' => 99999,
                ]);
        }

        if (
            'visible' === $this->showAccompanyingPeriod
            && $this->security->isGranted(AccompanyingPeriodVoter::SEE, $parameters['person'])
        ) {
            $menu->addChild($this->translator->trans('Accompanying period list'), [
                'route' => 'chill_person_accompanying_period_list',
                'routeParameters' => [
                    'person_id' => $parameters['person']->getId(),
                ],
            ])
                ->setExtras([
                    'order' => 100,
                    'counter' => 0 < ($nbAccompanyingPeriod = $parameters['person']->countAccompanyingPeriodInvolved())
                        ? $nbAccompanyingPeriod : null,
                ]);
        }

        $nbSignatures = count($this->entityWorkflowStepSignatureRepository->findByPersonAndPendingState($parameters['person']));

        if ($nbSignatures > 0) {
            $menu->addChild($this->translator->trans('workflow.signature_list.menu'), [
                'route' => 'chill_person_signature_list',
                'routeParameters' => [
                    'id' => $parameters['person']->getId(),
                ],
            ])
                ->setExtras([
                    'order' => 110,
                    'counter' => $nbSignatures,
                ]);
        }
    }

    public static function getMenuIds(): array
    {
        return ['person'];
    }
}
