<?php

namespace KupShop\AutomationConfiguratorBundle\Configurator\Orders\Actions;

use KupShop\AutomationConfiguratorBundle\Configurator\Interfaces\Config\ActionConfig;
use KupShop\AutomationConfiguratorBundle\Configurator\Orders\OrdersContext;
use KupShop\AutomationConfiguratorBundle\Configurator\Orders\Triggers\OrderCreated;
use KupShop\AutomationConfiguratorBundle\Event\TriggerEvent;
use KupShop\AutomationConfiguratorBundle\Exceptions\ActionRuntimeException;
use KupShop\AutomationConfiguratorBundle\Util\ActionUtil;
use KupShop\KupShopBundle\Util\Mail\Email;
use KupShop\KupShopBundle\Util\Mail\SMSSender;
use Symfony\Contracts\Service\Attribute\Required;

class SendSystemEmail extends Action implements OrdersContext
{
    public const NAME = 'send_system_email';

    #[Required]
    public ActionUtil $actionUtil;

    #[Required]
    public SMSSender $smsSender;

    /**
     * @var Email
     */
    protected $email;

    protected array $allowedSystemEmails = [
        Email::TYPE_ORDER_CHANGE,
        Email::TYPE_ORDER_CREATE,
        Email::TYPE_PAYMENT_SUCCESS,
        Email::TYPE_ORDER_STORNO,
        Email::TYPE_WAITING_PACKAGE,
        Email::TYPE_ORDER_NOT_PAID,
        Email::TYPE_LATE_PACKAGE,
    ];

    /**
     * @required
     */
    public function setEmailService(Email $email): void
    {
        $this->email = $email;
    }

    public function getConfig()
    {
        // TODO: asi by bylo lepsi definovat na Email classe, zda ma byt dostupny v Autopilotu, nez to mit definovany na tvrdo tady
        $emailType = array_filter($this->email->getDefaultTypes(), function ($val) {
            return in_array($val, $this->getAllowedSystemEmails());
        });

        $statuses = array_map(function ($type) {
            $emailService = $this->email->getServiceByType($type);

            return ['key' => (string) $type, 'title' => $emailService::getName()];
        }, $emailType);

        return [
            'label' => 'Odeslat systémovou zprávu',
            'fields' => [
                [
                    'name' => 'order_message_type',
                    'title' => 'Typ zprávy',
                    'type' => 'select',
                    'values' => array_values($statuses),
                ],
                [
                    'name' => 'send_to_invoice_email',
                    'title' => 'Odeslat i na email pro fakturaci',
                    'type' => 'checkbox',
                ],
            ],
        ];
    }

    public function getName()
    {
        return self::NAME;
    }

    public function run(ActionConfig $actionConfig, $context, TriggerEvent $triggerEvent): bool
    {
        $messageType = $actionConfig->getField('order_message_type')->getValue();
        $sendToInvoiceEmail = $actionConfig->getField('send_to_invoice_email')?->getValue() === 'Y';

        if (!$messageType) {
            return false;
        }

        try {
            $emailService = $this->email->getServiceByType($messageType);
        } catch (\Exception $e) {
            throw new ActionRuntimeException("Pro objednávku č. {$context['o_order_no']} nebyla odeslána systémová zpráva.", ['type' => $messageType]);
        }

        $order = $this->actionUtil->getOrder($context['id'], $triggerEvent);
        $action = function () use ($order, $messageType, $sendToInvoiceEmail, $emailService) {
            $order->sendEmail(null, null, false, $messageType, sendToInvoiceEmail: $sendToInvoiceEmail);
            $order->logHistory('Autopilot: odeslána systémová zpráva: '.$messageType);
            $this->smsSender->sendSMS($order, $emailService, force_order_history: true);
        };

        if ($triggerEvent->getTriggerName() == OrderCreated::NAME) {
            $this->postOrderFinishedRunner->registerCallback($action);
        } else {
            $action();
        }

        return true;
    }

    public function getLog(ActionConfig $actionConfig, $context)
    {
        return 'Pro objednávku č. '.$context['o_order_no'].' byla odeslána systémová zpráva.';
    }

    protected function getAllowedSystemEmails(): array
    {
        return $this->allowedSystemEmails;
    }
}
