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

use Chill\CalendarBundle\Entity\Calendar;
use Chill\CalendarBundle\Entity\CalendarDoc;
use Chill\CalendarBundle\Form\CalendarDocCreateType;
use Chill\CalendarBundle\Form\CalendarDocEditType;
use Chill\CalendarBundle\Security\Voter\CalendarDocVoter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security;

final readonly class CalendarDocController
{
    public function __construct(
        private \Twig\Environment $engine,
        private EntityManagerInterface $entityManager,
        private FormFactoryInterface $formFactory,
        private Security $security,
        private UrlGeneratorInterface $urlGenerator,
    ) {}

    #[Route(path: '/{_locale}/calendar/calendar-doc/{id}/new', name: 'chill_calendar_calendardoc_new')]
    public function create(Calendar $calendar, Request $request): Response
    {
        $calendarDoc = (new CalendarDoc($calendar, null))->setCalendar($calendar);

        if (!$this->security->isGranted(CalendarDocVoter::EDIT, $calendarDoc)) {
            throw new AccessDeniedHttpException();
        }

        // set variables
        switch ($calendarDoc->getCalendar()->getContext()) {
            case 'accompanying_period':
                $view = '@ChillCalendar/CalendarDoc/new_accompanying_period.html.twig';
                $returnRoute = 'chill_calendar_calendar_list_by_period';
                $returnParams = ['id' => $calendarDoc->getCalendar()->getAccompanyingPeriod()->getId()];

                break;

            case 'person':
                $view = '@ChillCalendar/CalendarDoc/new_person.html.twig';
                $returnRoute = 'chill_calendar_calendar_list_by_person';
                $returnParams = ['id' => $calendarDoc->getCalendar()->getPerson()->getId()];

                break;

            default:
                throw new \UnexpectedValueException('Unsupported context');
        }

        $calendarDocDTO = new CalendarDoc\CalendarDocCreateDTO();
        $form = $this->formFactory->create(CalendarDocCreateType::class, $calendarDocDTO);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $calendarDoc->createFromDTO($calendarDocDTO);

            $this->entityManager->persist($calendarDoc);
            $this->entityManager->flush();

            if ($request->query->has('returnPath')) {
                return new RedirectResponse($request->query->get('returnPath'));
            }

            return new RedirectResponse(
                $this->urlGenerator->generate($returnRoute, $returnParams)
            );
        }

        return new Response(
            $this->engine->render(
                $view,
                ['calendar_doc' => $calendarDoc, 'form' => $form->createView()]
            )
        );
    }

    #[Route(path: '/{_locale}/calendar/calendar-doc/{id}/delete', name: 'chill_calendar_calendardoc_delete')]
    public function delete(CalendarDoc $calendarDoc, Request $request): Response
    {
        if (!$this->security->isGranted(CalendarDocVoter::EDIT, $calendarDoc)) {
            throw new AccessDeniedHttpException('Not authorized to delete document');
        }

        switch ($calendarDoc->getCalendar()->getContext()) {
            case 'accompanying_period':
                $view = '@ChillCalendar/CalendarDoc/delete_accompanying_period.html.twig';
                $returnRoute = 'chill_calendar_calendar_list_by_period';
                $returnParams = ['id' => $calendarDoc->getCalendar()->getAccompanyingPeriod()->getId()];

                break;

            case 'person':
                $view = '@ChillCalendar/CalendarDoc/delete_person.html.twig';
                $returnRoute = 'chill_calendar_calendar_list_by_person';
                $returnParams = ['id' => $calendarDoc->getCalendar()->getPerson()->getId()];

                break;

            default:
                throw new \LogicException(sprintf("This context '%s' is not supported", $calendarDoc->getCalendar()->getContext()));
        }

        $form = $this->formFactory->createBuilder()
            ->add('submit', SubmitType::class, [
                'label' => 'Delete',
            ])
            ->getForm();

        $form->handleRequest($request);

        if ($form->isSubmitted()) {
            $this->entityManager->remove($calendarDoc);
            $this->entityManager->flush();

            if ($request->query->has('returnPath')) {
                return new RedirectResponse($request->query->get('returnPath'));
            }

            return new RedirectResponse(
                $this->urlGenerator->generate($returnRoute, $returnParams)
            );
        }

        return new Response(
            $this->engine->render(
                $view,
                [
                    'calendar_doc' => $calendarDoc,
                    'form' => $form->createView(),
                ]
            )
        );
    }

    #[Route(path: '/{_locale}/calendar/calendar-doc/{id}/edit', name: 'chill_calendar_calendardoc_edit')]
    public function edit(CalendarDoc $calendarDoc, Request $request): Response
    {
        if (!$this->security->isGranted(CalendarDocVoter::EDIT, $calendarDoc)) {
            throw new AccessDeniedHttpException();
        }

        // set variables
        switch ($calendarDoc->getCalendar()->getContext()) {
            case 'accompanying_period':
                $view = '@ChillCalendar/CalendarDoc/edit_accompanying_period.html.twig';
                $returnRoute = 'chill_calendar_calendar_list_by_period';
                $returnParams = ['id' => $calendarDoc->getCalendar()->getAccompanyingPeriod()->getId()];

                break;

            case 'person':
                $view = '@ChillCalendar/CalendarDoc/edit_person.html.twig';
                $returnRoute = 'chill_calendar_calendar_list_by_person';
                $returnParams = ['id' => $calendarDoc->getCalendar()->getPerson()->getId()];

                break;

            default:
                throw new \UnexpectedValueException('Unsupported context');
        }

        $calendarDocEditDTO = new CalendarDoc\CalendarDocEditDTO($calendarDoc);
        $form = $this->formFactory->create(CalendarDocEditType::class, $calendarDocEditDTO);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $calendarDoc->editFromDTO($calendarDocEditDTO);

            $this->entityManager->flush();

            if ($request->query->has('returnPath')) {
                return new RedirectResponse($request->query->get('returnPath'));
            }

            return new RedirectResponse(
                $this->urlGenerator->generate($returnRoute, $returnParams)
            );
        }

        return new Response(
            $this->engine->render(
                $view,
                ['calendar_doc' => $calendarDoc, 'form' => $form->createView()]
            )
        );
    }
}
