<?php

namespace FiloBlu\Rma\Model\Rma\Status;

use Exception;
use FiloBlu\Rma\Helper\RmaHelper;
use FiloBlu\Rma\Model\RmaEmailManagment;
use Magento\Framework\Api\AttributeValueFactory;
use Magento\Framework\Api\ExtensionAttributesFactory;
use Magento\Framework\App\Area;
use Magento\Framework\Data\Collection\AbstractDb;
use Magento\Framework\Exception\MailException;
use Magento\Framework\Mail\Template\SenderResolverInterface;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Model\Context;
use Magento\Framework\Model\ResourceModel\AbstractResource;
use Magento\Framework\Registry;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Magento\Framework\Translate\Inline\StateInterface;
use Magento\Rma\Api\RmaAttributesManagementInterface;
use Magento\Rma\Api\RmaRepositoryInterface;
use Magento\Rma\Helper\Data;
use Magento\Rma\Model\Config;
use Magento\Rma\Model\RmaFactory;
use Magento\Sales\Model\Order\Address\Renderer as AddressRenderer;
use Magento\Store\Model\StoreManagerInterface;
use Throwable;

/**
 * Class History
 * @package Model\Rma\Status
 *
 */
class History extends \Magento\Rma\Model\Rma\Status\History
{
    /**
     * @var string
     */
    const XML_PATH_RECEIVED_EMAIL = 'sales_email/magento_rma_received';

    /**
     * @var RmaEmailManagment
     */
    protected $rmaEmailManagement;
    /**
     * @var SenderResolverInterface
     */
    private $senderResolver;
    /**
     * @var RmaHelper
     */
    private $rmaDataHelper;


    /**
     * History constructor.
     * @param Context $context
     * @param Registry $registry
     * @param ExtensionAttributesFactory $extensionFactory
     * @param AttributeValueFactory $customAttributeFactory
     * @param StoreManagerInterface $storeManager
     * @param RmaFactory $rmaFactory
     * @param Config $rmaConfig
     * @param TransportBuilder $transportBuilder
     * @param DateTime $dateTimeDateTime
     * @param StateInterface $inlineTranslation
     * @param Data $rmaHelper
     * @param TimezoneInterface $localeDate
     * @param RmaRepositoryInterface $rmaRepositoryInterface
     * @param RmaAttributesManagementInterface $metadataService
     * @param AddressRenderer $addressRenderer
     * @param RmaEmailManagment $rmaEmailManagement
     * @param SenderResolverInterface $senderResolver
     * @param RmaHelper $rmaDataHelper
     * @param AbstractResource|null $resource
     * @param AbstractDb|null $resourceCollection
     * @param array $data
     */
    public function __construct(
        Context $context,
        Registry $registry,
        ExtensionAttributesFactory $extensionFactory,
        AttributeValueFactory $customAttributeFactory,
        StoreManagerInterface $storeManager,
        RmaFactory $rmaFactory,
        Config $rmaConfig,
        TransportBuilder $transportBuilder,
        DateTime $dateTimeDateTime,
        StateInterface $inlineTranslation,
        Data $rmaHelper,
        TimezoneInterface $localeDate,
        RmaRepositoryInterface $rmaRepositoryInterface,
        RmaAttributesManagementInterface $metadataService,
        AddressRenderer $addressRenderer,
        RmaEmailManagment $rmaEmailManagement,
        SenderResolverInterface $senderResolver,
        RmaHelper $rmaDataHelper,
        AbstractResource $resource = null,
        AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        parent::__construct(
            $context,
            $registry,
            $extensionFactory,
            $customAttributeFactory,
            $storeManager,
            $rmaFactory,
            $rmaConfig,
            $transportBuilder,
            $dateTimeDateTime,
            $inlineTranslation,
            $rmaHelper,
            $localeDate,
            $rmaRepositoryInterface,
            $metadataService,
            $addressRenderer,
            $resource,
            $resourceCollection,
            $data
        );
        $this->rmaEmailManagement = $rmaEmailManagement;
        $this->senderResolver = $senderResolver;
        $this->rmaDataHelper = $rmaDataHelper;
    }

    /**
     * @return \FiloBlu\Rma\Model\Rma\Status\History|null
     */
    public function sendReceivedEmail()
    {
        try {
            return $this->_sendRmaEmailWithItems($this->getRma(), $this->getRootReceivedRmaEmail());
        } catch (Exception $e) {
            $this->_logger->critical($e->getMessage(), ['exception' => $e]);
        }
        return null;
    }

    /**
     * @return string
     */
    public function getRootReceivedRmaEmail()
    {
        return self::XML_PATH_RECEIVED_EMAIL;
    }

    /**
     * @param $config
     * @return $this
     */
    public function sendRmaEmail($config)
    {
        try {
            return $this->sendEmail($this->getRma(), $config);
        } catch (Exception $e) {
            $this->_logger->critical($e->getMessage(), ['exception' => $e]);
        }

        return $this;
    }

    /**
     * @param $rma
     * @param $rootConfig
     * @return $this
     */
    protected function sendEmail($rma, $rootConfig, $iswrongOrDamagedRma = false)
    {
        try {
            $storeId = $rma->getStoreId();
            $order = $rma->getOrder();

            $this->_rmaConfig->init($rootConfig, $storeId);

            if (!$this->_rmaConfig->isEnabled()) {
                return $this;
            }

            $this->inlineTranslation->suspend();

            $copyTo = $this->_rmaConfig->getCopyTo();
            $copyMethod = $this->_rmaConfig->getCopyMethod();

            if ($order->getCustomerIsGuest()) {
                $template = $this->_rmaConfig->getGuestTemplate();
                $customerName = $order->getBillingAddress()->getName();
            } else {
                $template = $this->_rmaConfig->getTemplate();
                $customerName = $rma->getCustomerName();
            }

            $order->setData('customer_name', $order->getCustomerName());
            $order->setData('is_not_virtual', $order->getIsNotVirtual());

            $sendTo = [['email' => $order->getCustomerEmail(), 'name' => $customerName]];
            if ($rma->getCustomerCustomEmail() && $rma->getCustomerCustomEmail() !== $order->getCustomerEmail()) {
                $sendTo[] = ['email' => $rma->getCustomerCustomEmail(), 'name' => $customerName];
            }
            if ($copyTo && $copyMethod == 'copy') {
                foreach ($copyTo as $email) {
                    $sendTo[] = ['email' => $email, 'name' => null];
                }
            }

            $returnAddress = $this->rmaHelper->getReturnAddress('html', [], $storeId);

            $bcc = [];
            if ($copyTo && $copyMethod == 'bcc') {
                $bcc = $copyTo;
            }
            $store = $this->_storeManager->getStore($storeId);
            $identity = $this->_rmaConfig->getIdentity('', $storeId);


            foreach ($sendTo as $recipient) {
                $this->_transportBuilder
                    ->setTemplateIdentifier($template)
                    ->setTemplateOptions(['area' => Area::AREA_FRONTEND, 'store' => $storeId])
                    ->setTemplateVars(
                        [
                            'rma'                      => $rma,
                            'easy_return'              => $rma->getIsEasyReturn(),
                            'rma_id'                   => $rma->getId(),
                            'rma_data'                 => [
                                'status_label' => is_string($rma->getStatusLabel()) ?
                                    $rma->getStatusLabel() : $rma->getStatusLabel()->render(),
                            ],
                            'order'                    => $order,
                            'order_data'               => [
                                'customer_name' => $order->getCustomerName(),
                            ],
                            'created_at_formatted_1'   => $rma->getCreatedAtFormated(1),
                            'store'                    => $store,
                            'return_address'           => $returnAddress,
                            'item_collection'          => $rma->getItemsForDisplay(),
                            'formattedShippingAddress' => $this->addressRenderer->format(
                                $order->getShippingAddress(),
                                'html'
                            ),
                            'formattedBillingAddress'  => $this->addressRenderer->format(
                                $order->getBillingAddress(),
                                'html'
                            ),
                            'supportEmail'             => $store->getConfig('trans_email/ident_support/email'),
                            'storePhone'               => $store->getConfig('general/store_information/phone'),
                        ]
                    )
                    ->addTo($recipient['email'], $recipient['name'])
                    ->addBcc($bcc);

                if (method_exists($this->_transportBuilder, 'setFromByScope')) {
                    $this->_transportBuilder->setFromByScope($identity, $storeId);
                } else {
                    $emailFrom = $this->senderResolver->resolve($identity, $storeId);
                    $this->_transportBuilder->setFrom($emailFrom);
                }

                $transport = $this->_transportBuilder->getTransport();
                $transport->sendMessage();
            }

            $this->setEmailSent(true);
        } catch (MailException $exception) {
            $this->_logger->critical($exception->getMessage(), ['exception' => $exception]);
        } catch (Exception $e) {
            $this->_logger->critical($e->getMessage(), ['exception' => $e]);
        } catch (Throwable $t) {
            $this->_logger->critical($t->getMessage(), ['exception' => $t]);
        }

        $this->inlineTranslation->resume();

        return $this;
    }

    /**
     * @return \Magento\Rma\Model\Rma\Status\History
     */
    public function sendAuthorizeEmail()
    {
        $rma = $this->getRma();
        return $this->rmaEmailManagement->checkIfSendRmaEmail($rma);
    }

    /**
     * Sending email with RMA data
     *
     * @return $this
     */
    public function sendNewRmaEmail()
    {
        return $this;
    }

    public function sendWrongOrDamagedItemsEmail($config, $wrongOrDamagedItems)
    {
        $rma = clone $this->getRma();

        $rma->setItems([]);
        $rma->setItems($wrongOrDamagedItems);

        try {

            $storeId = $rma->getStoreId();
            $order = $rma->getOrder();

            if (!$this->rmaDataHelper->isWrongOrDamagedEmailEmailConfigEnabled($config, $storeId)) {
                return $this;
            }

            $this->inlineTranslation->suspend();

            $copyTo = $this->rmaDataHelper->getCopyTo($config, $storeId) !== null
                ? explode(',', $this->rmaDataHelper->getCopyTo($config, $storeId))
                : null;
            $copyMethod = $this->rmaDataHelper->getCopyMethod($config, $storeId);

            if ($order->getCustomerIsGuest()) {
                //$template = $this->_rmaConfig->getGuestTemplate();
                $customerName = $order->getBillingAddress()->getName();
            } else {
                $customerName = $rma->getCustomerName();
            }
            $template = $this->rmaDataHelper->getTemplate($config, $storeId);

            $order->setData('customer_name', $order->getCustomerName());
            $order->setData('is_not_virtual', $order->getIsNotVirtual());

            $sendTo = [['email' => $order->getCustomerEmail(), 'name' => $customerName]];
            if ($rma->getCustomerCustomEmail() && $rma->getCustomerCustomEmail() !== $order->getCustomerEmail()) {
                $sendTo[] = ['email' => $rma->getCustomerCustomEmail(), 'name' => $customerName];
            }
            if ($copyTo && $copyMethod == 'copy') {
                foreach ($copyTo ?? [] as $email) {
                    $sendTo[] = ['email' => $email, 'name' => null];
                }
            }

            $returnAddress = $this->rmaHelper->getReturnAddress('html', [], $storeId);

            $bcc = [];
            if ($copyTo && $copyMethod == 'bcc') {
                $bcc = $copyTo;
            }
            $store = $this->_storeManager->getStore($storeId);
            $identity = $this->rmaDataHelper->getIdentity($config , $storeId);


            foreach ($sendTo as $recipient) {
                $this->_transportBuilder
                    ->setTemplateIdentifier($template)
                    ->setTemplateOptions(['area' => Area::AREA_FRONTEND, 'store' => $storeId])
                    ->setTemplateVars(
                        [
                            'rma'                      => $rma,
                            'easy_return'              => $rma->getIsEasyReturn(),
                            'rma_id'                   => $rma->getId(),
                            'rma_data'                 => [
                                'status_label' => is_string($rma->getStatusLabel()) ?
                                    $rma->getStatusLabel() : $rma->getStatusLabel()->render(),
                            ],
                            'order'                    => $order,
                            'order_data'               => [
                                'customer_name' => $order->getCustomerName(),
                            ],
                            'created_at_formatted_1'   => $rma->getCreatedAtFormated(1),
                            'store'                    => $store,
                            'return_address'           => $returnAddress,
                            'item_collection'          => $rma->getItems(),
                            'formattedShippingAddress' => $this->addressRenderer->format(
                                $order->getShippingAddress(),
                                'html'
                            ),
                            'formattedBillingAddress'  => $this->addressRenderer->format(
                                $order->getBillingAddress(),
                                'html'
                            ),
                            'supportEmail'             => $store->getConfig('trans_email/ident_support/email'),
                            'storePhone'               => $store->getConfig('general/store_information/phone'),
                        ]
                    )
                    ->addTo($recipient['email'], $recipient['name'])
                    ->addBcc($bcc);

                if (method_exists($this->_transportBuilder, 'setFromByScope')) {
                    $this->_transportBuilder->setFromByScope($identity, $storeId);
                } else {
                    $emailFrom = $this->senderResolver->resolve($identity, $storeId);
                    $this->_transportBuilder->setFrom($emailFrom);
                }

                $transport = $this->_transportBuilder->getTransport();
                $transport->sendMessage();
            }

            $this->setEmailSent(true);
        } catch (MailException $exception) {
            $this->_logger->critical($exception->getMessage(), ['exception' => $exception]);
        } catch (Exception $e) {
            $this->_logger->critical($e->getMessage(), ['exception' => $e]);
        } catch (Throwable $t) {
            $this->_logger->critical($t->getMessage(), ['exception' => $t]);
        }

        $this->inlineTranslation->resume();

        return $this;

    }

}
