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

use Chill\DocStoreBundle\GenericDoc\ManagerInterface;
use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactory;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\SecurityBundle\Security;

final readonly class GenericDocForAccompanyingPeriodController
{
    public function __construct(
        private FilterOrderHelperFactory $filterOrderHelperFactory,
        private ManagerInterface $manager,
        private PaginatorFactory $paginator,
        private Security $security,
        private \Twig\Environment $twig,
    ) {}

    /**
     * @throws \Doctrine\DBAL\Exception
     */
    #[\Symfony\Component\Routing\Attribute\Route(path: '/{_locale}/doc-store/generic-doc/by-period/{id}/index', name: 'chill_docstore_generic-doc_by-period_index')]
    public function list(AccompanyingPeriod $accompanyingPeriod): Response
    {
        if (!$this->security->isGranted(AccompanyingCourseDocumentVoter::SEE, $accompanyingPeriod)) {
            throw new AccessDeniedHttpException('not allowed to see the documents for accompanying period');
        }

        $filterBuilder = $this->filterOrderHelperFactory
            ->create(self::class)
            ->addSearchBox()
            ->addDateRange('dateRange', 'generic_doc.filter.date-range');

        if ([] !== $places = $this->manager->placesForAccompanyingPeriod($accompanyingPeriod)) {
            $filterBuilder->addCheckbox('places', $places, [], array_map(
                static fn (string $k) => 'generic_doc.filter.keys.'.$k,
                $places
            ));
        }

        $filter = $filterBuilder
            ->build();

        ['to' => $endDate, 'from' => $startDate] = $filter->getDateRangeData('dateRange');
        $content = $filter->getQueryString();

        $nb = $this->manager->countDocForAccompanyingPeriod(
            $accompanyingPeriod,
            $startDate,
            $endDate,
            $content,
            $filter->hasCheckBox('places') ? array_values($filter->getCheckboxData('places')) : []
        );
        $paginator = $this->paginator->create($nb);

        // restrict the number of items for performance reasons
        $paginator->setItemsPerPage(20);

        $documents = $this->manager->findDocForAccompanyingPeriod(
            $accompanyingPeriod,
            $paginator->getCurrentPageFirstItemNumber(),
            $paginator->getItemsPerPage(),
            $startDate,
            $endDate,
            $content,
            $filter->hasCheckBox('places') ? array_values($filter->getCheckboxData('places')) : []
        );

        return new Response($this->twig->render(
            '@ChillDocStore/GenericDoc/accompanying_period_list.html.twig',
            [
                'accompanyingCourse' => $accompanyingPeriod,
                'pagination' => $paginator,
                'documents' => iterator_to_array($documents),
                'filter' => $filter,
            ]
        ));
    }
}
