<?php declare(strict_types=1);

namespace Diamond\Application\Notification\SendEmail;

use Diamond\Application\Mailing\MailingFactory;
use Diamond\Config\Mail;
use Diamond\Config\Main;
use Diamond\Infrastructure\Models\MessageRequest\MessageRequest;
use Diamond\Repositories\MessageRequest\MessageRequestRepository;
use Nette\Mail\FallbackMailerException;
use Nette\Mail\SendException;
use Nette\Mail\Message;

class SendEmailHandler
{

    public function __construct(private Mail $mailConfig,
                                private Main $mainConfig,
                                private MessageRequestRepository $messageRequestRepository,
                                private MailingFactory $mailerFactory)
    {
    }

    /**
     * @param SendEmailCommand $command
     */
    public function handle(SendEmailCommand $command): void
    {
        if (!$this->mailConfig->getMail_from()) {
            throw new SendEmailException('mail from not set in configs');
        }

        $mailer = $this->mailerFactory->buildFallbackMailer();

        $message = $command->getMessage();
        $email = $command->getEmail();

        $message = (new Message())
            ->setFrom($this->mailConfig->getMail_from(),$this->mailConfig->getName_from())
            ->addTo($email)
            ->setSubject($message->getSubject())
            ->setHtmlBody($message->getContent())
        ;

        foreach ($command->getMessage()->getAttachFilesLinks() as $file){
            $message->addAttachment($file);
        }

        $messageRequest = new MessageRequest();
        $messageRequest->setSubject($message->getSubject());
        $messageRequest->setBody($message->getHtmlBody());
        $messageRequest->setAttachments(json_encode($message->getAttachments(),JSON_UNESCAPED_UNICODE));
        $messageRequest->setEmailTo(json_encode($message->getHeader('To'),JSON_UNESCAPED_UNICODE));
        $messageRequest->setEmailFrom(json_encode($message->getHeader('From'),JSON_UNESCAPED_UNICODE));
        $messageRequest->setStatus('send');

        try {
            $this->messageRequestRepository->save($messageRequest);

            if(getenv('MODE')==='dev' && $this->mainConfig->getEmail_admin() !== $email){
                $messageRequest->setStatus('emulate');
            }
            else{
                $mailer->send($message);
                $messageRequest->setStatus('success');
            }

            $this->messageRequestRepository->save($messageRequest);
        } catch (FallbackMailerException $ex) {

            foreach ($ex->failures as $failure) {
                if (strpos($failure->getMessage(), 'account is disabled') ||
                    strpos($failure->getMessage(), 'invalid mailbox') ||
                    strpos($failure->getMessage(), 'verification failed')
                ) {
                    $messageRequest->setStatus($failure->getMessage());
                    $this->messageRequestRepository->save($messageRequest);
                    throw new EmailAccountDisabledException($failure->getMessage().':'. $email);
                }
            }

            if(isset($failure)){
                $messageRequest->setStatus($failure->getMessage());
                $this->messageRequestRepository->save($messageRequest);
                throw new SendEmailException($failure->getMessage());
            }

        } catch (SendException $ex) {
            $messageRequest->setStatus($ex->getMessage());
            $this->messageRequestRepository->save($messageRequest);
            throw new SendEmailException($ex->getMessage());
        }
    }
}