<?php

namespace FiloBlu\Storelocator\Model\Plugin\Rma\Source;

use FiloBlu\Storelocator\Helper\Data;
use Magento\Framework\Exception\LocalizedException;
use Magento\Rma\Model\Item\Attribute\Source\StatusFactory;
use Magento\Rma\Model\Rma\Source\Status as StatusAlias;
use Magento\Store\Model\StoreManagerInterface;

class Status
{
    CONST STATE_RECEIVED_IN_STORE = 'return_received_in_store';
    CONST STATE_RECEIVED_IN_STORE_PHRASE = 'Return Received in Store';
    /**
     * @var StatusFactory
     */
    protected $_statusFactory;
    /**
     * @var Data
     */
    protected $helper;
    /**
     * @var StoreManagerInterface
     */
    protected $storeManager;

    /**
     * @param StatusFactory $statusFactory
     * @param Data $helper
     * @param StoreManagerInterface $storeManager
     */
    public function __construct(
        StatusFactory $statusFactory,
        Data $helper,
        StoreManagerInterface $storeManager
    )
    {
        $this->_statusFactory = $statusFactory;
        $this->helper = $helper;
        $this->storeManager = $storeManager;
    }

    /**
     * @param \Magento\Rma\Model\Rma\Source\Status $subject
     * @param $state
     * @return array
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function beforeGetItemLabel(StatusAlias $subject, $state) {

        $storeId = $this->storeManager->getStore()->getId();

        if (!$this->helper->getReturnToStoreEnabled($storeId)) {
            return [$state];
        }

        if ($state == self::STATE_RECEIVED_IN_STORE) {
            return [__(self::STATE_RECEIVED_IN_STORE_PHRASE)];
        }

        return [$state];
    }

    /**
     * @param \Magento\Rma\Model\Rma\Source\Status $subject
     * @param $result
     * @return mixed
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function afterGetAllOptionsForGrid(StatusAlias $subject, $result) {

        $storeId = $this->storeManager->getStore()->getId();

        if (!$this->helper->getReturnToStoreEnabled($storeId)) {
            return $result;
        }

        if (!isset($result[self::STATE_RECEIVED_IN_STORE])) {
            $result[self::STATE_RECEIVED_IN_STORE] = __(self::STATE_RECEIVED_IN_STORE_PHRASE);
        }

        return $result;

    }

    /**
     * @throws LocalizedException
     */
    public function aroundGetStatusByItems(StatusAlias $subject, callable $proceed, $itemStatusArray) {

        $storeId = $this->storeManager->getStore()->getId();

        if (!$this->helper->getReturnToStoreEnabled($storeId)) {
            return $proceed($itemStatusArray);
        }

        if (!is_array($itemStatusArray) || empty($itemStatusArray)) {
            throw new LocalizedException(__('This is the wrong RMA item status.'));
        }

        $itemStatusArray = array_unique($itemStatusArray);

        /** @var \Magento\Rma\Model\Item\Attribute\Source\Status $itemStatusModel */
        $itemStatusModel = $this->_statusFactory->create();

        foreach ($itemStatusArray as $status) {
            if (!$itemStatusModel->checkStatus($status)) {
                throw new LocalizedException(__('This is the wrong RMA item status.'));
            }
        }

        $itemStatusToBits = [
            StatusAlias::STATE_PENDING      => 1,
            StatusAlias::STATE_AUTHORIZED   => 2,
            StatusAlias::STATE_DENIED       => 4,
            StatusAlias::STATE_RECEIVED     => 8,
            StatusAlias::STATE_APPROVED     => 16,
            StatusAlias::STATE_REJECTED     => 32,
            Status::STATE_RECEIVED_IN_STORE => 64
        ];
        $rmaBitMaskStatus = 0;
        foreach ($itemStatusArray as $status) {
            $rmaBitMaskStatus += $itemStatusToBits[$status];
        }

        if ($rmaBitMaskStatus == 1) {
            return StatusAlias::STATE_PENDING;
        } elseif ($rmaBitMaskStatus == 2) {
            return StatusAlias::STATE_AUTHORIZED;
        } elseif ($rmaBitMaskStatus == 4) {
            return StatusAlias::STATE_CLOSED;
        } elseif ($rmaBitMaskStatus == 5) {
            return StatusAlias::STATE_PENDING;
        } elseif ($rmaBitMaskStatus > 2 && $rmaBitMaskStatus < 8) {
            return StatusAlias::STATE_PARTIAL_AUTHORIZED;
        } elseif ($rmaBitMaskStatus == 8) {
            return StatusAlias::STATE_RECEIVED;
        } elseif ($rmaBitMaskStatus >= 9 && $rmaBitMaskStatus <= 15) {
            return StatusAlias::STATE_RECEIVED_ON_ITEM;
        } elseif ($rmaBitMaskStatus == 16) {
            return StatusAlias::STATE_PROCESSED_CLOSED;
        } elseif ($rmaBitMaskStatus == 20) {
            return StatusAlias::STATE_PROCESSED_CLOSED;
        } elseif ($rmaBitMaskStatus >= 17 && $rmaBitMaskStatus <= 31) {
            return StatusAlias::STATE_APPROVED_ON_ITEM;
        } elseif ($rmaBitMaskStatus == 32) {
            return StatusAlias::STATE_CLOSED;
        } elseif ($rmaBitMaskStatus == 36) {
            return StatusAlias::STATE_CLOSED;
        } elseif ($rmaBitMaskStatus >= 33 && $rmaBitMaskStatus <= 47) {
            return StatusAlias::STATE_REJECTED_ON_ITEM;
        } elseif ($rmaBitMaskStatus == 48) {
            return StatusAlias::STATE_PROCESSED_CLOSED;
        } elseif ($rmaBitMaskStatus == 52) {
            return StatusAlias::STATE_PROCESSED_CLOSED;
        } elseif ($rmaBitMaskStatus > 48 && $rmaBitMaskStatus < 64) {
            return StatusAlias::STATE_APPROVED_ON_ITEM;
        } elseif ($rmaBitMaskStatus == 64) {
            return Status::STATE_RECEIVED_IN_STORE;
        }
    }

    /**
     * @param \Magento\Rma\Model\Rma\Source\Status $subject
     * @param $result
     * @param $status
     * @return false|mixed
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function afterGetButtonDisabledStatus(StatusAlias $subject, $result, $status = null) {

        $storeId = $this->storeManager->getStore()->getId();

        if (!$this->helper->getReturnToStoreEnabled($storeId)) {
            return $result;
        }

        if ($status !== self::STATE_RECEIVED_IN_STORE) {
            return $result;
        }

        return false;
    }
}