<?php
declare(strict_types=1);

namespace FiloBlu\Refilo\Model;

use FiloBlu\Refilo\Api\OrderMappingManagementInterface;
use FiloBlu\Refilo\Api\OrderMappingRepositoryInterface;
use FiloBlu\Refilo\Helper\OrderMappingHelper;
use Magento\Framework\Api\FilterBuilder;
use Magento\Framework\Api\Search\FilterGroupBuilder;
use Magento\Framework\Api\SearchCriteriaBuilderFactory;
use Magento\Sales\Api\OrderRepositoryInterface;

/**
 * @class OrderMappingManagement
 * @package FiloBlu\Refilo\Model
 */
class OrderMappingManagement implements OrderMappingManagementInterface
{
    /**
     * @var OrderMappingRepositoryInterface
     */
    private $orderMappingRepository;
    /**
     * @var OrderMappingHelper
     */
    private $orderMappingHelper;
    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;
    /**
     * @var SearchCriteriaBuilderFactory
     */
    private $searchCriteriaBuilderFactory;
    /**
     * @var FilterBuilder
     */
    private $filterBuilder;
    /**
     * @var FilterGroupBuilder
     */
    private $filterGroupBuilder;

    /**
     * @param OrderMappingRepositoryInterface $orderMappingRepository
     * @param OrderMappingHelper $orderMappingHelper
     * @param OrderRepositoryInterface $orderRepository
     * @param SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory
     * @param FilterBuilder $filterBuilder
     * @param FilterGroupBuilder $filterGroupBuilder
     */
    public function __construct(
        OrderMappingRepositoryInterface $orderMappingRepository,
        OrderMappingHelper $orderMappingHelper,
        OrderRepositoryInterface $orderRepository,
        SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory,
        FilterBuilder $filterBuilder,
        FilterGroupBuilder $filterGroupBuilder
    ) {
        $this->orderMappingRepository = $orderMappingRepository;
        $this->orderMappingHelper = $orderMappingHelper;
        $this->orderRepository = $orderRepository;
        $this->searchCriteriaBuilderFactory = $searchCriteriaBuilderFactory;
        $this->filterBuilder = $filterBuilder;
        $this->filterGroupBuilder = $filterGroupBuilder;
    }

    /**
     * @param int $customerId
     * @return array|mixed
     */
    public function getOrderIdByCustomer($customerId)
    {
        if (!$customerId) {
            return [];
        }

        $enabledStore = $this->orderMappingHelper->getEnabledStore();

        return $this->orderMappingRepository->getByCustomerId($customerId, array_keys($enabledStore));
    }

    /**
     * @param \FiloBlu\Refilo\Api\Data\GuestOrderRequestInterface $request
     * @return \Magento\Sales\Api\Data\OrderSearchResultInterface|null
     */
    public function getGuestOrder(\FiloBlu\Refilo\Api\Data\GuestOrderRequestInterface $request)
    {
        if (!$request->getCustomerEmail() || !$request->getIncrementId()) {
            return null;
        }

        $searchCriteriaBuilder = $this->searchCriteriaBuilderFactory->create();

        $searchCriteriaBuilder->setPageSize(1);
        $searchCriteriaBuilder->setCurrentPage(1);

        $searchCriteriaBuilder->addFilter('customer_is_guest', 1);
        $searchCriteriaBuilder->addFilter('customer_email', $request->getCustomerEmail());
        $searchCriteriaBuilder->addFilter('increment_id', $request->getIncrementId());

        $enabledStore = array_keys($this->orderMappingHelper->getEnabledStore());
        $enabledStore[] = $request->getStoreId();
        $searchCriteriaBuilder->addFilter('store_id', $enabledStore, 'in');

        $searchCriteria = $searchCriteriaBuilder->create();

        return $this->orderRepository->getList($searchCriteria);
    }

    /**
     * @param \FiloBlu\Refilo\Api\Data\CustomerOrderRequestInterface $request
     * @return \Magento\Sales\Api\Data\OrderSearchResultInterface|null
     */
    public function getCustomerOrder(\FiloBlu\Refilo\Api\Data\CustomerOrderRequestInterface $request)
    {
        if (!$request->getCustomerId()) {
            return null;
        }

        $searchCriteriaBuilder = $this->searchCriteriaBuilderFactory->create();

        $pageSize = $request->getPageSize() ? $request->getPageSize() : 1;
        $pageNumber = $request->getPageNumber() ? $request->getPageNumber() : 1;
        $searchCriteriaBuilder->setPageSize($pageSize);
        $searchCriteriaBuilder->setCurrentPage($pageNumber);

        $enabledStore = array_keys($this->orderMappingHelper->getEnabledStore());
        $enabledStore[] = $request->getStoreId();
        $searchCriteriaBuilder->addFilter('store_id', $enabledStore, 'in');

        if ($request->getOrderId()) {
            $searchCriteriaBuilder->addFilter('entity_id', $request->getOrderId());
            $searchCriteria = $searchCriteriaBuilder->create();
        } else {
            $searchCriteria = $searchCriteriaBuilder->create();

            $this->filterGroupBuilder->addFilter(
                $this->filterBuilder->setField('customer_id')
                    ->setValue($request->getCustomerId())
                    ->setConditionType('eq')
                    ->create()
            );

            $orderIds = $this->getOrderIdByCustomer($request->getCustomerId());
            if (!empty($orderIds)) {
                $this->filterGroupBuilder->addFilter(
                    $this->filterBuilder->setField('entity_id')
                        ->setValue($orderIds)
                        ->setConditionType('in')
                        ->create()
                );
            }

            $filterGroups = $searchCriteria->getFilterGroups();
            $filterGroups[] = $this->filterGroupBuilder->create();
            $searchCriteria->setFilterGroups($filterGroups);
        }

        return $this->orderRepository->getList($searchCriteria);
    }
}
