<?php

namespace Ig\IgReservations\Command;

use Ig\IgReservations\Domain\Repository\EventRepository;
use Ig\IgReservations\Domain\Repository\ReminderRepository;
use Ig\IgReservations\Domain\Repository\ReservationRepository;
use Ig\IgReservations\Domain\Repository\StatusRepository;
use Ig\IgReservations\Service\MailService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\Http\NormalizedParams;
use TYPO3\CMS\Core\Http\ServerRequestFactory;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;

use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
use TYPO3\CMS\Extbase\Service\EnvironmentService;

class ReminderCommand extends Command
{
    protected ReminderRepository $reminderRepository;
    protected EventRepository $eventRepository;
    protected ReservationRepository $reservationRepository;
    protected StatusRepository $statusRepository;
    protected ConfigurationManager $configurationManager;

    public function injectReminderRepository(ReminderRepository $reminderRepository)
    {
        $this->reminderRepository = $reminderRepository;
    }

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

    public function injectReservationRepository(ReservationRepository $reservationRepository)
    {
        $this->reservationRepository = $reservationRepository;
    }

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

    public function injectConfigurationManager(ConfigurationManager $configurationManager)
    {
        $this->configurationManager = $configurationManager;
    }

    /**
     * Configure the command by defining the name, options and arguments
     */
    protected function configure()
    {
        $this->setDescription('Sends a reminder mail to the participants at a specific time');
        $this->setHelp('Sends a reminder mail at a specific time');
    }

    /**
     * Executes the command for showing sys_log entries
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $io = new SymfonyStyle($input, $output);
        //$io->title($this->getDescription());
        //$io->writeln($this->getHelp());
        Bootstrap::initializeBackendAuthentication();


        $extbaseFrameworkConfiguration = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
        $settings = $extbaseFrameworkConfiguration['plugin.']['tx_igreservations.']['settings.'];

        // set storagePids etc. for Query/Repository
        $this->configurationManager->setConfiguration($extbaseFrameworkConfiguration);

        // set environment to frontendMode for uri builder
        $environmentService = GeneralUtility::makeInstance(EnvironmentService::class);
        $environmentService->setFrontendMode(true);
        
        // set TYPO3_REQUEST for link builder from site with adminPageUid
        $finder = GeneralUtility::makeInstance(SiteFinder::class);
        $site = $finder->getSiteByPageId((int)$settings['adminPageUid']);
        //var_dump($site);die();
        $siteUrl = (string) $site->getBase();
        GeneralUtility::setIndpEnv('TYPO3_REQUEST_HOST', $siteUrl);
        GeneralUtility::setIndpEnv('TYPO3_REQUEST_DIR', $siteUrl);


        $normalizedParams = new NormalizedParams(
            [
                'HTTP_HOST' => $site->getBase()->getHost(),
                'HTTPS' => $site->getBase()->getScheme() === 'https' ? 'on' : 'off',
            ],
            $systemConfiguration ?? $GLOBALS['TYPO3_CONF_VARS']['SYS'],
            '',
            ''
        );

        $request = (new ServerRequestFactory())
                    ->createServerRequest('GET', $siteUrl)
                    ->withAttribute('site', $site)
                    ->withAttribute('normalizedParams', $normalizedParams)
                    ->withAttribute('applicationType', 1);

        $GLOBALS['TYPO3_REQUEST'] = $request;

        $mailService = GeneralUtility::makeInstance(MailService::class);
        $mailService->setSettings($settings);
        $mailService->setRequest($request);

        $reminders = $this->reminderRepository->findAll();

        $io->writeln($reminders->count() . ' Reminder-Configurations found');
        $io->writeln('');

        $confirmedStatusses = $this->statusRepository->findForReminder();

        $confirmedStatusUids = [];
        foreach($confirmedStatusses as $status) {
            $confirmedStatusUids[] = $status->getUid();
        }

        foreach($reminders as $reminder) {
            $events = $this->eventRepository->findForReminder($reminder, $confirmedStatusUids);
            $from = $reminder->getMailFrom();
            $subject = $reminder->getSubject();
            $debugMail = $reminder->getDebugMail();

            if($debugMail !== '') {
                $io->writeln('All mails sent to debug mail: ' . $debugMail);
                $io->writeln('');
            }

            $timeModifier = $reminder->getTimeModifier();

            $limit = new \DateTime();
            $limit->modify($timeModifier);

            $io->writeln($events->count() . ' Events found for Reminder ' . $reminder->getUid());

            foreach($events as $event) {
                $reservations = $this->reservationRepository->findForReminder($event);

                $io->writeln($reservations->count() . ' Reservations found for Event ' . $event->getUid());

                foreach($reservations as $reservation) {
                    if($reservation->getReminderSent()) {
                        $io->writeln('Reminder already sent for Reservation ' . $reservation->getUid() . ' to ' . $reservation->getEmail());
                        continue;
                    }
                    if($reservation->getReminderSent() || $reservation->getEmail() === '' || ($reservation->getEmail() !== '' && !GeneralUtility::validEmail($reservation->getEmail()))) {
                        $io->writeln('Not sending reminder mail for Reservation ' . $reservation->getUid() . ' to ' . $reservation->getEmail());
                        continue;
                    }

                    $io->writeln('Sending reminder mail for Reservation ' . $reservation->getUid() . ' to ' . $reservation->getEmail());

                    $mailsTo = [$debugMail !== '' ? $debugMail : $reservation->getEmail()];
                    $reservationLanguage = $reservation->getLanguageConfig();
                    $locale = $reservationLanguage->getLocale();
                    $languageKey = $reservationLanguage->getTwoLetterIsoCode();

                    $mailService->sendMail(
                        $from,
                        $mailsTo,
                        $subject . ($debugMail !== '' ? ' (' . $reservation->getEmail() . ')' : ''),
                        'IgReservations/Command/Reminder/User',
                        [
                            'event' => $event,
                            'reservation' => $reservation,
                            'reminder' => $reminder,
                            'settings' => $settings,
                            'languageKey' => $languageKey
                        ],
                        $locale
                    );

                    $reservation->setReminderSent(true);
                    $this->reservationRepository->update($reservation);
                }

                $io->writeln('');
            }
            $io->writeln('');
        }
        GeneralUtility::makeInstance(PersistenceManager::class)->persistAll();
        $io->writeln('DONE');

        return 0;
    }
}
