<?php

/**
 * 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.
 */

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

use Chill\CalendarBundle\RemoteCalendar\Connector\RemoteCalendarConnectorInterface;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Pagination\PaginatorFactory;
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\SerializerInterface;

/**
 * Contains method to get events (Calendar) from remote calendar.
 */
class RemoteCalendarProxyController
{
    public function __construct(private readonly PaginatorFactory $paginatorFactory, private readonly RemoteCalendarConnectorInterface $remoteCalendarConnector, private readonly SerializerInterface $serializer) {}

    #[Route(path: 'api/1.0/calendar/proxy/calendar/by-user/{id}/events')]
    public function listEventForCalendar(User $user, Request $request): Response
    {
        if (!$request->query->has('dateFrom')) {
            throw new BadRequestHttpException('You must provide a dateFrom parameter');
        }

        if (false === $dateFrom = \DateTimeImmutable::createFromFormat(
            \DateTimeImmutable::ATOM,
            $request->query->get('dateFrom')
        )) {
            throw new BadRequestHttpException('dateFrom not parsable');
        }

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

        if (false === $dateTo = \DateTimeImmutable::createFromFormat(
            \DateTimeImmutable::ATOM,
            $request->query->get('dateTo')
        )) {
            throw new BadRequestHttpException('dateTo not parsable');
        }

        $total = $this->remoteCalendarConnector->countEventsForUser($user, $dateFrom, $dateTo);
        $paginator = $this->paginatorFactory->create($total);

        if (0 === $total) {
            return new JsonResponse(
                $this->serializer->serialize(new Collection([], $paginator), 'json'),
                JsonResponse::HTTP_OK,
                [],
                true
            );
        }

        $events = $this->remoteCalendarConnector->listEventsForUser(
            $user,
            $dateFrom,
            $dateTo,
            $paginator->getCurrentPageFirstItemNumber(),
            $paginator->getItemsPerPage()
        );

        // in some case, we cannot paginate: we have to fetch all the items at once. We must avoid
        // further requests by forcing the number of items returned.
        if (\count($events) > $paginator->getItemsPerPage()) {
            $paginator->setItemsPerPage(\count($events));
        }

        $collection = new Collection($events, $paginator);

        return new JsonResponse(
            $this->serializer->serialize($collection, 'json', ['groups' => ['read']]),
            JsonResponse::HTTP_OK,
            [],
            true
        );
    }
}
