<?php

namespace Ig\IgReservations\Controller;

use Internetgalerie\IgDatapoolFe\Controller\ActionController;
use Ig\IgReservations\Domain\Repository\EventRepository;
use Ig\IgReservations\Domain\Repository\EventGroupRepository;
use Ig\IgReservations\Domain\Repository\CategoryRepository;
use Ig\IgReservations\Domain\Repository\StatusRepository;
use Ig\IgReservations\Domain\Repository\AddressRepository;
use Ig\IgReservations\Domain\Repository\FeUserRepository;
use Ig\IgReservations\Domain\Repository\CalendarRepository;
use Ig\IgReservations\Domain\Repository\LocationRepository;
use Ig\IgReservations\Domain\Repository\BookingTypeRepository;
use Ig\IgReservations\Domain\Repository\ReservationTypeRepository;
use Internetgalerie\IgDatapoolFe\Property\TypeConverter\HtmlConverter;
use TYPO3\CMS\Extbase\Annotation\IgnoreValidation;
use Ig\IgReservations\Domain\Model\Timeslot;
use Ig\IgReservations\Domain\Model\Calendar;
use DateTime;
use TYPO3\CMS\Extbase\Annotation\Validate;
use Internetgalerie\IgDynval\Validation\Validator\DynamicValidator;
use GeorgRinger\NumberedPagination\NumberedPagination;
use Ig\IgReservations\Domain\Model\Event;
use Ig\IgReservations\Domain\Model\EventGroup;
use Ig\IgReservations\Domain\Repository\PurposeRepository;
use Ig\IgReservations\Service\MailService;
use Ig\IgReservations\Service\UserService;
use Internetgalerie\IgDynval\Controller\DynamicValidationActionController;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Mime\Part\AbstractPart;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Pagination\ArrayPaginator;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
use TYPO3\CMS\Extbase\Property\TypeConverter\DateTimeConverter;
use TYPO3\CMS\Fluid\View\StandaloneView;

/**
 * EventController
 */
class EventController extends ActionController
{
    use DynamicValidationActionController;

    /**
     * eventRepository
     *
     * @var EventRepository
     */
    protected $eventRepository = null;

    /**
     * eventGroupRepository
     *
     * @var EventGroupRepository
     */
    protected $eventGroupRepository = null;

    /**
     * categoryRepository
     *
     * @var CategoryRepository
     */
    protected $categoryRepository = null;

    /**
     * statusRepository
     *
     * @var StatusRepository
     */
    protected $statusRepository = null;

    /**
     * addressRepository
     *
     * @var AddressRepository
     */
    protected $addressRepository = null;

    /**
     * feUserRepository
     *
     * @var FeUserRepository
     */
    protected $feUserRepository = null;

    /**
     * calendarRepository
     *
     * @var CalendarRepository
     */
    protected $calendarRepository = null;

    /**
     * locationRepository
     *
     * @var LocationRepository
     */
    protected $locationRepository = null;

    /**
     * reservationTypeRepository
     *
     * @var ReservationTypeRepository
     */
    protected $reservationTypeRepository = null;

    /**
     * bookingTypeRepository
     *
     * @var BookingTypeRepository
     */
    protected $bookingTypeRepository = null;

    protected PurposeRepository $purposeRepository;

    /**
     * MailService
     *
     * @var MailService
     */
    protected $mailService = null;

    /**
     * @var \Ig\IgReservations\Domain\Service\UserService
     */
    protected UserService $userService;

    
    public function injectEventRepository(EventRepository $eventRepository): void
    {
        $this->eventRepository = $eventRepository;
    }

    
    public function injectEventGroupRepository(
        EventGroupRepository $eventGroupRepository
    ): void {
        $this->eventGroupRepository = $eventGroupRepository;
    }

    
    public function injectCategoryRepository(
        CategoryRepository $categoryRepository
    ): void {
        $this->categoryRepository = $categoryRepository;
    }

    
    public function injectStatusRepository(
        StatusRepository $statusRepository
    ): void {
        $this->statusRepository = $statusRepository;
    }

    
    public function injectAddressRepository(
        AddressRepository $addressRepository
    ): void {
        $this->addressRepository = $addressRepository;
    }

    
    public function injectFeUserRepository(
        FeUserRepository $feUserRepository
    ): void {
        $this->feUserRepository = $feUserRepository;
    }

    
    public function injectCalendarRepository(
        CalendarRepository $calendarRepository
    ): void {
        $this->calendarRepository = $calendarRepository;
    }

    
    public function injectLocationRepository(
        LocationRepository $locationRepository
    ): void {
        $this->locationRepository = $locationRepository;
    }

    
    public function injectBookingTypeRepository(
        BookingTypeRepository $bookingTypeRepository
    ): void {
        $this->bookingTypeRepository = $bookingTypeRepository;
    }

    
    public function injectReservationTypeRepository(
        ReservationTypeRepository $reservationTypeRepository
    ): void {
        $this->reservationTypeRepository = $reservationTypeRepository;
    }

    public function injectPurposeRepository(PurposeRepository $purposeRepository): void
    {
        $this->purposeRepository = $purposeRepository;
    }


    public function injectMailService(MailService $mailService): void
    {
        $this->mailService = $mailService;
    }

    public function injectUserService(UserService $userService): void
    {
        $this->userService = $userService;
    }

    public function initializeAction(): void
    {
        parent::initializeAction();
        if (isset($this->arguments['newEvent']) || isset($this->arguments['event'])) {
            $event = $this->arguments['newEvent'] ?? $this->arguments['event'];

            $pmc = $event
                ->getPropertyMappingConfiguration();
            $pmc->allowProperties('files');
            $pmc->forProperty('files')
                ->allowAllProperties();
            $pmc->forProperty('files.*')
                ->allowAllProperties();
            $pmc->forProperty('files.*.*')
                ->allowAllProperties();

            $event->getPropertyMappingConfiguration()
->forProperty('startDate')
->setTypeConverterOption(DateTimeConverter::class, DateTimeConverter::CONFIGURATION_DATE_FORMAT, 'Y-m-d');
            $event->getPropertyMappingConfiguration()
->forProperty('endDate')
->setTypeConverterOption(DateTimeConverter::class, DateTimeConverter::CONFIGURATION_DATE_FORMAT, 'Y-m-d');

            $event
                ->getPropertyMappingConfiguration()
                ->forProperty('description')
                ->setTypeConverter(
                    GeneralUtility::makeInstance(HtmlConverter::class)
                );
        }

        $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
        $pageRenderer->addCssFile('EXT:ig_reservations/Resources/Public/Lib/select2/select2.css');
        $pageRenderer->addCssFile('EXT:ig_reservations/Resources/Public/Css/ig_reservations.scss');
        $pageRenderer->addJsFooterFile('EXT:ig_reservations/Resources/Public/JavaScript/handlePurposes.js');
        $pageRenderer->addJsFooterFile('EXT:ig_reservations/Resources/Public/Lib/select2/select2.min.js');
        $pageRenderer->addJsFooterFile('EXT:ig_reservations/Resources/Public/Lib/select2/i18n/de.js');
        $pageRenderer->addJsFooterFile('EXT:ig_reservations/Resources/Public/JavaScript/ConfirmDelete.js');
        $pageRenderer->addJsFooterFile('EXT:ig_reservations/Resources/Public/JavaScript/ig_reservations.js');

        $this->mailService->setSettings($this->settings);
        $this->mailService->setRequest($this->request);
    }

    public function listAction(): ResponseInterface
    {
        $search = $this->request->hasArgument('search') ? $this->request->getArgument('search') : [];

        $bookingTypeUid = $search['bookingType'] ?? 0;
        $bookingType = $this->bookingTypeRepository->findByUid($bookingTypeUid);
        $locations = $this->locationRepository->findByBookingType($bookingTypeUid);

        $showWithoutReservations = (int)$this->settings['showWithoutReservations'];
        $events = $this->eventRepository->findPublic(
            $this->settings['view'] == 'list' ? 0 : 3,
            $search,
            $showWithoutReservations
        );

        $currentPage = $this->request->hasArgument('currentPage') ? (int)$this->request->getArgument('currentPage') : 1;

        $paginator = new ArrayPaginator($events, $currentPage, $this->settings['eventList']['itemsPerPage'] ?? 10);
        $pagination = new NumberedPagination($paginator, 10); // zweiter Argument: maximal Anzahl Links

        $this->view->assign('pagination', [
            'paginator' => $paginator,
            'pagination' => $pagination,
        ]);

        $this->view->assign('events', $events);
        $this->view->assign('search', $search);
        $this->view->assign('locations', $locations);
        $this->view->assign('bookingType', $bookingType);
        $this->view->assign('purposes', $this->purposeRepository->findAll());

        return $this->htmlResponse();
    }

    /**
     * action approvalList
     */
    public function approvalListAction(array $search = []): ResponseInterface
    {
        // @todo flexform with calendar select and only list events of selected  calendars
        $eventsToApprove = $this->eventRepository->findUnapproved($search);
        $this->view->assign('eventsToApprove', $eventsToApprove);
        $this->view->assign('search', $search);
        //$this->view->assign('event', $event);

        return $this->htmlResponse();
    }

    /**
     * action show
     */
    #[IgnoreValidation([])] // $event
    public function showAction(Event $event): ResponseInterface
    {
        $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
        $pageRenderer->addCssFile('EXT:ig_reservations/Resources/Public/Lib/jquery-confirm/jquery-confirm.min.css');
        $pageRenderer->addJsFooterFile('EXT:ig_reservations/Resources/Public/Lib/jquery-confirm/jquery-confirm.min.js');
        $redirect = $this->request->hasArgument('redirect') ? $this->request->getArgument('redirect') : 'callendar';
        $this->view->assign('redirect', $redirect);
        $this->view->assign('event', $event);

        return $this->htmlResponse();
    }

    /**
     * action new
     */
    public function newAction(
        string $date,
        Timeslot $timeslot,
        Calendar $calendar
    ): ResponseInterface {
        $date = new DateTime($date ?: null);
        $date->setTime(12, 0, 0);
        $protectedArea = $this->request->getPluginName() == 'Protected';

        if ($protectedArea) {
            $categories = $this->categoryRepository->findAll();
            $statusses = $this->statusRepository->findAll();
            $this->view->assign('statusses', $statusses);
        } else {
            $categories = $this->categoryRepository->findBy(['public' => 1]);
        }

        $defaultStatus = $this->statusRepository->findOneBy(['isDefault' => 1]);

        $this->view->assign('date', $date);
        $this->view->assign('timeslot', $timeslot);
        $this->view->assign('calendar', $calendar);
        $this->view->assign('categories', $categories);
        $this->view->assign('defaultStatus', $defaultStatus);
        $this->view->assign('protectedArea', $protectedArea);
        $this->view->assign('purposes', $this->purposeRepository->findAll());

        return $this->htmlResponse();
    }

    /**
     * action create
     */
    #[Validate(['validator' => DynamicValidator::class, 'param' => 'newEvent'])]
    public function createAction(Event $newEvent): ResponseInterface
    {
        $date = $newEvent->getStartDate();
        $now = new DateTime();
        $now->setTime(12, 0, 0);
        $newEvent->setCreateDate($now);

        $this->eventRepository->secureAdd($newEvent);

        $context = GeneralUtility::makeInstance(Context::class);
        $languageUid = $context->getPropertyFromAspect('language', 'id');
        $newEvent->setLanguage($languageUid);

        $protectedArea = $this->request->getPluginName() == 'Protected';

        if (!$protectedArea) {
            $teammembers = $this->feUserRepository->findTeammembers($this->settings['usergroupForTeammembers'] ?: 0);

            GeneralUtility::makeInstance(PersistenceManager::class)->persistAll();
            $mailTo = [$this->settings['coordinationPersonMail']];

            foreach ($teammembers as $teammember) {
                $email = $teammember->getEmail();
                if (GeneralUtility::validEmail($email) && !in_array($email, $mailTo)) {
                    $mailTo[] = $email;
                }
            }

            $this->sendHtmlMail(
                'Neue Buchung',
                [$this->settings['coordinationPersonMail']],
                $mailTo,
                'Event/Mail/Create/Admin',
                [
                    'event' => $newEvent,
                ]
            );
            if ($newEvent->getAddress()) {
                $this->sendHtmlMail(
                    'Ihre neue Buchung',
                    [$this->settings['coordinationPersonMail']],
                    [$newEvent->getAddress()->getEmail()],
                    'Event/Mail/Create/User',
                    [
                        'event' => $newEvent,
                    ]
                );
            }
        }

        $pluginName = $this->request->getPluginName();
        if ($pluginName == 'ProtectedMonth') {
            return $this->redirect('adminMonth', 'Calendar', null, [
                'date' => $date->format('Y-m-d'),
            ]);
        } elseif ($pluginName == 'ProtectedWeek') {
            return $this->redirect('adminWeek', 'Calendar', null, [
                'date' => $date->format('Y-m-d'),
            ]);
        } elseif ($pluginName == 'PublicMonth') {
            return $this->redirect('month', 'Calendar', null, [
                'date' => $date->format('Y-m-d'),
            ]);
        }
        return $this->redirect('week', 'Calendar', null, [
            'date' => $date->format('Y-m-d'),
        ]);
    }

    /**
     * action edit
     */
    #[IgnoreValidation([])] // $event
    public function editAction(Event $event): ResponseInterface
    {
        $canRepeat = null;
        $calendar = $event->getCalendar();
        $acl = $calendar->getAcl();
        $categories = $this->categoryRepository->findAll();
        $statusses = $this->statusRepository->findAll();
        $eventStartDate = clone $event->getStartDateTime();
        $eventEndDate = clone $event->getEndDateTime();
        $lastStartDateTime = clone $eventStartDate;
        $lastStartDateTime->modify('+1 year');

        $startTimestamp = $eventStartDate->getTimestamp();
        $endTimestamp = $eventEndDate->getTimestamp();

        $startDate = strftime('%Y-%m-%d', $startTimestamp);
        $startTime = strftime('%H:%M:%S', $startTimestamp);
        $endDate = strftime('%Y-%m-%d', $endTimestamp);
        $endTime = strftime('%H:%M:%S', $endTimestamp);

        $possibleEndTimes = $calendar->getPossibleStartAndEndTimes($startDate, $startTime, $endDate, $endTime);
        $this->view->assign('startDate', $startDate);
        $this->view->assign('startTime', $startTime);
        $this->view->assign('endDate', $endDate);
        $this->view->assign('endTime', $endTime);
        $this->view->assign('canRepeat', $canRepeat);
        $this->view->assign('eventStartDate', $eventStartDate);
        $this->view->assign('eventEndDate', $eventEndDate);
        $this->view->assign('possibleEndTimes', $possibleEndTimes);

        if ($acl && $acl->hasPermission('team')) {
            $this->view->assign('categories', $this->categoryRepository->findAll());
        } else {
            $this->view->assign('categories', $this->categoryRepository->findBy(['public' => 1]));
        }

        $this->view->assign('calendars', $this->calendarRepository->findByNotInUids([$calendar->getUid()]));
        $this->view->assign('defaultStatus', $this->statusRepository->findOneBy(['isDefault' => 1]));
        $this->view->assign('statusses', $statusses);
        $this->view->assign('event', $event);
        $this->view->assign('date', $event->getStartDate());
        $this->view->assign('timeslot', $event->getTimeslot());
        $this->view->assign('calendar', $event->getCalendar());
        $this->view->assign('calendars', $this->calendarRepository->findAll());
        $this->view->assign('categories', $categories);
        $this->view->assign('bookingTypes', $this->bookingTypeRepository->findAll());
        $this->view->assign('reservationTypes', $this->reservationTypeRepository->findAll());
        $this->view->assign('locations', $this->locationRepository->findAll());
        $this->view->assign('purposes', $this->purposeRepository->findAll());
        $this->view->assign(
            'users',
            $this->feUserRepository->findTeammembers($this->settings['usergroupForTeammembers'] ?: 0)
        );

        return $this->htmlResponse();
    }

    /**
     * action update
     */
    #[Validate(['validator' => DynamicValidator::class, 'param' => 'event'])]
    public function updateAction(Event $event, string $applyTo = ''): ResponseInterface
    {
        if ($applyTo && $applyTo != 'this' && $event->getEventGroup()) {
            $events = null;
            $newEventGroup = null;
            if ($applyTo == 'after') {
                $events = $this->eventRepository->findLaterEventsInSameGroup($event);
                $newEventGroup = GeneralUtility::makeInstance(EventGroup::class);
                $newEventGroup->setRepetition($event->getEventGroup()->getRepetition());
                $this->eventGroupRepository->add($newEventGroup);
            } else {
                $events = $this->eventRepository->findBy(['eventGroup' => $event->getEventGroup()]);
            }
            $i = 0;
            $files = [];
            foreach ($event->getFiles() as $file) {
                $files[] = $file;
            }
            foreach ($events as $ev) {
                if ($newEventGroup) {
                    $ev->setEventGroup($newEventGroup);
                    if ($i == 0) {
                        $ev->setMainEvent(true);
                    }
                    $i++;
                }
                $ev->setUpdateProperties($event);
                $filesToRemove = [];
                foreach ($ev->getFiles() as $file) {
                    $filesToRemove[] = $file;
                }
                foreach ($filesToRemove as $file) {
                    $ev->removeFile($file);
                }
                foreach ($files as $file) {
                    $fileReference = GeneralUtility::makeInstance(FileReference::class);
                    $fileReference->setOriginalResource($file->getOriginalResource());
                    $ev->addFile($fileReference);
                }
                $this->eventRepository->secureUpdate($ev);
            }
        } else {
            $event->setEventGroup(null);
            $this->eventRepository->secureUpdate($event);
        }

        return $this->redirect('show', null, null, [
            'event' => $event->getUid(),
        ]);
    }

    #[IgnoreValidation([])] // $event
    public function deleteConfirmAction(Event $event, array $source = []): ResponseInterface
    {
        $this->view->assign('event', $event);
        $this->view->assign('source', $source);

        return $this->htmlResponse();
    }

    /**
     * action delete
     */
    #[IgnoreValidation([])] // $event
    public function deleteAction(Event $event, string $applyTo = '', array $source = []): ResponseInterface
    {
        $calendar = $event->getCalendar();
        $startDate = $event->getStartDate();
        if ($applyTo && $applyTo != 'this' && $event->getEventGroup()) {
            $events = null;
            if ($applyTo == 'after') {
                $events = $this->eventRepository->findLaterEventsInSameGroup($event);
            } else {
                $events = $this->eventRepository->findBy(['eventGroup' => $event->getEventGroup()]);
                $this->eventGroupRepository->remove($event->getEventGroup());
            }
            foreach ($events as $ev) {
                $this->eventRepository->secureRemove($ev);
            }
        } else {
            //$event->setEventGroup(null);
            $this->eventRepository->secureRemove($event);
        }
        if (!empty($source)) {
            $this->uriBuilder->reset();
            if ($calendar->getPageUid() > 0) {
                $this->uriBuilder->setTargetPageUid($calendar->getPageUid());
            }
            $uri = $this->uriBuilder
                 ->uriFor(
                     $source['action'] ?? null,
                     ['search' => ['date' => $startDate->format('Y-m-d')]],
                     $source['controller'] ?? null,
                     $source['extensionName'] ?? null,
                     $source['pluginName'] ?? null
                 );
            return $this->redirectToUri($uri);
        }
        
        return $this->redirectToUri(
            $this->uriBuilder->reset()->setTargetPageUid($this->settings['unapprovedListPageUid'])->build()
        );
    }

    /**
     * action approve
     */
    #[IgnoreValidation([])] // $event
    public function approveAction(Event $event): ResponseInterface
    {
        $reservation = null;
        $user = $this->userService->getUser();
        $calendar = $event->getCalendar();

        if ($this->settings['notAvailableStatus']) {
            $notAvailableStatus = $this->statusRepository->findByUid($this->settings['notAvailableStatus']);
            $event->setStatus($notAvailableStatus);
        }

        //$event->setTeammember($user);

        // Set the locale if the language is not the default language

        // TODO: Dieses Mail darf wohl nicht immer versendet werden
        $acl = $calendar->getAcl();
        $this->eventRepository->secureUpdate($event);

        $this->mailService->sendMailAfterConfirmationOwner($calendar, $event, $reservation);
        /*
        if($event->getOwner() && $calendar->hasMailToSend('after-confirmation-owner')) {
            if(GeneralUtility::validEmail($event->getOwner()->getEmail())) {
                $mailTo = $event->getOwner()->getEmail();
                $email = GeneralUtility::makeInstance(FluidEmail::class)
                    ->subject(LocalizationUtility::translate('mail.subject.after_confirmation_owner', 'IgReservations'))
                    ->from($this->settings['coordinationPersonMailFrom'])
                    ->to(...[$mailTo])
                    ->setTemplate('IgReservations/Event/Update/Owner')
                    ->format('html')
                    ->assign('event', $event)
                    ->assign('status', $event->getStatus());
                if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
                    $request = $GLOBALS['TYPO3_REQUEST'];
                    $request->setLocale($reservation->getLanguageConfig()->getLocale());
                    $email->setRequest($request);
                }
                GeneralUtility::makeInstance(Mailer::class)->send($email);
            }
        }
        */
        $this->mailService->sendMailAfterConfirmationTeam($calendar, $event, $reservation);

        /*
        if($event->getTeammembers() && $calendar->hasMailToSend('after-confirmation-team')) {
            foreach($event->getTeammembers() as $teammember) {
                $mailTo = [];
                if(GeneralUtility::validEmail($teammember->getEmail())) {
                    $mailTo[] = $teammember->getEmail();
                }
            }
            $email = GeneralUtility::makeInstance(FluidEmail::class)
                ->subject(LocalizationUtility::translate('mail.subject.after_confirmation_team', 'IgReservations'))
                ->from($this->settings['coordinationPersonMailFrom'])
                ->to(...$mailTo)
                ->setTemplate('IgReservations/Event/Update/Team')
                ->format('html')
                ->assign('event', $event)
                ->assign('status', $event->getStatus());
            if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
                $request = $GLOBALS['TYPO3_REQUEST'];
                $request->setLocale($reservation->getLanguageConfig()->getLocale());
                $email->setRequest($request);
            }
            GeneralUtility::makeInstance(Mailer::class)->send($email);
        }
        */
        if ($this->mailService->sendMailAfterConfirmationUser($calendar, $event, $reservation)) {
            $event->setConfirmationSent(true);
            $this->eventRepository->secureUpdate($event);
        }
        /*
            if($calendar->hasMailToSend('after-confirmation-user')) {
            if(!$event->getConfirmationSent() && $event->getOwner() && $event->getReservations()) {

                foreach($event->getReservations() as $reservation) {
                    if(GeneralUtility::validEmail($reservation->getEmail())) {
                        $mailTo = $reservation->getEmail();

                        if ($reservation->getLanguage() > 0) {
                            setlocale(LC_ALL, $reservation->getLanguageConfig()->getLocale());
                        }

                        $email = GeneralUtility::makeInstance(FluidEmail::class)
                            ->subject(LocalizationUtility::translate('mail.subject.after_confirmation_user', 'IgReservations'))
                            ->from($this->settings['coordinationPersonMailFrom'])
                            ->to(...[$mailTo])
                            ->setTemplate('IgReservations/Event/Update/User')
                            ->format('html')
                            ->assign('event', $event)
                            ->assign('reservation', $reservation)
                            ->assign('settings', $this->settings);
                        if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
                            $request = $GLOBALS['TYPO3_REQUEST'];
                            $request->setLocale($reservation->getLanguageConfig()->getLocale());
                            $email->setRequest($request);
                        }
                        GeneralUtility::makeInstance(Mailer::class)->send($email);
                    }
                }
                $event->setConfirmationSent(true);
                $this->eventRepository->secureUpdate($event);
            }
        }
        */

        return $this->redirect('show', null, null, [
            'event' => $event->getUid(),
        ]);
    }

    /**
     * action approve
     */
    #[IgnoreValidation([])] // $event
    public function unapproveAction(Event $event): ResponseInterface
    {
        $user = $this->userService->getUser();
        $calendar = $event->getCalendar();
        $acl = $calendar->getAcl();

        if (($acl && $acl->getIsAdmin()) || !$event->getOwner() || ($event->getOwner()->getUid() == $user->getUid())) {
            $defaultStatus = $this->statusRepository->findOneBy(['isDefault' => 1]);
            $event->setStatus($defaultStatus);
            //$event->setOwner(null);
            $this->eventRepository->secureUpdate($event);
            $this->mailService->sendMailAfterUnapproveEventUser($event);

            /*$this->sendHtmlMail(
        'Zuweisung Teammitglied entfernt',
        [$this->settings['coordinationPersonMail']],
        [$this->settings['coordinationPersonMail']],
        'Event/Mail/Unapprove/Admin',
        ['event' => $event]
        );
        // TODO: Noch nicht klar, ob das kommt
        if ($event->getAddress()) {
        $this->sendHtmlMail(
        'Die Bestätigung Ihrer Buchung wurde aufgehoben',
        [$this->settings['coordinationPersonMail']],
        [$event->getAddress()->getEmail()],
        'Event/Mail/Unapprove/User',
        ['event' => $event]
        );
        }*/
        }

        return $this->redirect('show', 'Event', 'IgReservations', [
            'event' => $event->getUid(),
        ]);
    }

    /**
     * action assign
     */
    #[IgnoreValidation([])] // $event
    public function assignUserAction(Event $event): ResponseInterface
    {
        if ($this->userService->isAdminLoggedIn()) {
            $users = $this->feUserRepository->findTeammembers($this->settings['usergroupForTeammembers'] ?: 0);

            $this->view->assign('event', $event);
            $this->view->assign('users', $users);
            return $this->htmlResponse();
        }
        return $this->redirect('show', null, null, [
            'event' => $event->getUid(),
        ]);
    }

    /**
     * action update
     */
    #[IgnoreValidation([])] // $event
    public function updateTeammemberAction(Event $event): ResponseInterface
    {
        $reservation = null;
        $calendar = $event->getCalendar();

        if (!$event->getOwner()) {
            $defaultStatus = $this->statusRepository->findOneBy(['isDefault' => 1]);
            $event->setStatus($defaultStatus);
        }

        // TODO: Dieses Mail darf wohl nicht immer versendet werden

        $acl = $calendar->getAcl();

        $this->eventRepository->secureUpdate($event);

        $this->mailService->sendMailAfterConfirmationCoordinationperson($calendar, $event, $reservation);
        /*
        if($event->getOwner() && $calendar->hasMailToSend('after-confirmation-coordinationperson')) {
            if(GeneralUtility::validEmail($this->settings['coordinationPersonMailTo'])) {
                $mailTo = $this->settings['coordinationPersonMailTo'];
                $email = GeneralUtility::makeInstance(FluidEmail::class)
                    ->subject(LocalizationUtility::translate('mail.subject.after_confirmation_coordinationperson', 'IgReservations'))
                    ->from($this->settings['coordinationPersonMailFrom'])
                    ->to(...[$mailTo])
                    ->setTemplate('IgReservations/Event/Update/CoordinationPerson')
                    ->format('html')
                    ->assign('event', $event)
                    ->assign('status', $event->getStatus());
                if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
                    $request = $GLOBALS['TYPO3_REQUEST'];
                    $request->setLocale($reservation->getLanguageConfig()->getLocale());
                    $email->setRequest($request);
                }
                GeneralUtility::makeInstance(Mailer::class)->send($email);
            }
        }
        */
        $this->mailService->sendMailAfterConfirmationOwner($calendar, $event, $reservation);
        /*
        if($event->getOwner() && $calendar->hasMailToSend('after-confirmation-owner')) {
            if(GeneralUtility::validEmail($event->getOwner()->getEmail())) {
                $mailTo = $event->getOwner()->getEmail();
                $email = GeneralUtility::makeInstance(FluidEmail::class)
                    ->subject(LocalizationUtility::translate('mail.subject.after_confirmation_owner', 'IgReservations'))
                    ->from($this->settings['coordinationPersonMailFrom'])
                    ->to(...[$mailTo])
                    ->setTemplate('IgReservations/Event/Update/Owner')
                    ->format('html')
                    ->assign('event', $event)
                    ->assign('status', $event->getStatus());
                if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
                    $request = $GLOBALS['TYPO3_REQUEST'];
                    $request->setLocale($reservation->getLanguageConfig()->getLocale());
                    $email->setRequest($request);
                }
                GeneralUtility::makeInstance(Mailer::class)->send($email);
            }
        }
        */
        $this->mailService->sendMailAfterConfirmationTeam($calendar, $event, $reservation);
        /*
        if($event->getTeammembers() && $calendar->hasMailToSend('after-confirmation-team')) {
            foreach($event->getTeammembers() as $teammember) {
                $mailTo = [];
                if(GeneralUtility::validEmail($teammember->getEmail())) {
                    $mailTo[] = $teammember->getEmail();
                }
            }
            $email = GeneralUtility::makeInstance(FluidEmail::class)
                ->subject(LocalizationUtility::translate('mail.subject.after_confirmation_team', 'IgReservations'))
                ->from($this->settings['coordinationPersonMailFrom'])
                ->to(...$mailTo)
                ->setTemplate('IgReservations/Event/Update/Team')
                ->format('html')
                ->assign('event', $event)
                ->assign('status', $event->getStatus());
            if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
                $request = $GLOBALS['TYPO3_REQUEST'];
                $request->setLocale($reservation->getLanguageConfig()->getLocale());
                $email->setRequest($request);
            }
            GeneralUtility::makeInstance(Mailer::class)->send($email);
        }
        */
        if ($this->mailService->sendMailAfterConfirmationUser($calendar, $event, $reservation)) {
            $event->setConfirmationSent(true);
            $this->eventRepository->secureUpdate($event);
        }
        /*
        if($calendar->hasMailToSend('after-confirmation-user')) {
            if (!$event->getConfirmationSent() && $event->getOwner() && $event->getReservations()) {

                foreach($event->getReservations() as $reservation) {
                    if(GeneralUtility::validEmail($reservation->getEmail())) {
                        $mailTo = $reservation->getEmail();

                        if ($reservation->getLanguage() > 0) {
                            setlocale(LC_ALL, $reservation->getLanguageConfig()->getLocale());
                        }


                        $this->eventRepository->secureUpdate($event);
                        $email = GeneralUtility::makeInstance(FluidEmail::class)
                            ->subject(LocalizationUtility::translate('mail.subject.after_confirmation_user', 'IgReservations'))
                            ->from($this->settings['coordinationPersonMailFrom'])
                            ->to(...[$mailTo])
                            ->setTemplate('IgReservations/Event/Update/User')
                            ->format('html')
                            ->assign('event', $event)
                            ->assign('reservation', $reservation)
                            ->assign('settings', $this->settings)
                            ->assign('status', $event->getStatus());
                        if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
                            $request = $GLOBALS['TYPO3_REQUEST'];
                            $request->setLocale($reservation->getLanguageConfig()->getLocale());
                            $email->setRequest($request);
                        }
                        GeneralUtility::makeInstance(Mailer::class)->send($email);
                    }
                }
                $event->setConfirmationSent(true);

                $this->eventRepository->secureUpdate($event);
            }
        }
        */
        return $this->redirect('show', null, null, [
            'event' => $event->getUid(),
        ]);
    }


    /**
     * action confirm
     *
     * @param Event $event
     * @param string $linkHash
     */
    public function confirmAction($event, $linkHash = ''): ResponseInterface
    {
        $acl = $event->getCalendar()
->getAcl();
        if ($acl && $acl->hasPermission('team') || ($linkHash != '' && $this->checkLinkHash($event, $linkHash))) {
            if ($this->settings['notAvailableStatus']) {
                $notAvailableStatus = $this->statusRepository->findByUid($this->settings['notAvailableStatus']);
                $event->setStatus($notAvailableStatus);
                $this->eventRepository->secureUpdate($event);
            }
            $calendar = $event->getCalendar();
            if ($calendar->hasMailToSend('after-confirmation-user')) {
                if (!$event->getConfirmationSent() && $event->getReservations()) {
                    foreach ($event->getReservations() as $reservation) {
                        $this->mailService->sendMailAfterConfirmationUser($calendar, $event, $reservation);
                    }
                    $event->setConfirmationSent(true);

                    $this->eventRepository->secureUpdate($event);
                }
            }
            if ($acl->hasPermission('team')) {
                return $this->redirect('show', 'Event', 'IgReservations', [
                    'event' => $event->getUid(),
                ]);
            }
            return $this->redirect('show', 'Calendar', 'IgReservations', [
                'search' => [
                    'date' => $event->getStartDate()->format('Y-m-d'),
                ],
            ]);
        }
        return $this->redirectToUri(
            $this->uriBuilder->reset()->setTargetPageUid($event->getCalendar()->getPageUid())->build()
        );
    }

    public function checkLinkHash($event, $linkHash): bool
    {
        return $event->getLinkHash() == $linkHash;
    }

    public function alarmAdminAction(): ResponseInterface
    {
        $events = $this->eventRepository->findForAlarmAdmin();

        if ((is_countable($events) ? count($events) : 0) > 0) {
            $this->sendHtmlMail(
                'Unbestätigte Buchungen',
                [$this->settings['coordinationPersonMail']],
                [$this->settings['coordinationPersonMail']],
                'Event/Mail/Alarm/Admin',
                [
                    'events' => $events,
                ]
            );
        }

        return $this->redirectToUri($this->uriBuilder->reset()->setTargetPageUid(20)->build());
    }

    /**
     * cut an event to move it
     */
    public function cutAction(Event $event): ResponseInterface
    {
        $date = $event->getStartDateTime();
        $date->setTime(12, 0, 0);

        setcookie('eventClipboard', (string) $event->getUid(), [
            'expires' => time() + 300,
        ]);

        return $this->redirect('show', 'Calendar', null, [
            'search' => [
                'date' => $date->format('Y-m-d'),
            ],
        ]);
    }

    /**
     * insert an event that was cut out
     */
    public function insertAction(
        Event $event,
        string $date,
        Timeslot $timeslot
    ): ResponseInterface {
        $date = new DateTime($date);
        $date->setTime(12, 0, 0);

        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
            'tx_igebestattungen_domain_model_events'
        );
        $calendar = $event->getCalendar();

        $res = $queryBuilder->select('uid')
            ->from('tx_igreservations_domain_model_event')
            ->where($queryBuilder->expr()->and($queryBuilder->expr()
->eq('timeslot', $timeslot->getUid()), $queryBuilder->expr()
->eq('calendar', $calendar->getUid()), $queryBuilder->expr()
->eq('start_date', $queryBuilder->createNamedParameter($date->format('Y-m-d')))))
            ->executeQuery()
            ->fetchAssociative();

        $oldDate = $event->getStartDate();

        if (!$res) {
            $event->setTimeslot($timeslot);
            $event->setStartDate($date);
            $event->setCalendar($calendar);
            $this->eventRepository->update($event);
            setcookie('eventClipboard', '', [
                'expires' => time() - 3600,
            ]);
        } else {
            $this->addFlashMessage(
                'Beim Verschieben des Events ist ein Fehler aufgetreten. Bitte wählen Sie eine andere Zeit / ein anderes Datum.'
            );
        }

        return $this->redirect('show', 'Calendar', null, [
            'search' => [
                'date' => $date->format('Y-m-d'),
            ],
        ]);
    }

    /**
     * uncut an event to stop moving it
     */
    public function uncutAction(Event $event): ResponseInterface
    {
        $date = $event->getStartDateTime();
        $date->setTime(12, 0, 0);
        setcookie('eventClipboard', '', [
            'expires' => time() - 3600,
        ]);

        return $this->redirect('show', 'Calendar', null, [
            'search' => [
                'date' => $date->format('Y-m-d'),
            ],
        ]);
    }

    protected function initializeView($view): void
    {
        $user = $this->userService->getUser();
        $view->assign('user', $user);
    }

    /**
     * Sends an email
     */
    protected function sendHtmlMail(
        string $subject,
        array $from,
        array $to,
        string $template,
        array $variables = [],
        $debug = false
    ): void {
        if (!$variables['settings']) {
            $variables['settings'] = $this->settings;
        }

        $mailView = $this->createFluidTemplate($template);
        $mailView->assignMultiple($variables);


        //die($mailView->render());
        // Create mail object and send mail to email address the user who registered to the event entered

        if ($debug) {
            die($mailView->render());
        }

        if ($this->settings['mailSubjectPrefix']) {
            $subject = $this->settings['mailSubjectPrefix'] . ' ' . $subject;
        }

        if ($this->settings['debugMail']) {
            $subject .= ' (DEBUG: ' . implode(',', $to) . ')';
            $to = $this->settings['debugMail'];
        }
        $part = new AbstractPart();
        $mail = GeneralUtility::makeInstance(MailMessage::class);
        $mail->setSubject($subject)
            ->setFrom($from)
            ->setTo($to)
            ->html($mailView->render(), 'text/html')
            ->send();
    }

    /**
     * Create a fluid template
     */
    private function createFluidTemplate(string $name): StandaloneView
    {
        $extbaseFrameworkConfiguration = $this->configurationManager->getConfiguration(
            ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK
        );
        $view = GeneralUtility::makeInstance(StandaloneView::class);
        //$view->setControllerContext($this->controllerContext); // TODO: Replacement for TYPO3 12
        $view->setLayoutRootPaths($extbaseFrameworkConfiguration['view']['layoutRootPaths']);
        $view->setTemplateRootPaths($extbaseFrameworkConfiguration['view']['templateRootPaths']);
        $view->setPartialRootPaths($extbaseFrameworkConfiguration['view']['partialRootPaths']);
        $view->setTemplate($name);
        return $view;
    }
}
