<?php

/**
 * Created by PhpStorm.
 * User: jderosa
 * Date: 09/04/20
 * Time: 11.02
 */

namespace FiloBlu\Rma\Helper;

use Exception;
use FiloBlu\Rma\Api\Data\EasyReturnConfigInterface;
use FiloBlu\Rma\Api\EasyReturnRepositoryInterface;
use FiloBlu\Rma\Model\OrderLocator;
use FiloBlu\Rma\Model\Carrier\CarrierRateFactory;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Quote\Model\Quote\Address\RateRequestFactory;
use Magento\Sales\Api\Data\OrderAddressInterface;
use Magento\Sales\Model\Order\ItemRepository;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\ScopeInterface;
use Throwable;

/**
 *
 */
class EasyReturnHelper extends AbstractHelper
{
    /**
     * @var EasyReturnRepositoryInterface
     */
    protected $easyReturnRepository;
    /**
     * @var ChangeSizeAttributeHelper
     */
    protected $changeSizeAttributeHelper;
    /**
     * @var OrderLocator
     */
    protected $orderLocator;
    /**
     * @var Context
     */
    protected $context;

    /**
     * @var RateRequestFactory
     */
    private $rateRequestFactory;

    /**
     * @var \FiloBlu\Rma\Model\Carrier\CarrierRate
     */
    private $easyReturnRateFactory;
    /**
     * @var ItemRepository
     */
    private $orderItemRepository;

    /**
     * @var \FiloBlu\Rma\Model\Carrier\CarrierRate
     */
    private $changeSizeRateFactory;

    private $orderItemsId;

    /**
     * @param RateRequestFactory $rateRequestFactory
     * @param CarrierRateFactory $easyReturnRateFactory
     * @param Context $context
     * @param EasyReturnRepositoryInterface $easyReturnRepository
     * @param ChangeSizeAttributeHelper $changeSizeAttributeHelper
     * @param OrderLocator $orderLocator
     * @param CarrierRateFactory $changeSizeRateFactory
     * @param ItemRepository $orderItemRepository
     */
    public function __construct(
        RateRequestFactory $rateRequestFactory,
        CarrierRateFactory $easyReturnRateFactory,
        Context $context,
        EasyReturnRepositoryInterface $easyReturnRepository,
        ChangeSizeAttributeHelper $changeSizeAttributeHelper,
        OrderLocator $orderLocator,
        CarrierRateFactory $changeSizeRateFactory,
        ItemRepository $orderItemRepository
    ) {
        parent::__construct($context);
        $this->rateRequestFactory = $rateRequestFactory;
        $this->easyReturnRateFactory = $easyReturnRateFactory;
        $this->easyReturnRepository = $easyReturnRepository;
        $this->changeSizeAttributeHelper = $changeSizeAttributeHelper;
        $this->orderLocator = $orderLocator;
        $this->context = $context;
        $this->changeSizeRateFactory = $changeSizeRateFactory;
        $this->orderItemRepository = $orderItemRepository;
    }

    /**
     * @param OrderAddressInterface $address
     * @param StoreInterface $store
     * @param float $weight
     * @param float $orderTotal
     * @param int $taxPercentage
     * @param string $type
     * @param string $returnType
     * @param null $orderId
     * @param null $orderItemsId
     * @return mixed
     */
    public function simulateEasyReturnShippingCost(
        OrderAddressInterface $address,
        StoreInterface $store,
        float $weight,
        float $orderTotal = 0,
        $taxPercentage = 0,
        $type = 'price',
        $returnType = 'easy_return',
        $orderId = null,//refilo only
        $orderItemsId = null
    )
    {
        $shippingAmounts [] = 0.00;

        //MNTFOS-419
        if($orderItemsId){
            $this->setOrderItemsId($orderItemsId);
        }

        //MNTFOS-151
        $order = $this->orderLocator->getCurrentOrder();
        if ($order) {
            $countryId = $order->getShippingAddress()->getCountryId();
        } else {
            $countryId = $address->getCountryId();
        }

        $request = $this->rateRequestFactory->create();
        $request->setDestCountryId($countryId);
        $request->setDestRegionId($address->getRegionId());
        $request->setDestPostcode($address->getPostcode());
        $request->setDestCity($address->getCity());
        $request->setPackageWeight($weight);
        $request->setFreeMethodWeight($weight);
        $request->setPackageQty(1);
        $request->setStoreId($store->getId());
        $request->setWebsiteId($store->getWebsiteId());
        $request->setLimitCarrier(null);
        $request->setFreeShipping(null);

        //Set additional data that will be used for
        $request->setData('order_total', $orderTotal);
        $request->setData('tax_percentage', $taxPercentage);

        //TO DO use strategy pattern

        if ($returnType == 'change_size') {
            $matrixRate = $this->changeSizeRateFactory->create();
        } else {
            $matrixRate = $this->easyReturnRateFactory->create();
        }
        //get rates for the matrixrate request created
        $result = $matrixRate->collectRates($request);
        if ($result) {
            $rates = $result->getAllRates();
            if (!empty($rates)) {
                foreach ($rates as $rate) {
                    $price = $rate->getData($type);
                    if (isset($price) && $price > 0) {
                        $shippingAmounts[] = $price;
                    }
                }
            }
        }
        return max($shippingAmounts);
    }

    /**
     * @param null $storeId
     * @return bool
     */
    public function isEasyReturnEnabled($storeId = null)
    {
        return $this->scopeConfig->isSetFlag(
            EasyReturnConfigInterface::EASY_RETURN_ENABlE_XML_PATH,
            ScopeInterface::SCOPE_STORE,
            $storeId
        );
    }

    /**
     * @param null $storeId
     * @return bool
     */
    public function isForceEasyReturnEnabled($storeId = null)
    {
        return $this->scopeConfig->isSetFlag(
            EasyReturnConfigInterface::FORCE_EASY_RETURN_WHEN_CHANGE_SIZE_ENABlE_XML_PATH,
            ScopeInterface::SCOPE_STORE,
            $storeId
        );
    }

    /**
     * @param $rmaId
     * @return bool
     */
    public function isEasyReturn($rmaId)
    {
        try {
            if ($rmaId) {
                return (bool)$this->easyReturnRepository->getByRmaId($rmaId)->getId();
            }

            return false;
        } catch (Exception $exception) {
            $this->_logger->critical($exception->getMessage(), ['exception' => $exception]);
            return false;
        } catch (Throwable $throwable) {
            $this->_logger->critical($throwable->getMessage(), ['exception' => $throwable]);
            return false;
        }
    }

    /**
     * TODO: Use better approach this is really tme consuming
     * @param $orderItemId
     * @return bool
     * @throws \Magento\Framework\Exception\InputException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function isABundleSku($orderItemId): bool
    {
        $orderItem = $this->orderItemRepository->get($orderItemId);
        $product = $orderItem->getProduct();

        return $product->getTypeId() === 'bundle';
    }

    /**
     * TODO: Use better approach this is really tme consuming
     * @param $orderItemId
     * @return string
     * @throws \Magento\Framework\Exception\InputException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function getBundleSku($orderItemId)
    {
        $orderItem = $this->orderItemRepository->get($orderItemId);
        return $orderItem->getProduct()
                         ->getSku();
    }

    /**
     * @param $bundleSku
     * @param $sku
     * @return string|string[]|null
     */
    public function resolveBundleSkus($bundleSku, $sku)
    {
        $childSku = str_replace($bundleSku, '', $sku);
        $childSku = trim($childSku, '-');

        $skus = explode('-', $childSku);

        if (count($skus) === 1) {
            return array_shift($skus);
        }

        return $skus;
    }

    /**
     * MNTFOS-419
     * @param $orderItemsId
     * @return void
     */
    public function setOrderItemsId($orderItemsId)
    {
        foreach ($orderItemsId as $item){
            $this->orderItemsId[] = $item['order_item_id'];
        }
    }

    /**
     * @return mixed
     */
    public function getOrderItemsId()
    {
        return $this->orderItemsId;
    }
}
