<?php

namespace KupShop\ReclamationsBundle\Email;

use KupShop\KupShopBundle\Email\BaseEmail;
use KupShop\KupShopBundle\Email\EmailGroupTypeEnum;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use KupShop\OrderingBundle\Util\Attachment\AttachmentLocator;
use KupShop\ReclamationsBundle\Entity\ReclamationEntity;
use KupShop\ReclamationsBundle\Util\ReclamationsUtil;
use KupShop\ReturnsBundle\Util\ReturnsUtil;
use Symfony\Component\Routing\Router;
use Symfony\Component\Routing\RouterInterface;

class ReclamationEmail extends BaseEmail
{
    protected static $priority = -2;
    protected static $type = 'RECLAMATION_EMAIL';
    protected static $group = EmailGroupTypeEnum::RECLAMATION;

    /** @var ReclamationEntity */
    protected $reclamation;
    protected $comment;

    /** @var ReclamationsUtil */
    private $reclamationsUtil;
    private $logHistory = false;

    public static string $type_test_email = 'reclamations';

    /** @var AttachmentLocator */
    private $attachmentLocator;

    /**
     * @required
     */
    public function setReclamationsUtil(ReclamationsUtil $reclamationsUtil)
    {
        $this->reclamationsUtil = $reclamationsUtil;
    }

    /**
     * @required
     */
    public function setAttachmentLocator(AttachmentLocator $attachmentLocator)
    {
        $this->attachmentLocator = $attachmentLocator;
    }

    /** @var ReclamationsUtil */
    private $returnsUtil;

    /**
     * @required
     */
    public function setReturnsUtil(?ReturnsUtil $returnsUtil)
    {
        $this->returnsUtil = $returnsUtil;
    }

    public function setComment($comment)
    {
        $this->comment = $comment;

        return $this;
    }

    public function setLogHistory($logHistory)
    {
        $this->logHistory = $logHistory;

        return $this;
    }

    public function setReclamation(ReclamationEntity $reclamation)
    {
        $this->reclamation = $reclamation;

        return $this;
    }

    public function testEmail(): array
    {
        if (!isset($this->reclamation)) {
            $this->setTestEntity();
        }

        return parent::testEmail();
    }

    public function setTestEntity(?int $id = null): void
    {
        if (!$id) {
            $id = sqlQueryBuilder()->select('MAX(id)')->from('reclamations')->execute()->fetchOne();
        }

        if ($id) {
            $this->reclamation = $this->reclamationsUtil->getReclamation($id);

            return;
        }

        $this->reclamation = new ReclamationEntity();
        $this->reclamation->setCode('R1234');
        $this->reclamation->setId(1234);
        $this->reclamation->setPackageId('TESTTEST');
        $this->reclamation->setBankAccount('TESTTESTTEST');
        $this->reclamation->setDescr('Some test description');
        $this->reclamation->setData([]);
        $this->reclamation->setOrderNumber('123456');
        $this->reclamation->setIdOrder('1');
        $this->reclamation->setDateCreated('2023-01-05 12:20:15');
    }

    public function getEmail($replacements = []): array
    {
        $template = $this->getEmailTemplate();

        $message = $this->renderEmail($template);
        $message['body'] = $this->reclamationsUtil->replacePlaceholders($message['body'], [], [$this, 'replacePlaceholdersItem']);
        $message['subject'] = $this->reclamationsUtil->replacePlaceholders($message['subject'], [], [$this, 'replacePlaceholdersItem']);

        return $message;
    }

    public function sendEmail($message)
    {
        if ($bcc = (\Settings::getDefault()->archive_email ?? null)) {
            $message['bcc'] = [$bcc];
        }

        $sent = parent::sendEmail($message);

        if ($sent && $this->logHistory && $this->reclamation) {
            if ($this->comment) {
                $template = $this->comment;
            } else {
                $template = $this->getEmailTemplate()['body'];
            }

            $template = $this->reclamationsUtil->replacePlaceholders($template, [], [$this, 'replacePlaceholdersItem']);

            $attachments = [];
            if (!empty($message['attachments'])) {
                foreach ($message['attachments'] as $attachment) {
                    $attachments[] = $attachment['type'];
                }
            }

            $this->reclamationsUtil->logHistory($this->reclamation->getId(), $template, true, $this->reclamation->getStatus(), ['attachments' => $attachments]);
        }

        return $sent;
    }

    public function renderEmail($template, $data = [], $base_template = 'other.tpl'): array
    {
        if ($this->comment) {
            $template['body'] = $this->comment;
        }

        $message = parent::renderEmail($template, $data, $base_template);

        if ($this->reclamation) {
            $message['to'] = $this->reclamation->getEmail();
        }
        $message['template'] = $template;

        return $message;
    }

    public static function getPlaceholders()
    {
        $placeholders = [
            'KOD_REKLAMACE' => [
                'text' => 'Kód reklamace',
            ],
            'ODKAZ_REKLAMACE' => [
                'text' => 'Odkaz na reklamace',
            ],
            'REKLAMACE_INSTRUKCE' => [
                'text' => 'Instrukce',
            ],
            'KOD_OBJEDNAVKY' => [
                'text' => 'Kód objednávky vyřizující reklamaci výměnou',
            ],
            'ODKAZ_OBJEDNAVKA' => [
                'text' => 'Odkaz na objednávku vyřizující reklamaci výměnou',
            ],
            'KOD_PUVODNI_OBJEDNAVKY' => [
                'text' => 'Kód objednávky ze které byla vytvořena reklamace',
            ],
            'ODKAZ_PUVODNI_OBJEDNAVKA' => [
                'text' => 'Odkaz na objednávku ze které byla vytvořena reklamace',
            ],
            'ODKAZ_PDF' => [
                'text' => 'Odkaz na PDF',
            ],
            'BALIK_ID' => [
                'text' => 'Číslo balíku',
            ],
            'DATUM_VYTVORENI' => [
                'text' => 'Datum vytvoření reklamace',
            ],
            'CISLO_UCTU' => [
                'text' => 'Číslo účtu',
            ],
            'PACKAGE_LABEL' => [
                'text' => 'Autorizační kód Odvozu zboží',
            ],
            'POSUDEK' => [
                'text' => 'Posudek',
            ],
            'POZNAMKA_UZIVATELE' => [
                'text' => 'Poznámka uživatele',
            ],
            'REKAPITULACE_OBCHODNIKOVI' => [
                'text' => 'Rekapitulace obchodníkovi',
            ],
            'PRILOHY_NAHRANE_ZAKAZNIKEM' => [
                'text' => 'Vloží seznam příloh nahraných zákazníkem',
            ],
        ];

        return [self::$type => $placeholders] + (parent::getPlaceholders() ?? []);
    }

    public function replacePlaceholdersItem($placeholder)
    {
        $result = parent::replacePlaceholdersItem($placeholder);
        $dbcfg = \Settings::getDefault();

        if (!$result) {
            switch ($placeholder) {
                case 'KOD_REKLAMACE':
                    return $this->reclamation->getCode();
                case 'ODKAZ_REKLAMACE':
                    return path('kupshop_reclamations_reclamations_reclamation', [
                        'id' => $this->reclamation->getId(),
                        'cf' => $this->reclamationsUtil->getSecurityCode($this->reclamation->getId()),
                    ]);
                case 'ODKAZ_VRATKA':
                    $returnId = $this->reclamation->getData()['return'] ?? null;
                    if ($returnId) {
                        return path('kupshop_returns_returns_return', ['id' => $returnId, 'cf' => $this->returnsUtil->getSecurityCode($returnId)]);
                    }
                    // no break
                case 'KOD_VRATKY':
                    return $this->returnsUtil->getCode($this->reclamation->getData()['return'] ?? null);
                case 'REKLAMACE_INSTRUKCE':
                    return $dbcfg->reclamations['descr'] ?? '';
                case 'KOD_OBJEDNAVKY':
                    $exchangeOrderID = $this->reclamation->getData()['exchange_order'] ?? null;
                    if ($exchangeOrderID) {
                        $order = new \Order();
                        $order->createFromDB($exchangeOrderID);

                        return $order->order_no;
                    }

                    return '';
                case 'ODKAZ_OBJEDNAVKA':
                    $exchangeOrderID = $this->reclamation->getData()['exchange_order'] ?? null;
                    if ($exchangeOrderID) {
                        $order = new \Order();
                        $order->createFromDB($exchangeOrderID);

                        return $order->getUrl();
                    }

                    return '';
                case 'ODKAZ_PUVODNI_OBJEDNAVKA':
                    $id_order = $this->reclamation->getIdOrder();

                    $order = new \Order();
                    $order->createFromDB($id_order);

                    return $order->getUrl();
                case 'KOD_PUVODNI_OBJEDNAVKY':
                    return $this->reclamation->getOrderNumber();
                case 'ODKAZ_PDF':
                    return path('kupshop_reclamations_reclamations_reclamationattachment', [
                        'id' => $this->reclamation->getId(),
                        'cf' => $this->reclamationsUtil->getSecurityCode($this->reclamation->getId()),
                    ], Router::ABSOLUTE_URL);
                case 'BALIK_ID':
                    return $this->reclamation->getPackageId();
                case 'CISLO_UCTU':
                    return $this->reclamation->getBankAccount();
                case 'PACKAGE_LABEL':
                    return $this->reclamationsUtil->getAuthCode($this->reclamation->getId());
                case 'POSUDEK':
                    return $this->reclamation->getDescr();
                case 'DATUM_VYTVORENI':
                    $date = $this->reclamation->getDateCreated();
                    if (!$date) {
                        return '';
                    }

                    return \DateTime::createFromFormat('Y-m-d H:i:s', $date)->format(\Settings::getDateFormat());
                case 'POZNAMKA_UZIVATELE':
                    return $this->reclamation->getUserNote();
                case 'REKAPITULACE_OBCHODNIKOVI':
                    // Objednavka, z ktere byla reklamace vytvorena
                    $order = new \Order();
                    $order->createFromDB($this->reclamation->getIdOrder());

                    $smarty = createSmarty(true, true);
                    $smarty->assign('reclamation', $this->reclamation);
                    $smarty->assign('order', $order);

                    return $smarty->fetch('email/reclamationShopkeeper.tpl');
                case 'PRILOHY_NAHRANE_ZAKAZNIKEM':
                    $returnCustomData = $this->reclamation->getData() ?? [];
                    $element = HTML::create('div')
                        ->tag('h3')->text(translate_shop('attachments_uploaded_by_customer', 'email'))->end();
                    $list = $element->tag('ul');
                    foreach ($returnCustomData['userContent'] ?? [] as $fileInfo) {
                        $src = ltrim($fileInfo['src'], '/');
                        $list->tag('li')
                            ->tag('a')
                            ->attr('href', path('page', ['path' => $src], RouterInterface::ABSOLUTE_URL))
                            ->text($fileInfo['originalFilename'])->end()->end();
                    }

                    return $element->end()->end();
            }
        }

        return $result;
    }

    public function getAttachments($template): array
    {
        if (empty($template['attachments'])) {
            return [];
        }

        return $this->renderAttachments(function () use ($template): iterable {
            $order = new \Order();
            $order->createFromDB($this->reclamation->getIdOrder());

            $types = json_decode($template['attachments'], true);
            foreach ($types as $type) {
                $attachment = $this->attachmentLocator->getServiceByType($type, $order);
                $attachment->setReclamation($this->reclamation);
                yield $attachment;
            }
        });
    }

    public function getTestType(): string
    {
        return self::$type_test_email;
    }

    public function __wakeup()
    {
        parent::__wakeup();

        $this->attachmentLocator = ServiceContainer::getService(AttachmentLocator::class);
        $this->reclamationsUtil = ServiceContainer::getService(ReclamationsUtil::class);
    }

    public function __sleep()
    {
        return array_diff(parent::__sleep(), ['attachmentLocator', 'reclamationsUtil']);
    }
}
