<?php

namespace FiloBlu\Rma\Helper;

use Exception;
use FiloBlu\Rma\Api\EasyReturnRepositoryInterface;
use FiloBlu\Rma\Model\OrderLocator;
use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Model\AddressFactory;
use Magento\Customer\Model\Vat;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\Rma\Api\Data\RmaInterface;
use Magento\Rma\Model\RmaFactory;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;

/**
 *
 */
class RmaPoliciesHelper extends AbstractHelper
{
    /** @var string */
    const XML_PATH_FIRST_RETURN_POLICY = 'filoblu_disablerma_section/return_creation_policies_first_return/policies';
    /** @var string */
    const XML_PATH_SECONDARY_RETURNS_POLICY = 'filoblu_disablerma_section/return_creation_policies_by_second_return/policies';
    /** @var string */
    const XML_PATH_POLICIES_CHECK_ENABLED = 'filoblu_disablerma_section/return_creation_policies_general_settings/active';
    /** @var string */
    const XML_PATH_RMA_STATUSES_TO_SKIP = 'filoblu_disablerma_section/return_creation_policies_general_settings/rma_status_to_skip_for_existing_rma_count';

    const XML_PATH_RMA_ITEM_REASON_POLICY = 'filoblu_disablerma_section/return_creation_policies_by_item_reason/policies';

    /**
     * @var OrderRepositoryInterface
     */
    protected $orderRepository;
    /**
     * @var Vat
     */
    protected $customerVat;
    /**
     * @var RmaHelper
     */
    protected $rmaHelper;
    /**
     * @var EasyReturnHelper
     */
    protected $easyReturnHelper;
    /**
     * @var CustomerRepositoryInterface
     */
    protected $customer;
    /**
     * @var Context
     */
    protected $context;
    /**
     * @var AddressFactory
     */
    protected $addressFactory;
    /**
     * @var RmaFactory
     */
    protected $rmaFactory;
    /**
     * @var StoreManagerInterface
     */
    protected $storeManager;
    /**
     * @var EasyReturnRepositoryInterface
     */
    protected $easyReturnRepository;
    /**
     * @var Json
     */
    protected $serializer;
    /**
     * @var \Psr\Log\LoggerInterface
     */
    private $logger;
    /**
     * @var \Magento\Framework\App\ResourceConnection
     */
    private $resourceConnection;
    /**
     * @var OrderLocator
     */
    private $orderLocator;

    /**
     * @param Context $context
     * @param OrderRepositoryInterface $orderRepository
     * @param Vat $customerVat
     * @param RmaHelper $rmaHelper
     * @param EasyReturnHelper $easyReturnHelper
     * @param CustomerRepositoryInterface $customer
     * @param AddressFactory $addressFactory
     * @param RmaFactory $rmaFactory
     * @param StoreManagerInterface $storeManager
     * @param EasyReturnRepositoryInterface $easyReturnRepository
     * @param Json $serializer
     * @param LoggerInterface $logger
     * @param ResourceConnection $resourceConnection
     * @param OrderLocator $orderLocator
     */
    public function __construct(
        Context $context,
        OrderRepositoryInterface $orderRepository,
        Vat $customerVat,
        RmaHelper $rmaHelper,
        EasyReturnHelper $easyReturnHelper,
        CustomerRepositoryInterface $customer,
        AddressFactory $addressFactory,
        RmaFactory $rmaFactory,
        StoreManagerInterface $storeManager,
        EasyReturnRepositoryInterface $easyReturnRepository,
        Json $serializer,
        LoggerInterface $logger,
        ResourceConnection $resourceConnection,
        OrderLocator $orderLocator
    ) {
        parent::__construct($context);
        $this->orderRepository = $orderRepository;
        $this->customerVat = $customerVat;
        $this->rmaHelper = $rmaHelper;
        $this->easyReturnHelper = $easyReturnHelper;
        $this->customer = $customer;
        $this->context = $context;
        $this->addressFactory = $addressFactory;
        $this->rmaFactory = $rmaFactory;
        $this->storeManager = $storeManager;
        $this->easyReturnRepository = $easyReturnRepository;
        $this->serializer = $serializer;
        $this->logger = $logger;
        $this->resourceConnection = $resourceConnection;
        $this->orderLocator = $orderLocator;
    }

    /**
     * @return array|bool|float|int|string|null
     */
    public function getSecondaryRmaPolicies()
    {
        $policiesJson = $this->scopeConfig->getValue(
            self::XML_PATH_SECONDARY_RETURNS_POLICY,
            ScopeInterface::SCOPE_STORE
        );
        return $this->serializer->unserialize($policiesJson);
    }

    /**
     * @param RmaInterface $rma
     * @return string
     */
    public function check(RmaInterface $rma)
    {
        $rmaType = 'paid_return';

        $order = $this->orderLocator->getCurrentOrder();

        $orderItemIds = array_map(function($item) {
            return $item->getOrderItemId();
        }, $rma->getItems());

        foreach ($order->getItems() as $item) {
            if (in_array($item->getItemId(), $orderItemIds) && $item->getFreeReturnShipping()) {
                return 'free_return';
            }
        }

        if (!$this->isPolicesCheckActive()) {
            return $rmaType;
        }

        $isEasyReturn = $this->easyReturnHelper->isEasyReturn($rma->getEntityId());

        $easyReturn = $this->easyReturnRepository->getByRmaId($rma->getId());
        $easyReturnAmount = $easyReturn->getTheoricShippingAmount();

        if ($isEasyReturn && !(int)$easyReturnAmount) {
            $rmaType = 'free_return';
        }

        return $rmaType;
    }

    /**
     * @param $rma
     * @return bool
     */
    public function isEasyReturn($rma)
    {
        return $this->easyReturnHelper->isEasyReturn($rma->getEntityId());
    }

    /**
     * @param $order
     * @return mixed
     */
    public function getEasyReturnAmountByOrder($order)
    {
        return $this->easyReturnHelper->simulateEasyReturnShippingCost(
            $order->getShippingAddress(),
            $order->getStore(),
            $order->getWeight(),
            $order->getGrandTotal()
        );
    }

    /**
     * @deprecad
     *
     * @param $customerId
     * @return mixed|string|null
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function checkCustomerPolicy($customerId)
    {
        $customer = $this->customer->getById($customerId);

        $firstRmaPolicies = $this->getFirstRmaPolicies();

        foreach ($firstRmaPolicies as $policy) {
            if ($customer->getGroupId() == $policy['customer_group']) {
                return $policy['return_type'];
            }
        }

        return null;
    }

    /**
     * @return array|bool|float|int|string|null
     */
    public function getFirstRmaPolicies()
    {
        $policiesJson = $this->scopeConfig->getValue(self::XML_PATH_FIRST_RETURN_POLICY, ScopeInterface::SCOPE_STORE);

        if (!$policiesJson) {
            return false;
        }

        return $this->serializer->unserialize($policiesJson);
    }

    /**
     * @param $order
     * @return bool
     */
    public function isFirstReturn($order)
    {
        if (!$this->hasOrderOtherRmas($order->getEntityId())) {
            return true;
        }

        return false;
    }

    /**
     * @param $orderId
     * @return int
     */
    public function hasOrderOtherRmas($orderId)
    {
        try {
            $statusesToSkip = $this->getRmaStatusesToSkipFormExistingReturnsCount();

            // Get the RMA collection filtered by the order ID
            $rmaCollection = $this->rmaFactory->create()->getCollection()->addFieldToFilter(
                'order_id',
                $orderId
            )
            ->addFieldToFilter('status', ['in' => $statusesToSkip])
            ->addFieldToFilter('status', ['neq' => 'closed']);

            return $rmaCollection->count() ? 1 : 0;
        } catch (Exception $exception) {
            $this->logger->error($exception->getMessage(), ['exception' => $exception]);
            return 0;
        }
    }

    /**
     * Deprecated
     * @param $orderId
     * @param $easyReturnAmount
     * @return mixed
     */
    public function calculateFirstRmaPolicies($orderId, $easyReturnAmount)
    {
        return $easyReturnAmount;
    }

    /**
     * @param $order
     * @return \Magento\Customer\Api\Data\CustomerInterface
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function getOrderCustomer($order)
    {
        if ($order->getCustomerIsGuest()) {
            return null;
        }

        return $this->customer->getById($order->getCustomerId());
    }

    /**
     * @param OrderInterface $order
     * @return bool
     */
    public function isOrderInEU($order)
    {

        if ($order && $order->getShippingAddress() && $order->getShippingAddress()->getCountryId()) {
            return $this->customerVat->isCountryInEU($order->getShippingAddress()->getCountryId(), $order->getStoreId());
        }

        //Fallback
        if ($order && $order->getBillingAddress() && $order->getBillingAddress()->getCountryId()) {
            return $this->customerVat->isCountryInEU($order->getBillingAddress()->getCountryId(), $order->getStoreId());
        }

        return false;
    }

    /**
     * Deprecated
     * @param $customer
     * @param $order
     * @return string|null
     */
    public function getCustomerCountryId($customer, $order)
    {
        if (!empty($customer)) {
            $addressId = $customer->getDefaultShipping();
            $address = $this->addressFactory->create()->load($addressId);
        } else {
            $address = $order->getShippingAddress();
        }

        if (!$address->getEntityId()) {
            return null;
        }

        return $address->getCountryId();
    }

    /**
     * @param $orderItemId
     * @return \Magento\Sales\Api\Data\OrderInterface
     * @throws \Magento\Framework\Exception\InputException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function getOrderByItemId($orderItemId): OrderInterface
    {
        $connection = $this->resourceConnection->getConnection();
        $orderId = $connection->fetchOne(
            $connection->select()->from($connection->getTableName('sales_order_item'), ['order_id'])->where(
                'item_id = ? ',
                $orderItemId
            )
        );

        return $this->getOrderById($orderId);
    }

    /**
     * @param $orderId
     * @return \Magento\Sales\Api\Data\OrderInterface
     * @noinspection PhpDocRedundantThrowsInspection
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     * @throws \Magento\Framework\Exception\InputException
     */
    public function getOrderById($orderId): OrderInterface
    {
        return $this->orderRepository->get($orderId);
    }

    /**
     * @return bool
     */
    public function isPolicesCheckActive(): bool
    {
        return $this->scopeConfig->isSetFlag(self::XML_PATH_POLICIES_CHECK_ENABLED, ScopeInterface::SCOPE_STORES);
    }

    /**
     * @return array
     */
    public function getRmaStatusesToSkipFormExistingReturnsCount(): array
    {
        $statuses = $this->scopeConfig->getValue(self::XML_PATH_RMA_STATUSES_TO_SKIP, ScopeInterface::SCOPE_STORES);

        if (empty($statuses) || !\is_string($statuses)) {
            return ['authorized'];
        }

        return \explode(',', $statuses);
    }

    public function getRmaItemReasonPolicy()
    {
        $policiesJson = $this->scopeConfig->getValue(self::XML_PATH_RMA_ITEM_REASON_POLICY, ScopeInterface::SCOPE_STORE);

        if (!$policiesJson) {
            return false;
        }

        return $this->serializer->unserialize($policiesJson);
    }
}
