<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\AdminBundle\Controller\Dashboard;

use Ferienpass\AdminBundle\Controller\TagsResponses;
use Ferienpass\CoreBundle\Facade\DecisionsFacade;
use Ferienpass\CoreBundle\Facade\EraseDataFacade;
use Ferienpass\CoreBundle\HttpCache\CacheTag;
use Ferienpass\CoreBundle\Repository\EditionRepository;
use Ferienpass\CoreBundle\Repository\OfferRepositoryInterface;
use Ferienpass\CoreBundle\Repository\SentMessageRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\Response;

/**
 * ESI fragment rendering the admin "next steps" todo list (editions with
 * uncommitted / waiting attendances, delivery errors, expired participants).
 * It buckets attendances by status, so the CacheInvalidationListener purges its
 * {@see CacheTag::dashboard()} tag whenever an attendance is created, removed or
 * transitions status — keeping it fresh inside the year-cached /admin page.
 */
class NextStepsController extends AbstractController
{
    use TagsResponses;

    private const int TTL = 31556926;

    public function __invoke(OfferRepositoryInterface $offers, EditionRepository $editions, EraseDataFacade $eraseData, DecisionsFacade $decisons, SentMessageRepository $sentMessageRepository, #[Autowire(param: 'app.id')] string $appId): Response
    {
        if (!$this->isGranted('ROLE_ADMIN')) {
            return new Response('', Response::HTTP_NO_CONTENT);
        }

        $response = $this->render('@FerienpassAdmin/fragment/dashboard/next_steps.html.twig', [
            'editions' => $editions,
            'editionsWithUncommitedAttendances' => $editions->findWithUncommitedAttendances(),
            'messagesWithError' => $sentMessageRepository->findWithError('30 days'),
            'upcomingOffers' => $offers->findUpcoming(),
            'editionsWithFinalizedOffers' => $editions->findWithFinalizedOffers(),
            'editionsWithWaitingAttendances' => $editions->findWithWaitingAttendances(),
            'expiredParticipants' => $eraseData->expiredParticipants(),
            'decisions' => $decisons,
        ]);

        // Tenant-global aggregate, shared across the tenant's admins — no Vary.
        $response->setPublic();
        $response->setSharedMaxAge(self::TTL);
        $this->tagResponse(CacheTag::dashboard($appId));

        return $response;
    }
}
