<?php

namespace ArtabanMarketplace\Model;

use ArtabanMarketplace\Model\Base\AmpSellerOrder as BaseAmpSellerOrder;
use ArtabanMarketplace\Model\AmpSellerOrderProductQuery;
use ArtabanMarketplace\Model\Map\AmpSellerOrderProductTableMap;
use ArtabanMarketplace\Model\Map\AmpSellerOrderOrderProductTaxTableMap;
use ArtabanMarketplace\Model\Map\AmpSellerOrderTableMap;
use Thelia\Model\Map\OrderProductTaxTableMap;
use Thelia\Model\Map\OrderProductTableMap;
use Thelia\Model\OrderProductQuery;
use Propel\Runtime\ActiveQuery\Join;
use Propel\Runtime\ActiveQuery\Criteria;
use ArtabanMarketplace\Model\AmpSellerOrderStatus;

class AmpSellerOrder extends BaseAmpSellerOrder {

    /**
     * Compute this order amount.
     *
     * The order amount is only available once the order is persisted in database.
     * During invoice process, use all cart methods instead of order methods (the order doest not exists at this moment)
     *
     * @param  int $sellerOrderId
     * @return float
     */
    public function getAmountTax(int $sellerOrderId, int $orderId) {

        $orderProductIdsString = AmpSellerOrderQuery::create()
                ->filterById($sellerOrderId)
                ->select(['order_product_id'])
                ->findOne();

        $orderInfo = OrderProductQuery::create()
                ->filterByOrderId($orderId)
                ->leftJoinOrderProductTax()
                ->withColumn('SUM(
                ' . OrderProductTableMap::QUANTITY . '
                * IF(' . OrderProductTableMap::WAS_IN_PROMO . ' = 1, ' . OrderProductTaxTableMap::PROMO_AMOUNT . ', ' . OrderProductTaxTableMap::AMOUNT . ')
            )', 'total_tax')
                ->withColumn('SUM(
                ' . OrderProductTableMap::QUANTITY . '
                * IF(' . OrderProductTableMap::WAS_IN_PROMO . ' = 1, ' . OrderProductTableMap::PROMO_PRICE . ', ' . OrderProductTableMap::PRICE . ')
            )', 'total_amount')
                ->where(OrderProductTableMap::ID . " " . Criteria::IN . " (" . $orderProductIdsString . ")")
                ->select(['total_tax', 'total_amount'])
                ->findOne();

        return $orderInfo;
    }

    /**
     * Compute this order weight.
     *
     * The order weight is only available once the order is persisted in database.
     * During invoice process, use all cart methods instead of order methods (the order doest not exists at this moment)
     *
     * @return float
     */
    public function getWeight(int $sellerOrderId, int $orderId) {

        $orderProductIdsString = AmpSellerOrderQuery::create()
                ->filterById($sellerOrderId)
                ->select(['order_product_id'])
                ->findOne();

        $orderProductArray = OrderProductQuery::create()
                ->filterByOrderId($orderId)
                ->where(OrderProductTableMap::ID . " " . Criteria::IN . " (" . $orderProductIdsString . ")")
                ->find();

        $weight = 0;

        /* browse all products */
        foreach ($orderProductArray as $orderProduct) {
            $weight += $orderProduct->getQuantity() * (double) $orderProduct->getWeight();
        }

        return $weight;
    }

    /**
     * Return the postage without tax
     * @return float|int
     */
    public function getUntaxedPostage() {
        if (0 < $this->getPostageTax()) {
            $untaxedPostage = round($this->getPostage() - $this->getPostageTax(), 2);
        } else {
            $untaxedPostage = $this->getPostage();
        }

        return $untaxedPostage;
    }

    /**
     * Set the status of the current order to NOT PAID
     */
    public function setNotPaid() {
        $this->setStatusHelper(AmpSellerOrderStatus::CODE_NOT_PAID);
    }

    /**
     * Check if the current status of this order is NOT PAID
     *
     * @return bool true if this order is NOT PAID, false otherwise.
     */
    public function isNotPaid() {
        return $this->hasStatusHelper(AmpSellerOrderStatus::CODE_NOT_PAID);
    }

    /**
     * Set the status of the current order to PAID
     */
    public function setPaid() {
        $this->setStatusHelper(AmpSellerOrderStatus::CODE_PAID);
    }

    /**
     * Check if the current status of this order is PAID
     *
     * @param bool $exact if true, the method will check if the current status is exactly OrderStatus::CODE_PAID.
     * if false, it will check if the order has been paid, whatever the current status is. The default is true.
     * @return bool true if this order is PAID, false otherwise.
     */
    public function isPaid($exact = true) {
        return $this->hasStatusHelper(
                        $exact ?
                        AmpSellerOrderStatus::CODE_PAID :
                        [AmpSellerOrderStatus::CODE_PAID, AmpSellerOrderStatus::CODE_PROCESSING, AmpSellerOrderStatus::CODE_SENT]
        );
    }

    /**
     * Set the status of the current order to PROCESSING
     */
    public function setProcessing() {
        $this->setStatusHelper(AmpSellerOrderStatus::CODE_PROCESSING);
    }

    /**
     * Check if the current status of this order is PROCESSING
     *
     * @return bool true if this order is PROCESSING, false otherwise.
     */
    public function isProcessing() {
        return $this->hasStatusHelper(AmpSellerOrderStatus::CODE_PROCESSING);
    }

    /**
     * Set the status of the current order to SENT
     */
    public function setSent() {
        $this->setStatusHelper(AmpSellerOrderStatus::CODE_SENT);
    }

    /**
     * Check if the current status of this order is SENT
     *
     * @return bool true if this order is SENT, false otherwise.
     */
    public function isSent() {
        return $this->hasStatusHelper(AmpSellerOrderStatus::CODE_SENT);
    }

    /**
     * Set the status of the current order to CANCELED
     */
    public function setCancelled() {
        $this->setStatusHelper(AmpSellerOrderStatus::CODE_CANCELED);
    }

    /**
     * Check if the current status of this order is CANCELED
     *
     * @return bool true if this order is CANCELED, false otherwise.
     */
    public function isCancelled() {
        return $this->hasStatusHelper(AmpSellerOrderStatus::CODE_CANCELED);
    }

    /**
     * Set the status of the current order to REFUNDED
     */
    public function setRefunded() {
        $this->setStatusHelper(AmpSellerOrderStatus::CODE_REFUNDED);
    }

    /**
     * Check if the current status of this order is REFUNDED
     *
     * @return bool true if this order is REFUNDED, false otherwise.
     */
    public function isRefunded() {
        return $this->hasStatusHelper(AmpSellerOrderStatus::CODE_REFUNDED);
    }

    /**
     * Set the status of the current order to the provided status
     *
     * @param string $statusCode the status code, one of OrderStatus::CODE_xxx constants.
     */
    public function setStatusHelper($statusCode) {
        if (null !== $ordeStatus = AmpSellerOrderStatusQuery::create()->findOneByCode($statusCode)) {
            $this->setOrderStatus($ordeStatus)->save();
        }
    }

    /**
     * Check if the current status of this order is $statusCode or, if $statusCode is an array, if the current
     * status is in the $statusCode array.
     *
     * @param  string|array $statusCode the status code, one of OrderStatus::CODE_xxx constants.
     * @return bool   true if this order have the provided status, false otherwise.
     */
    public function hasStatusHelper($statusCode) {
        if (is_array($statusCode)) {
            return in_array($this->getAmpSellerOrderStatus()->getCode(), $statusCode);
        } else {
            return $this->getAmpSellerOrderStatus()->getCode() == $statusCode;
        }
    }

}