<?php

namespace FiloBlu\Storelocator\Plugin\Api;

use Exception;
use FiloBlu\Storelocator\Helper\Import;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Framework\Translate\Inline\StateInterface;
use Magento\Payment\Helper\Data;
use Magento\Quote\Model\Quote;
use Magento\Quote\Model\QuoteFactory;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Model\Order\Address\Renderer;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;
use Magento\Directory\Model\RegionFactory;

use function strlen;

/**
 *
 */
class OrderManagementInterface
{
    /**
     * @var \FiloBlu\Storelocator\Helper\Data
     */
    protected $helper;
    /**
     * @var \Magento\Quote\Model\QuoteFactory
     */
    protected $quoteFactory;
    /**
     * @var \Magento\Sales\Api\OrderRepositoryInterface
     */
    protected $orderRepository;
    /**
     * @var \Magento\Framework\Mail\Template\TransportBuilder
     */
    protected $transportBuilder;
    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;
    /**
     * @var \Magento\Framework\Translate\Inline\StateInterface
     */
    protected $inlineTranslation;
    /**
     * @var \Magento\Payment\Helper\Data
     */
    protected $paymentHelper;
    /**
     * @var \Magento\Sales\Model\Order\Address\Renderer
     */
    protected $addressRenderer;
    /**
     * @var \Magento\Framework\Stdlib\DateTime\DateTime
     */
    protected $date;
    /**
     * @var \Psr\Log\LoggerInterface
     */
    private $logger;
    /**
     * @var \Magento\Directory\Model\RegionFactory
     */
    private $regionFactory;

    /**
     * @param \FiloBlu\Storelocator\Helper\Import $helper
     * @param \Magento\Quote\Model\QuoteFactory $quoteFactory
     * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
     * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation
     * @param \Magento\Payment\Helper\Data $paymentHelper
     * @param \Magento\Sales\Model\Order\Address\Renderer $addressRenderer
     * @param \Magento\Framework\Stdlib\DateTime\DateTime $date
     * @param \Psr\Log\LoggerInterface $logger
     * @param \Magento\Directory\Model\RegionFactory $regionFactory
     */
    public function __construct(
        Import $helper,
        QuoteFactory $quoteFactory,
        OrderRepositoryInterface $orderRepository,
        TransportBuilder $transportBuilder,
        StoreManagerInterface $storeManager,
        StateInterface $inlineTranslation,
        Data $paymentHelper,
        Renderer $addressRenderer,
        DateTime $date,
        LoggerInterface $logger,
        RegionFactory $regionFactory
    ) {
        $this->helper = $helper;
        $this->quoteFactory = $quoteFactory;
        $this->orderRepository = $orderRepository;
        $this->transportBuilder = $transportBuilder;
        $this->storeManager = $storeManager;
        $this->inlineTranslation = $inlineTranslation;
        $this->paymentHelper = $paymentHelper;
        $this->addressRenderer = $addressRenderer;
        $this->date = $date;
        $this->logger = $logger;
        $this->regionFactory = $regionFactory;
    }

    /**
     * @param \Magento\Sales\Api\OrderManagementInterface $subject
     * @param \Magento\Sales\Api\Data\OrderInterface | \Magento\Sales\Model\Order $order
     * @return \Magento\Sales\Api\Data\OrderInterface|\Magento\Sales\Model\Order
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     * @see \Magento\Sales\Model\Service\OrderService::place
     * @see \Magento\Sales\Api\OrderManagementInterface::place
     *
     */
    public function afterPlace($subject, $order)
    {
        if (!$this->helper->getConfig('carriers/pickupinstore/active')) {
            return $order;
        }

        if (!$order->getQuoteId()) {
            return $order;
        }

        $quote = $this->quoteFactory->create()->load($order->getQuoteId());

        if (!$this->canStorePickUpInformation($quote)) {
            return $order;
        }

        try {
            // Save PickUp Store Information
            $order->setPickupInStoreId($quote->getPickupInStoreId());
            $order->setPickupInStoreEmail($quote->getPickupInStoreEmail());
            $order->setPickupInStoreCode($quote->getPickupInStoreCode());
            $order->setPickupInStoreHash(md5(time()));

            $storeName = $order->getShippingAddress()->getFirstname();
            if(!$this->helper->validateFieldLength('title', $storeName)) {
                $storeName = substr($storeName, 0, $this->helper->getStoreFieldMaxLength('title'));
                $order->getShippingAddress()->setFirstname($storeName);
            }

            // Added check so that sum of firstname and lastname of shipping address does not exceed the configuration set in store_title_length
            $titleLength = $this->helper->getStoreFieldMaxLength('title');
            $nameAndLastnameLength = strlen($storeName) + strlen($order->getShippingAddress()->getLastname());

            if ($nameAndLastnameLength > $titleLength) {
                $lastnameLength = $titleLength - strlen($storeName);

                if ($lastnameLength > 0) {
                    $lastname = substr($order->getShippingAddress()->getLastname(), 0, $lastnameLength);
                } else {
                    $lastname = $storeName[$titleLength - 1];
                    if ($lastname === ' ') {
                        $lastname = substr($order->getShippingAddress()->getLastname(), 0, 1);
                    }
                    $storeName = substr($storeName, 0, $titleLength - 1);
                    $order->getShippingAddress()->setFirstname($storeName);
                }

                $order->getShippingAddress()->setLastname($lastname);
            }

            $storeStreet = $order->getShippingAddress()->getStreet();
            if(!$this->helper->validateFieldLength('street', $storeStreet)) {
                $storeStreet = substr($storeStreet[0], 0, $this->helper->getStoreFieldMaxLength('street'));
                $order->getShippingAddress()->setStreet($storeStreet);
            }

            $storeRegion = $order->getShippingAddress()->getRegion();
            if(!$this->helper->validateFieldLength('region_code', $storeRegion) && $order->getShippingAddress()->getRegionId()) {
                $shippingRegion = $this->reFormatRegion($order->getShippingAddress()->getRegionId());
                $order->getShippingAddress()->setRegion($shippingRegion);
            }

            $this->orderRepository->save($order);
        } catch (Exception $exception) {
            $this->logger->error($exception->getMessage(), ['exception' => $exception]);
        }

        return $order;
    }

    /**
     * @param Quote | \Magento\Quote\Api\Data\CartInterface $quote
     * @return bool
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function canStorePickUpInformation($quote): bool
    {
        if (!$quote || !$quote->getId()) {
            return false;
        }

        if (!$quote->getPickupInStoreId() && !$quote->getPickupInStoreCode()) {
            return false;
        }

        if($this->helper->getConfig(
                'carriers/pickupinstore/email_to_store_enabled',
                $quote->getStoreId()
            ) && !$quote->getPickupInStoreEmail())
        {
            return false;
        }

        if (!$quote->getShippingAddress()) {
            return false;
        }

        if ($quote->getShippingAddress()->getShippingMethod() !== 'pickupinstore_pickupinstore') {
            return false;
        }

        return true;
    }

    protected function reFormatRegion($regionId) {
        return $this->regionFactory->create()->load($regionId)->getCode();
    }
}
