<?php

namespace Ig\IgReservations\Service;

use Ig\IgReservations\Domain\Model\Calendar;
use Ig\IgReservations\Domain\Model\Event;
use Ig\IgReservations\Domain\Model\Reservation;
use TYPO3\CMS\Core\Mail\FluidEmail;
use TYPO3\CMS\Core\Mail\Mailer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;

class MailService
{
    protected $request = null;
    private $settings = null;
    private $debugMail = false;

    public function setRequest($request): void
    {
        $this->request = $request;
    }

    public function setSettings($settings): void
    {
        $this->settings = $settings;
        $this->debugMail = $this->settings['debugMail'] ?: false;
    }

    public function sendMail(
        string $from,
        array $mailsTo,
        string $subject,
        string $template,
        array $assigns = [],
        ?string $locale = null
    ) {
        if ($this->settings['mailSubjectPrefix']) {
            $subject = $this->settings['mailSubjectPrefix'] . ' ' . $subject;
        }
        if ($this->debugMail) {
            $subject .= ' (DEBUG: ' . implode(',', $mailsTo) . ')';
            $mailsTo = [$this->debugMail];
        }
        if (!$from || empty($mailsTo)) {
            return false;
        }
        $email = GeneralUtility::makeInstance(FluidEmail::class)
               ->subject($subject)
               ->from($from)
               ->to(...$mailsTo)
               ->setTemplate($template)
               ->format('html');

        $assigns['settings'] = $this->settings;
        if (!empty($assigns)) {
            $email->assignMultiple($assigns);
        }
        //->assigns('event', $event)
        //     ->assign('status', $event->getStatus());

        if ($this->request) {
            $email->setRequest($this->request);
        }
        if ($locale !== null) {
            /*
            if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
                $request = $GLOBALS['TYPO3_REQUEST'];
                $request->setLocale($locale);
                $email->setRequest($request);
            }
            */
            setlocale(LC_ALL, $locale);
        }

        return GeneralUtility::makeInstance(Mailer::class)->send($email);
    }

    public function sendMailAfterConfirmationCoordinationperson(
        Calendar $calendar,
        Event $event,
        ?Reservation $reservation = null
    ) {
        if ($event->getOwner() && $calendar->hasMailToSend('after-confirmation-owner')) {
            if (GeneralUtility::validEmail($this->settings['coordinationPersonMailTo'])) {
                $subject = LocalizationUtility::translate(
                    'mail.subject.after_confirmation_coordinationperson',
                    'IgReservations'
                );
                $mailsTo = [$this->settings['coordinationPersonMailTo']];
                return $this->sendMail(
                    $this->settings['coordinationPersonMailFrom'],
                    $mailsTo,
                    $subject,
                    'IgReservations/Event/Update/CoordinationPerson',
                    [
                        'event' => $event,
                        'status' => $event->getStatus(),
                    ],
                    $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
                );
            }
        }
    }

    public function sendMailAfterConfirmationOwner(Calendar $calendar, Event $event, ?Reservation $reservation = null)
    {
        if ($calendar->hasMailToSend('after-confirmation-owner') && $event->getOwner()) {
            if (GeneralUtility::validEmail($event->getOwner()->getEmail())) {
                $subject = LocalizationUtility::translate('mail.subject.after_confirmation_owner', 'IgReservations');
                $mailsTo = [$event->getOwner()->getEmail()];
                return $this->sendMail(
                    $this->settings['coordinationPersonMailFrom'],
                    $mailsTo,
                    $subject,
                    'IgReservations/Event/Update/Owner',
                    [
                        'event' => $event,
                        'status' => $event->getStatus(),
                    ],
                    $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
                );
            }
        }
    }


    public function sendMailAfterConfirmationTeam(Calendar $calendar, Event $event, ?Reservation $reservation = null)
    {
        if ($calendar->hasMailToSend('after-confirmation-team') && $event->getTeammembers()) {
            $subject = LocalizationUtility::translate('mail.subject.after_confirmation_team', 'IgReservations');
            $mailsTo = [];
            foreach ($event->getTeammembers() as $teammember) {
                if (GeneralUtility::validEmail($teammember->getEmail())) {
                    $mailsTo[] = $teammember->getEmail();
                }
            }
            if (!empty($mailsTo)) {
                return $this->sendMail(
                    $this->settings['coordinationPersonMailFrom'],
                    $mailsTo,
                    $subject,
                    'IgReservations/Event/Update/Team',
                    [
                        'event' => $event,
                        'status' => $event->getStatus(),
                    ],
                    $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
                );
            }
        }
    }


    public function sendMailAfterConfirmationUser(Calendar $calendar, Event $event, ?Reservation $reservation = null)
    {
        if ($calendar->hasMailToSend('after-confirmation-user')) {
            if (!$event->getConfirmationSent() && $event->getReservations()) {
                foreach ($event->getReservations() as $reservation) {
                    if (GeneralUtility::validEmail($reservation->getEmail())) {
                        $subject = LocalizationUtility::translate(
                            'mail.subject.after_confirmation_user',
                            'IgReservations'
                        );
                        $mailsTo = [$reservation->getEmail()];

                        $this->sendMail(
                            $this->settings['coordinationPersonMailFrom'],
                            $mailsTo,
                            $subject,
                            'IgReservations/Event/Update/User',
                            [
                                'event' => $event,
                                'status' => $event->getStatus(),
                                'reservation' => $reservation,
                            ],
                            $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
                        );
                    }
                }
                return true; // do event->setConfirmationSent
            }
        }
        return false; // no email send
    }


    public function sendMailAfterUnapproveEventUser(Event $event)
    {
        $calendar = $event->getCalendar();
        if ($calendar->hasMailToSend('after-confirmation-user')) {
            foreach ($event->getReservations() as $reservation) {
                if (GeneralUtility::validEmail($reservation->getEmail())) {
                    $subject = LocalizationUtility::translate('mail.subject.after_unapprove_user', 'IgReservations');
                    $mailsTo = [$reservation->getEmail()];

                    $this->sendMail(
                        $this->settings['coordinationPersonMailFrom'],
                        $mailsTo,
                        $subject,
                        'IgReservations/Event/Unapprove/User',
                        [
                            'event' => $event,
                        ],
                        $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
                    );
                }
            }
            return true; // do event->setConfirmationSent
        }
        return false; // no email send
    }


    public function sendMailAfterBookingUser(Calendar $calendar, Event $event,?Reservation $reservation = null): void
    {
        if ($calendar->hasMailToSend('after-booking-user')) {
            if (GeneralUtility::validEmail($reservation->getEmail())) {
                $subject = LocalizationUtility::translate('mail.subject.after_booking_user', 'IgReservations');
                $mailsTo = [$reservation->getEmail()];
                $this->sendMail(
                    $this->settings['coordinationPersonMailFrom'],
                    $mailsTo,
                    $subject,
                    'IgReservations/Event/Create/User',
                    [
                        'event' => $event,
                        'status' => $event->getStatus(),
                        'reservation' => $reservation,
                    ],
                    $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
                );
            }
        }
    }

    public function sendMailAfterBookingCoordinationpersonAndTeam(
        Calendar $calendar,
        Event $event,
        ?Reservation $reservation = null
    ): void {
        if ($calendar->hasMailToSend('after-booking-coordinationperson') || $calendar->hasMailToSend(
            'after-booking-team'
        )) {
            $subject = $this->settings['adminNewBookingSubject'] ?? 'Neue Buchung';
            $mailsTo = [];
            if ($calendar->hasMailToSend('after-booking-coordinationperson')) {
                $mailsTo = array_merge(
                    $mailsTo,
                    array_filter(GeneralUtility::trimExplode(',', $this->settings['coordinationPersonMail']))
                );
            }
            if ($calendar->hasMailToSend('after-booking-team')) {
                //$teammembers = $this->feUserRepository->findTeammembers($this->settings['usergroupForTeammembers'] ? $this->settings['usergroupForTeammembers'] : 0);
                $teammembers = $event->getTeammembers();
                foreach ($teammembers as $teammember) {
                    $email = $teammember->getEmail();
                    if (GeneralUtility::validEmail($email) && !in_array($email, $mailsTo)) {
                        $mailsTo[] = $email;
                    }
                }
                $owner = $event->getOwner();
                if ($owner) {
                    $email = $owner->getEmail();
                    if (GeneralUtility::validEmail($email) && !in_array($email, $mailsTo)) {
                        $mailsTo[] = $email;
                    }
                }
            }
            if (!empty($mailsTo)) {
                $this->sendMail(
                    $this->settings['coordinationPersonMailFrom'],
                    $mailsTo,
                    $subject,
                    'IgReservations/Event/Create/Admin',
                    [
                        'event' => $event,
                        'status' => $event->getStatus(),
                        'reservation' => $reservation,
                    ],
                    $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
                );
            }
        }
    }

    /**
     * [sendMailAfterCancelRequest description]
     * @param  Reservation $reservation [description]
     * @return [type]                   [description]
     */
    public function sendMailAfterCancelRequest(Calendar $calendar, Event $event, Reservation $reservation): void
    {
        $mailsTo = array_filter(GeneralUtility::trimExplode(',', $this->settings['coordinationPersonMail']));

        if (!empty($mailsTo)) {
            $this->sendMail(
                $this->settings['coordinationPersonMailFrom'],
                $mailsTo,
                'Absage einer Buchung angefordert',
                'IgReservations/Reservation/CancelRequest/Admin',
                [
                    'event' => $event,
                    'status' => $event->getStatus(),
                    'reservation' => $reservation,
                ],
                $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
            );
        }
    }

    /**
     * [sendMailAfterCancelRequest description]
     * @param  Reservation $reservation [description]
     * @return [type]                   [description]
     */
    public function sendMailAfterApproveCancelRequest(Calendar $calendar, Event $event, Reservation $reservation): void
    {
        if (GeneralUtility::validEmail($reservation->getEmail())) {
            $subject = LocalizationUtility::translate('mail.subject.after_approve_cancel_request', 'IgReservations');
            $mailsTo = [$reservation->getEmail()];
            $this->sendMail(
                $this->settings['coordinationPersonMailFrom'],
                $mailsTo,
                $subject,
                'IgReservations/Reservation/ApproveCancelRequest/User',
                [
                    'event' => $event,
                    'status' => $event->getStatus(),
                    'reservation' => $reservation,
                ],
                $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
            );
        }
    }

    /**
     * [sendMailAfterCancelRequest description]
     * @param  Reservation $reservation [description]
     * @return [type]                   [description]
     */
    public function sendMailAfterUnapproveCancelRequest(Calendar $calendar, Event $event, Reservation $reservation): void
    {
        if (GeneralUtility::validEmail($reservation->getEmail())) {
            $subject = LocalizationUtility::translate('mail.subject.after_unapprove_cancel_request', 'IgReservations');
            $mailsTo = [$reservation->getEmail()];
            $this->sendMail(
                $this->settings['coordinationPersonMailFrom'],
                $mailsTo,
                $subject,
                'IgReservations/Reservation/UnapproveCancelRequest/User',
                [
                    'event' => $event,
                    'status' => $event->getStatus(),
                    'reservation' => $reservation,
                ],
                $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
            );
        }
    }

    /**
     * [sendMailAfterCancelRequest description]
     * @param  Reservation $reservation [description]
     * @return [type]                   [description]
     */
    public function sendMailAfterCreateBookingUser(Reservation $reservation): void
    {
        $event = $reservation->getEvent();
        $calendar = $event->getCalendar();
        if ($calendar->hasMailToSend('after-booking-user')) {
            if (GeneralUtility::validEmail($reservation->getEmail())) {
                $subject = LocalizationUtility::translate('mail.subject.after_booking_user', 'IgReservations');
                $mailsTo = [$reservation->getEmail()];
                $this->sendMail(
                    $this->settings['coordinationPersonMailFrom'],
                    $mailsTo,
                    $subject,
                    'IgReservations/Reservation/Create/User',
                    [
                        'event' => $event,
                        'status' => $event->getStatus(),
                        'reservation' => $reservation,
                    ],
                    $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
                );
            }
        }
    }

    /**
     * [sendMailAfterCancelRequest description]
     * @param  Reservation $reservation [description]
     * @return [type]                   [description]
     */
    public function sendMailAfterCreateBookingTeam(Reservation $reservation): void
    {
        $event = $reservation->getEvent();
        $calendar = $event->getCalendar();
        $mailsTo = [];
        if ($calendar->hasMailToSend('after-booking-coordinationperson')) {
            $mailsTo = array_merge(
                $mailsTo,
                array_filter(GeneralUtility::trimExplode(',', $this->settings['coordinationPersonMail']))
            );
        }
        if ($calendar->hasMailToSend('after-booking-team')) {
            //$teammembers = $this->feUserRepository->findTeammembers($this->settings['usergroupForTeammembers'] ? $this->settings['usergroupForTeammembers'] : 0);
            $owner = $event->getOwner();
            $email = $owner->getEmail();
            if (GeneralUtility::validEmail($email) && !in_array($email, $mailsTo)) {
                $mailsTo[] = $email;
            }
            $teammembers = $event->getTeammembers();
            foreach ($teammembers as $teammember) {
                $email = $teammember->getEmail();
                if (GeneralUtility::validEmail($email) && !in_array($email, $mailsTo)) {
                    $mailsTo[] = $email;
                }
            }
        }

        if (!empty($mailsTo)) {
            $subject = $this->settings['adminNewBookingSubject'] ?? 'Neue Buchung';
            $this->sendMail(
                $this->settings['coordinationPersonMailFrom'],
                $mailsTo,
                $subject,
                'IgReservations/Reservation/Create/Admin',
                [
                    'event' => $event,
                    'status' => $event->getStatus(),
                    'reservation' => $reservation,
                ],
                $reservation ? $reservation->getLanguageConfig()
->getLocale() : null
            );
        }
    }
}
