<?php

namespace common\modules\product\helpers;


use common\modules\product\models\Brand;
use common\modules\product\models\Category;
use common\modules\product\models\Product;
use common\modules\product\models\ProductVariant;
use common\modules\rubrication\models\TaxGroup;
use yii\base\Object;
use Yii;
use yii\db\Query;
use yii\db\QueryInterface;
use yii\db\ActiveQuery;
use yii\helpers\ArrayHelper;

class FilterHelper extends Object {

    public static $optionsList;

    public static function optionsTemplate(){
        if(empty(static::$optionsList)){
            return static::$optionsList = ArrayHelper::getColumn(TaxGroup::find()->where(['is_filter' => 'TRUE'])->all(),'alias');
        }
        else
        {
            return static::$optionsList;
        }

    }

    /**
     * Return custom filter-option link
     * @var array $filter
     * @var array $options
     * @return array
     */
    public static function getFilterForOption($filter, $key, $value, $remove = false) {

        $optionsTemplate = self::optionsTemplate();
        array_unshift($optionsTemplate, "special", "brands");

        $result = $filter;

        if (is_array($value)) {
            foreach($value as $value_key => $value_items) {
                if (!is_array($value_items)) {
                    $value_items = [$value_items];
                }
                foreach($value_items as $value_item) {
                    if ($remove && isset($result[$key]) && ($i = array_search($value_item, $result[$key][$value_key])) !== FALSE) {
                        unset($result[$key][$value_key][$i]);
                        if (empty($result[$key][$value_key])) {
                            unset($result[$key][$value_key]);
                        }
                    } else {
                        if (!isset($result[$key][$value_key]) || array_search($value_item, $result[$key][$value_key]) === FALSE) {
                            $result[$key][$value_key][] = $value_item;
                        }
                    }
                }
            }
        } else {
            if ($remove && isset($result[$key]) && ($i = array_search($value, $result[$key])) !== FALSE) {
                unset($result[$key][$i]);
                if (empty($result[$key])) {
                    unset($result[$key]);
                }
            } else {
                if (!isset($result[$key]) || array_search($value, $result[$key]) === FALSE) {
                    $result[$key][] = $value;
                }
            }
        }


        $filterView = [];

        foreach($optionsTemplate as $optionKey){
            if(isset($result[$optionKey])){
                $filterView[$optionKey] = $result[$optionKey];
            }


        }

        return $filterView;
    }



    /**
     * @param ActiveQuery $query
     * @param array       $params
     */
    public static function setNewQueryParams($query, $params)
    {
        $last_query = null;
        foreach ($params as $key => $param) {
            switch ($key) {
                case 'special':
                    self::filterSpecial($param, $query);
                    break;
                case 'brands':
                    self::filterBrands($param, $query);
                    break;
                case 'keywords':
                    self::filterKeywords($param, $query);
                    break;
                case 'prices':
                    self::filterPrices($param, $query);
                    break;
                default:
                    $last_query = self::filterOptions($param, $last_query);
                    break;
            }
        }
        if(!empty($last_query)) {
            $query->andWhere(['product.product_id' => $last_query]);
        }
    }

    private static function filterOptions(array $params, Query $last_query = null)
    {
        $variant_query = ( new Query() )->distinct()
            ->select('product_variant.product_id as products')
            ->from('product_variant_option')
            ->innerJoin(
                'product_variant',
                'product_variant_option.product_variant_id = product_variant.product_variant_id'
            )
            ->innerJoin('tax_option', 'tax_option.tax_option_id = product_variant_option.option_id')
            ->where([ 'tax_option.alias' => $params ]);
        $product_query = ( new Query() )->distinct()
            ->select('product_option.product_id as products')
            ->from('product_option')
            ->innerJoin('tax_option', 'product_option.option_id = tax_option.tax_option_id')
            ->where(
                [ 'tax_option.alias' => $params ]
            )->union($variant_query);
        $query = (new Query())->select('products')->from(['result_table' => $product_query]);
        if (!empty( $last_query )) {
            $query->andWhere([ 'product.product_id' => $last_query ]);
        }
        return $query;
    }

    private static function filterSpecial(array $params, ActiveQuery $query)
    {
        $conditions = [];
        /**
         * @var string $key
         */
        foreach ($params as $key => $param) {
            $conditions[] = [
                '=',
                Product::tableName() . '.' . $key,
                $param,
            ];
        }
        /* If 2 or more special conditions get all that satisfy at least one of them. */
        if (count($conditions) > 1) {
            array_unshift($conditions, 'or');
        } else {
            $conditions = $conditions[ 0 ];
        }
        $query->andFilterWhere($conditions);
    }

    private static function filterBrands(array $param, ActiveQuery $query)
    {
        $query->andFilterWhere([ Product::tableName() . '.brand_id' => $param ]);
    }

    private static function filterKeywords(array $params, ActiveQuery $query)
    {
        $conditions = [];
        if (!empty( $params )) {
            if (!is_array($params)) {
                $params = [ $params ];
            }
            /**
             * @var string $param Inputed keyword
             */
            foreach ($params as $param) {
                $conditions[] = [
                    'or',
                    [
                        'ilike',
                        Product::tableName() . '.name',
                        $param,
                    ],
                    [
                        'ilike',
                        Brand::tableName() . '.name',
                        $param,
                    ],
                    [
                        'ilike',
                        Category::tableName() . '.name',
                        $param,
                    ],
                    [
                        'ilike',
                        ProductVariant::tableName() . '.sku',
                        $param,
                    ],
                ];
            }
        }
        if (count($conditions) > 1) {
            array_unshift($conditions, 'or');
        } else {
            $conditions = $conditions[ 0 ];
        }
        $query->andFilterWhere($conditions);
    }

    private static function filterPrices(array $params, ActiveQuery $query)
    {
        $conditions = [];
        if (!empty( $params[ 'min' ] ) && $params[ 'min' ] > 0) {
            $conditions[] = [
                '>=',
                ProductVariant::tableName() . '.price',
                $params[ 'min' ],
            ];
        }
        if (!empty( $params[ 'max' ] ) && $params[ 'max' ] > 0) {
            $conditions[] = [
                '<=',
                ProductVariant::tableName() . '.price',
                $params[ 'max' ],
            ];
        }
        if (count($conditions) > 1) {
            array_unshift($conditions, 'and');
        } else {
            $conditions = $conditions[ 0 ];
        }
        $query->andFilterWhere($conditions);
    }


}