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

use Chill\MainBundle\CRUD\Controller\ApiController;
use Chill\MainBundle\Entity\PostalCode;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Pagination\PaginatorInterface;
use Chill\MainBundle\Repository\AddressReferenceRepository;
use Chill\MainBundle\Serializer\Model\Collection;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;

final class AddressReferenceAPIController extends ApiController
{
    public function __construct(private readonly AddressReferenceRepository $addressReferenceRepository, private readonly PaginatorFactory $paginatorFactory) {}

    #[Route(path: '/api/1.0/main/address-reference/by-postal-code/{id}/search.json')]
    public function search(PostalCode $postalCode, Request $request): JsonResponse
    {
        $this->denyAccessUnlessGranted('ROLE_USER');

        if (!$request->query->has('q')) {
            throw new BadRequestHttpException('You must supply a "q" parameter');
        }

        $pattern = $request->query->get('q');

        if ('' === \trim((string) $pattern)) {
            throw new BadRequestHttpException('the search pattern is empty');
        }

        $nb = $this->addressReferenceRepository->countByPostalCodePattern($postalCode, $pattern);
        $paginator = $this->paginatorFactory->create($nb);
        $addresses = $this->addressReferenceRepository->findByPostalCodePattern(
            $postalCode,
            $pattern,
            false,
            $paginator->getCurrentPageFirstItemNumber(),
            $paginator->getItemsPerPage()
        );

        return $this->json(
            new Collection($addresses, $paginator),
            Response::HTTP_OK,
            [],
            [AbstractNormalizer::GROUPS => ['read']]
        );
    }

    protected function customizeQuery(string $action, Request $request, $qb): void
    {
        if ($request->query->has('postal_code')) {
            $qb->where($qb->expr()->isNull('e.deletedAt'))
                ->andWhere('e.postcode = :postal_code')
                ->setParameter('postal_code', $request->query->get('postal_code'));
        }
    }

    protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator, $_format)
    {
        $query->addOrderBy('e.street', 'ASC');
        $query->addOrderBy('e.streetNumber', 'ASC');

        return $query;
    }
}
