<?php

namespace KupShop\AutomationConfiguratorBundle\Configurator\Orders\Conditions\Fields;

use KupShop\AutomationConfiguratorBundle\Configurator\Interfaces\Conditions\Fields\Field;
use KupShop\AutomationConfiguratorBundle\Configurator\Orders\OrdersContext;
use KupShop\AutomationConfiguratorBundle\Util\ExpressionContext;
use Query\Operator;
use Query\QueryBuilder;

class OrderItemsInStock extends Field implements OrdersContext
{
    public function getConfig(): array
    {
        return [
            'label' => 'Objednávka má položky skladem',
            'type' => 'boolean',
            'tooltip' => 'Vybere všechny aktivní objednávky, které mají všechny položky skladem. Bere v potaz webovou skladovost na detailu produktu.',
        ];
    }

    public function getName(): string
    {
        return 'order_items_in_stock';
    }

    public function getGroupName(): ?string
    {
        return 'products';
    }

    public function getCompareValue(ExpressionContext $context, $args = null)
    {
        $context = $context->getContext();

        return $context['order_items_min_in_stock'] >= 0;
    }

    /**
     * @param QueryBuilder $context
     */
    public function modifyPrefetchFastCondition($context, $jsonValue)
    {
        $value = $this->prefetchUtil->getBooleanValue($jsonValue);

        if ($value) {
            $context->andWhere('oiis.min_in_store >=0');
        } else {
            $context->andWhere('oiis.min_in_store < 0');
        }

        return $context;
    }

    /**
     * @param QueryBuilder $context
     *
     * @return void
     */
    public function modifyPrefetchOnUse($context)
    {
        $context->leftJoinSubQuery('o', $this->getOrderQueryBuilder(), 'oiis', 'o.id = oiis.id')
            ->addSelect('oiis.min_in_store AS order_items_min_in_stock');
    }

    protected function getBaseQueryBuilder()
    {
        return sqlQueryBuilder()
            ->from('orders', 'o')
            ->leftJoin('o', 'order_items', 'oi', 'oi.id_order=o.id')
            ->leftJoin('oi', 'products', 'p', 'oi.id_product=p.id')
            ->leftjoin('oi', 'products_variations', 'pv', 'pv.id=oi.id_variation')
            ->andWhere("NOT COALESCE(JSON_CONTAINS(oi.note, '\"return\"', '$.item_type'), FALSE)")
            ->groupBy('o.id');
    }

    protected function getOrderCountQueryBuilder()
    {
        return sqlQueryBuilder()->select('SUM(oi2.pieces)')
            ->from('order_items', 'oi2')
            ->leftJoin('oi2', 'orders', 'o2', 'oi2.id_order=o2.id')
            ->where('oi2.id_product=p.id AND o2.date_created >= o.date_created AND o2.status_storno=0 AND ((oi2.id_variation IS NULL AND oi.id_variation IS NULL) OR oi.id_variation=oi2.id_variation)')
            ->andWhere(Operator::inIntArray($this->getFromStatuses(), 'o2.status'))
            ->andWhere("NOT COALESCE(JSON_CONTAINS(oi2.note, '\"return\"', '$.item_type'), FALSE)");
    }

    protected function getOrderQueryBuilder()
    {
        $orderCount = $this->getOrderCountQueryBuilder();

        return $this->getBaseQueryBuilder()
            ->select('o.id,
            MIN(COALESCE(pv.in_store, p.in_store) - oi.pieces + ('.$orderCount->getSQL().')) as min_in_store')
            ->andWhere('o.status_storno=0')
            ->andWhere(Operator::inIntArray($this->getFromStatuses(), 'o.status'))
//            ->andWhere('o.total_price > 0')
//            ->andWhere(Operator::not(Operator::findInSet(['R'], 'o.flags')))
//            ->andWhere(Operator::orX('o.status_payed = 1', Order::byPaymentMethods(['METHOD_COD'])))
//            ->having('min_in_store >= 0')
            ->addParameters($orderCount->getParameters(), $orderCount->getParameterTypes());
    }

    protected function getFromStatuses()
    {
        return getStatuses('active');
    }
}
