<?php

namespace FiloBlu\ActiveCampaign\Model\Entity\Export;

use Exception;
use FiloBlu\ActiveCampaign\Api\Data\JobsInterface;
use FiloBlu\ActiveCampaign\Api\Data\JobsInterfaceFactory;
use FiloBlu\ActiveCampaign\Api\JobsRepositoryInterface;
use FiloBlu\ActiveCampaign\Helper\Data;
use FiloBlu\ActiveCampaign\Model\Config\Source\DirectionType;
use FiloBlu\ActiveCampaign\Model\Config\Source\EntityType;
use FiloBlu\ActiveCampaign\Model\Config\Source\JobStatus;
use FiloBlu\ActiveCampaign\Model\Resource\ActiveCampaign;
use Magento\Framework\App\ResourceConnection;
use Magento\Sales\Api\OrderRepositoryInterface;

/**
 * Class Order
 * @package FiloBlu\ActiveCampaign\Model\Entity\Export
 */
class Order extends AbstractEntityExport {

    /**
     * @var ResourceConnection
     */
    protected $resourceConnection;
    /**
     * @var Data
     */
    protected $helperData;
    /**
     * @var JobsRepositoryInterface
     */
    protected $jobsRepository;
    /**
     * @var string
     */
    protected $entity = EntityType::ENTITY_ORDER;
    /**
     * @var string
     */
    protected $direction = DirectionType::DIRECTION_EXPORT;
    /**
     * @var OrderRepositoryInterface
     */
    protected $orderRepository;

    /**
     * Order constructor.
     * @param ResourceConnection $resourceConnection
     * @param Data $helperData
     * @param JobsRepositoryInterface $jobsRepository
     * @param JobsInterfaceFactory $jobsFactory
     * @param ActiveCampaign $activeCampaign
     * @param OrderRepositoryInterface $orderRepository
     */
    public function __construct(
        ResourceConnection $resourceConnection,
        Data $helperData,
        JobsRepositoryInterface $jobsRepository,
        JobsInterfaceFactory $jobsFactory,
        ActiveCampaign $activeCampaign,
        OrderRepositoryInterface $orderRepository
    )
    {
        parent::__construct($resourceConnection, $helperData, $jobsRepository, $jobsFactory, $activeCampaign);
        $this->orderRepository = $orderRepository;
    }

    /**
     * @return array|mixed
     */
    public function getAllIncrementalIds()
    {
        if(!$this->helperData->isOrderEnabled()) {
            return [];
        }
        $connection = $this->resourceConnection->getConnection();
        $tableName = $this->resourceConnection->getTableName('sales_order');
        $tableNameJobs = $this->resourceConnection->getTableName(JobsInterface::DB_TABLE);

        $order_statuses = explode(',', $this->helperData->getOrderStatuses());
        $os = "";
        foreach ($order_statuses as $order_status) {
            $os .= "'" . $order_status . "',";
        }
        $os = rtrim($os, ',');

        if (empty($sw = $this->helperData->getEnabledStoreViews())) {
            return [];
        }

        $sql = "SELECT
                  ce.entity_id as entity_id
                FROM
                  " . $tableName . " AS ce
                LEFT JOIN
                  " . $tableNameJobs . " AS mj
                ON
                  mj.entity_id = ce.entity_id
                AND
                  mj.entity = ?
                AND
                  mj.direction = ?
                WHERE
                  mj.status is null
                AND
                  ce.status IN (" . $os . ")
                AND
                  FIND_IN_SET(ce.store_id, ?) > 0";

        return $connection->fetchCol($sql, [$this->entity, $this->direction, $sw]);
    }

    /**
     * @param array $job
     * @return bool
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function executeProcess(array $job): bool
    {
        if(!$this->helperData->isOrderEnabled()) {
            $this->jobsRepository->setStatus($this->options,$job['entity_id'],JobStatus::JOB_STATUS_SKIPPED,'The order job is not active');
            return false;
        }
        $orderData = $this->getOrderData($job);
        if(count($orderData)>0){
            $this->executeSalesRestProcess($orderData, $job);
            return true;
        }
        return false;
    }

    /**
     * @param $job
     * @return array[]
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function getOrderData($job) {
        $data = [];
        $order = $this->orderRepository->get($job['entity_id']);
        $order_statuses = explode(',', $this->helperData->getOrderStatuses());
        if(!in_array($order->getStatus(),$order_statuses)){
            $this->jobsRepository->setStatus($this->options,$job['entity_id'],JobStatus::JOB_STATUS_SKIPPED,'The status of the order is not in: '.$this->helperData->getOrderStatuses());
            return [];
        }
        $result = [
            'ecomOrder' => [
                'externalid' => $order->getEntityId(),
                'source' => 1,
                'email' => $order->getCustomerEmail(),
                'externalCreatedDate' => $order->getCreatedAt(),
                'externalUpdatedDate' => $order->getUpdatedAt(),
                'shippingMethod' => $order->getShippingDescription(),
                'totalPrice' => $this->helperData->formatPrice($order->getGrandTotal()),
                'shippingAmount' => (float)$this->helperData->formatPrice($order->getShippingAmount()) + (float)$this->helperData->formatPrice($order->getShippingTaxAmount()),
                'taxAmount' => $this->helperData->formatPrice($order->getTaxAmount()),
                'discountAmount' => abs($this->helperData->formatPrice($order->getDiscountAmount())),
                'currency' => $order->getOrderCurrencyCode(),
                'orderNumber' => $order->getIncrementId(),
                'connectionid' => $this->helperData->getConnectionId(),
                'customerid' => $order->getCustomerId()
            ]
        ];

        //Put coupon if exists
        if(!empty($order->getCouponCode())){
            $result['ecomOrder']['orderDiscounts'] = [
                [
                    'name' => $order->getCouponCode(),
                    'type' => "order",
                    'discountAmount' => abs($this->helperData->formatPrice($order->getDiscountAmount()))
                ]
            ];
        }
        $itemsMapping = $this->helperData->getItemsExtraAttributesMapping();
        foreach ($order->getItems() as $item) {
            $product = $item->getProduct();
            $storeUrl = $this->helperData->getMediaUrl($order->getStoreId());
            $productUrl = $this->helperData->getProductUrl($product,$order->getStoreId());

            $thumbnail = '';
            if(!empty($product->getThumbnail())){
                $thumbnail = ($product->getThumbnail() === 'no_selection') ? '' :  $storeUrl . 'catalog/product' . $product->getThumbnail();
            }
            $itemPrice = $item->getPriceInclTax();

            if($this->helperData->orderExportOnlySimple()) {
                if(in_array($product->getTypeId(), ['configurable','bundle'])){
                    continue;
                }
                //If export only simple get info from parent
                if (!empty($item->getParentItemId()) && $item->getParentItem()->getProductType()=="configurable") {
                    $itemPrice = $item->getParentItem()->getPriceInclTax();
                    if(empty($thumbnail)) {
                        $parentProduct = $this->helperData->getProduct($item->getParentItem()->getProductId());
                        if(!empty($parentProduct->getThumbnail())){
                            $thumbnail = ($parentProduct->getThumbnail() === 'no_selection') ? '' :  $storeUrl . 'catalog/product' . $parentProduct->getThumbnail();
                        }
                    }
                }
            }

            //TODO:: manage bundle
            $data[] = [
                'name' => mb_convert_encoding($item->getName(), 'UTF-8', mb_detect_encoding($item->getName())),
                'price' => $this->helperData->formatPrice($itemPrice),
                'quantity' => $item->getQtyOrdered(),
                'external_id' => $item->getProductId(),
                'sku' => $item->getSku(),
                'description' => $product->getDescription(),
                'productUrl' => $productUrl,
                'imageUrl' => $thumbnail,
                'category' => $this->helperData->getCategory($product)           ];

            $extraData = [];
            foreach ($itemsMapping as $magentoField => $acField) {
                $extraData = [$acField => $this->helperData->getEavAttribute($product, $magentoField)];
            }

            $mergedArray = array_merge(end($data), $extraData);
            $data[count($data)-1] = $mergedArray;
        }

        $result['ecomOrder']['orderProducts'] = $data;
        return $result;
    }

}
