<?php


namespace Diamond\Application\Notification;

use Core\MailingPreparation\CustomPrepareData;
use Core\MailingPreparation\MailingCook;
use Core\TwigAwareInterface;
use Core\TwigAwareTrait;
use Diamond\Config\Mail;
use Diamond\Config\Main;
use Diamond\Infrastructure\Models\Report\Report;
use Diamond\Application\Notification\Dto\Message;
use Diamond\Application\Notification\Exceptions\NotificationException;
use Diamond\Application\Notification\Exceptions\ReportNotFoundException;
use Diamond\Application\Notification\SendEmail\SendEmailCommand;
use Diamond\Application\Notification\SendSms\SendSmsCommand;
use Diamond\Repositories\Report\ReportCriteria;
use Diamond\Repositories\Report\ReportRepository;
use Nette\Mail\FallbackMailer;
use Diamond\Config\Sms;
use SmsSender\Drivers\Smsc\Smsc;
use spaceonfire\CommandBus\CommandBus;
use SmsSender\Sender;
use SmsSender\Drivers\Smsc\Config;

/**
 * Class NotificationService
 * @package Diamond\Application\Notification
 */
class NotificationService implements TwigAwareInterface
{
    use TwigAwareTrait;

    protected Sender $smsDriver;

    public function __construct(protected Mail $mailConfig,
                                protected FallbackMailer $mailer,
                                protected Main $mainConfig,
                                protected ReportRepository $reportRepository,
                                protected MailingCook $mailingCook,
                                protected Sms $smsConfig,
                                protected CommandBus $commandBus)
    {


        $config = (new Config)
            ->setLogin($smsConfig->getLogin())
            ->setPassword($smsConfig->getPassword())
            ->setFrom($smsConfig->getFrom());

        $this->smsDriver = new Sender(new Smsc($config));
    }


    /**
     * @return float
     */
    public function getSmsBalance(): float
    {
        return (float)$this->smsDriver->getBalance();
    }


    /**
     * @param string $reportName
     * @param array $data
     * @return Message
     */
    public function createMessageByReport(string $reportName, array $data): Message
    {

        $reports = $this->reportRepository->findByCriteria(
            ReportCriteria::create()->setFilterByCode($reportName)
        );

        /**
         * @var Report $report
         */
        if (!$report = $reports->current()) {
            throw new ReportNotFoundException(sprintf('report by code `%s` not found', $reportName));
        }

        $data = array_change_key_case($data);

        //кастомный драйвер
        $this->mailingCook->addDriver(new CustomPrepareData($data), $reportName);
        
        if (!$body = $report->getContent()) {
            $body = file_get_contents(
                $this->twig->load($report->getTemplate())->getSourceContext()->getPath());
        }

        $body = $this->mailingCook->prepare($body, time());
        $subject = $report->getTitle();

        return (new Message($subject, $body));
    }


    /**
     * Отправка письма на email на основе шаблона уведомления
     * @param string $report
     * @param string $email
     * @param array $data
     */
    public function sendToEmailByReport(string $report, string $email, array $data): void
    {
        if (!$email) {
            throw new NotificationException('user email is empty');
        }

        $message = $this->createMessageByReport($report, $data);

        if (isset($data['attach'])) {
            $message->setAttachFilesLinks((array)$data['attach']);
        }

        $this->sendToEmail($email, $message);
    }

    /**
     * Шлем на телефон
     *
     * @param string $report
     * @param string $phone
     * @param array $data
     */
    public function sendToPhoneByReport(string $report, string $phone, array $data): void
    {
        if (!$phone) {
            throw new NotificationException('user phone is empty');
        }

        $message = $this->createMessageByReport($report, $data);
        $message->setContent( preg_replace('~<img.*?\/>~','',$message->getContent()));//удаляем левак

        if (isset($data['attach'])) {
            $message->setAttachFilesLinks((array)$data['attach']);
        }

        $this->sendToPhoneNumber($phone, $message);
    }

    /**
     * @deprecated
     * @param Message $message
     */
    public function sendToAdmin(Message $message): void
    {
        $this->sendToAdminEmail($message);
    }

    /**
     * Отправка администратору на email
     * @param Message $message
     */
    public function sendToAdminEmail(Message $message): void
    {
        if (!$this->mainConfig->getEmail_admin()) {
            throw  new NotificationException('email admin not set');
        }
        $this->sendToEmail($this->mainConfig->getEmail_admin(), $message);
    }

    /**
     * отправляем письмо на email
     * @param string $email
     * @param Message $messageRequest
     */
    public function sendToEmail(string $email, Message $messageRequest): void
    {
        $this->commandBus->handle(
            new SendEmailCommand($email, $messageRequest)
        );
    }

    /**
     * отправляем смс
     * @param string $phone
     * @param Message $message
     */
    public function sendToPhoneNumber(string $phone, Message $message): void
    {
        $this->commandBus->handle(
            new SendSmsCommand($phone, $message)
        );
    }

}