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

use Contao\CoreBundle\Exception\PageNotFoundException;
use Doctrine\ORM\EntityManagerInterface;
use Ferienpass\AdminBundle\Breadcrumb\Breadcrumb;
use Ferienpass\AdminBundle\Controller\TagsResponses;
use Ferienpass\AdminBundle\Form\EditEditionType;
use Ferienpass\AdminBundle\Form\FormScreenFactory;
use Ferienpass\AdminBundle\Form\HandleFormTrait;
use Ferienpass\CoreBundle\Entity\Edition;
use Ferienpass\CoreBundle\Entity\EditionLog;
use Ferienpass\CoreBundle\Entity\User;
use Ferienpass\CoreBundle\HttpCache\CacheTag;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;

#[IsGranted('ROLE_ADMIN')]
#[Route('/saisons')]
final class EditionsEditController extends AbstractController
{
    use HandleFormTrait;
    use TagsResponses;

    public function __construct(
        private readonly ServiceLocator $sectionComponents,
    ) {
    }

    #[Route('/neu/{section?default}', name: 'admin_editions_create', priority: 2)]
    #[Route('/{alias}/bearbeiten/{section?default}', name: 'admin_editions_edit')]
    public function edit(?Edition $edition, string $section, Request $request, EntityManagerInterface $entityManager, EventDispatcherInterface $dispatcher, Breadcrumb $breadcrumb, FormScreenFactory $forms): Response
    {
        $isNew = null === $edition;
        $edition ??= new Edition();

        // Section components (e.g. `tasks` Gantt + phase cards) own their section
        // entirely and short-circuit the form-based render path. They're only
        // available on a persisted edition because they touch related entities.
        $hasComponent = null !== $edition->getId() && $this->sectionComponents->has($section);
        if ($hasComponent) {
            $formScreen = $forms->screen(EditEditionType::class, $edition)
                ->withExtraSections(array_keys($this->sectionComponents->getProvidedServices()));

            if (!\in_array($section, $formScreen->sections(), true)) {
                throw new PageNotFoundException('Section not found');
            }

            $this->tagResponse(CacheTag::edition($edition));

            return $this->render('@FerienpassAdmin/page/edition/edit.html.twig', [
                'item' => $edition,
                'section' => $section,
                'formScreen' => $formScreen,
                'component_class' => $this->sectionComponents->get($section)::class,
                'breadcrumb' => $breadcrumb->generate(
                    ['editions.title', ['route' => 'admin_editions_index']],
                    [$edition->getName(), ['route' => 'admin_editions_show', 'routeParameters' => ['alias' => $edition->getAlias()]]]
                ),
            ]);
        }

        $form = $this->createForm(EditEditionType::class, $edition, $formOptions = [
            'display_section' => $section,
        ]);

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $isNew = null === $edition->getId();
            $wasArchived = $edition->isArchived();

            $this->handleSubmit($form, $dispatcher, $request);

            $entityManager->flush();

            $user = $this->getUser();
            if ($user instanceof User) {
                if ($isNew) {
                    $entityManager->persist(new EditionLog($edition, $user, 'Saison erstellt'));
                } elseif ($wasArchived !== $edition->isArchived()) {
                    $entityManager->persist(new EditionLog($edition, $user, $edition->isArchived() ? 'Saison archiviert' : 'Saison wiederhergestellt'));
                }

                $entityManager->flush();
            }

            $this->addFlash('success', 'Die Änderungen wurden erfolgreich übernommen.');

            if ($nextSection = $request->request->get('nextSection')) {
                return $this->redirectToRoute('admin_editions_edit', ['alias' => $edition->getAlias(), 'section' => $nextSection]);
            }

            if ($redirect = $request->request->get('redirect')) {
                return $this->redirectToRoute($redirect, ['alias' => $edition->getAlias()]);
            }

            return $this->redirectToRoute('admin_editions_show', ['alias' => $edition->getAlias()]);
        }

        $breadcrumbTitle = $edition->getId() ? $edition->getName().' (bearbeiten)' : 'editions.new';

        $this->tagResponse(CacheTag::edition($edition));

        return $this->render('@FerienpassAdmin/page/edition/edit.html.twig', [
            'item' => $edition,
            'form' => $form,
            'formOptions' => $formOptions,
            'formScreen' => $forms->screen(EditEditionType::class, $edition)
                ->withExtraSections(array_keys($this->sectionComponents->getProvidedServices())),
            'section' => $section,
            'breadcrumb' => $breadcrumb->generate(
                ['editions.title', ['route' => 'admin_editions_index']],
                $edition->getId() ? [$edition->getName(), ['route' => 'admin_editions_show', 'routeParameters' => ['alias' => $edition->getAlias()]]] : null
            ),
        ]);
    }
}
