<?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 yii\base\Object;
    use Yii;
    use yii\db\ActiveQuery;
    
    class ProductHelper extends Object
    {
        
        const PRODUCT_TAX_GROUP_ID_TARGET = 20;
        const PRODUCT_TAX_GROUP_ID_YEAR = 21;
        const PRODUCT_TAX_GROUP_ID_SEX = 22;
        
        const PRODUCT_VARIANT_TYPE_COLOR = 1;
        const PRODUCT_VARIANT_TYPE_SIZE = 2;
        
        public static function getCategories()
        {
            return Category::find()
                           ->getTree(); // with('categoryName')->
        }
        
        public static function getBrands()
        {
            return Brand::find(); // ->with('brandName')
        }
        
        /**
         * Return custom filter-option link
         * @var array $filter
         * @var array $options
         * @return array
         */
        public static function getFilterForOption($filter, $key, $value, $remove = false)
        {
            $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;
                    }
                }
            }
            return $result;
        }
        
        public static function addLastProsucts($product_id)
        {
            $last_products = self::getLastProducts();
            if(!in_array($product_id, $last_products)) {
                $last_products[] = intval($product_id);
                if(count($last_products) > 16) {
                    array_shift($last_products);
                }
                Yii::$app->session->set('last_products', $last_products);
            }
        }
        
        public static function getLastProducts($as_object = false)
        {
            $last_products = Yii::$app->session->get('last_products', [ ]);
            if($as_object) {
                $last_products = Product::find()
                                        ->joinWith([ 'variant' ])
                                        ->where([ Product::tableName() . '.product_id' => $last_products ])
                                        ->andWhere([
                                            '!=',
                                            ProductVariant::tableName() . '.status',
                                            1,
                                        ])
                                        ->all();
            }
            return array_reverse($last_products);
        }
        
        public static function getSpecialProducts($type, $count, $sort = NULL)
        {
            switch($type) {
                case 'top':
                    $data = [ 'is_top' => true ];
                    break;
                case 'new':
                    $data = [ 'is_new' => true ];
                    break;
                case 'promo':
                    $data = [ 'akciya' => true ];
                    break;
            }
            return Product::find()
                          ->joinWith('variants')
                          ->where($data)
                          ->andWhere([
                              '!=',
                              ProductVariant::tableName() . '.status',
                              1,
                          ])
                          ->limit($count)/*->orderBy($sort)*/
                          ->all();
        }
        
        public static function getSimilarProducts($product, $count = 10)
        {
            if(!is_object($product)) {
                $product = Product::find()
                                  ->where([ 'product_id' => $product ])
                                  ->with('enabledVariants')
                                  ->one();
            }
            
            if(!$product->properties) {
                return [ ];
            }
            $product_categories = [ ];
            foreach($product->categories as $category) {
                $product_categories[] = $category->category_id;
            }
            $query = Product::find()

                            ->innerJoinWith('variant')
                            ->joinWith('category')
                            ->where([
                                '!=',
                                'product_variant.status',
                                1,
                            ])
                            ->andWhere([ 'product_category.category_id' => $product_categories ]);
            //        $query->andWhere(['>=', 'product_variant.price', $product->enabledVariant->price * 0.7]);
            //        $query->andWhere(['<=', 'product_variant.price', $product->enabledVariant->price * 1.3]);
            foreach($product->properties as $group) {
                $where = [ ];
                foreach($group->_options as $option) {
                    $where[] = $option->tax_option_id;
                }
                if(!$where) {
                    continue;
                }
                $query->innerJoin('product_option to' . $group->tax_group_id, 'to' . $group->tax_group_id . '.product_id = product.product_id');
                $query->andWhere([ 'to' . $group->tax_group_id . '.option_id' => $where ]);
            }
            $query->andWhere([
                '!=',
                'product.product_id',
                $product->product_id,
            ]);
            $query->groupBy('product.product_id');
            $query->limit($count);
            $products = $query
                              ->all();

            return $products;
        }
        
        /**
         * @param ActiveQuery $query
         * @param             $params
         * @param bool        $setPriceLimits
         */
        public static function _setQueryParams(&$query, $params)
        {
            if(!empty( $params[ 'keywords' ] )) {
                if(!is_array($params[ 'keywords' ])) {
                    $params[ 'keywords' ] = [ $params[ 'keywords' ] ];
                }
                foreach($params[ 'keywords' ] as $keyword) {
                    $query->orFilterWhere([
                        'ilike',
                        Product::tableName() . '.name',
                        $keyword,
                    ]);
                    $query->orFilterWhere([
                        'ilike',
                        Brand::tableName() . '.name',
                        $keyword,
                    ]);
                    $query->orFilterWhere([
                        'ilike',
                        Category::tableName() . '.name',
                        $keyword,
                    ]);
                    $query->orFilterWhere([
                        'ilike',
                        ProductVariant::tableName() . '.sku',
                        $keyword,
                    ]);
                }
            }
            
            foreach($params as $key => $param) {
                
                switch($key) {
                    case 'special':
                        foreach($param as $key => $value) {
                            $query->orFilterWhere([ Product::tableName() . '.' . $key => $value ]);
                        }
                        break;
                    case 'brands':
                        $query->andFilterWhere([ Product::tableName() . '.brand_id' => $param ]);
                        break;
                    case 'keywords':
                        break;
                    case 'prices':
                        if($param[ 'min' ] > 0) {
                            $query->andWhere([
                                '>=',
                                ProductVariant::tableName() . '.price',
                                $param[ 'min' ],
                            ]);
                        }
                        if($param[ 'max' ] > 0) {
                            $query->andWhere([
                                '<=',
                                ProductVariant::tableName() . '.price',
                                $param[ 'max' ],
                            ]);
                        }
                        break;
                    default:
                        $query->andWhere(
                            Product::tableName() . '.product_id IN (
                        SELECT DISTINCT products
                        FROM (
                            SELECT product_id AS products FROM product WHERE product_id IN(
                            SELECT product_id FROM  product_option
                                INNER JOIN tax_option ON tax_option.tax_option_id = product_option.option_id
                                INNER JOIN tax_group ON tax_group.tax_group_id = tax_option.tax_group_id
                            WHERE tax_group.alias = \''. $key .'\' AND tax_option.alias IN (\'' . implode('\',\'', $param) . '\'))
                             OR product_id IN (
                              (SELECT product_id AS products
                            FROM product_variant_option
                                INNER JOIN product_variant ON product_variant_option.product_variant_id = product_variant.product_variant_id
                                INNER JOIN tax_option ON tax_option.tax_option_id = product_variant_option.option_id
                                INNER JOIN tax_group ON tax_group.tax_group_id = tax_option.tax_group_id
                     WHERE tax_group.alias = \''. $key .'\' AND tax_option.alias IN (\'' . implode('\',\'', $param) . '\'))
                            )
                            ) AS table_name
                        )'
                        );
                }
                
            }
            
        }

        /**
         * @param ActiveQuery $query
         * @param             $params
         * @param bool        $setPriceLimits
         */
        public static function setCacheQueryParams(&$query, $params)
        {


            foreach($params as $key => $param) {


                    $query->andWhere(
                        Product::tableName() . '.product_id IN (
                    SELECT DISTINCT products
                    FROM (
                        SELECT product_id AS products FROM product WHERE product_id IN(
                        SELECT product_id FROM  product_option
                            INNER JOIN tax_option ON tax_option.tax_option_id = product_option.option_id
                            INNER JOIN tax_group ON tax_group.tax_group_id = tax_option.tax_group_id
                        WHERE tax_group.alias = \''. $key .'\' AND tax_option.alias IN (\'' . implode('\',\'', $param) . '\'))
                         OR product_id IN (
                          (SELECT product_id AS products
                        FROM product_variant_option
                            INNER JOIN product_variant ON product_variant_option.product_variant_id = product_variant.product_variant_id
                            INNER JOIN tax_option ON tax_option.tax_option_id = product_variant_option.option_id
                            INNER JOIN tax_group ON tax_group.tax_group_id = tax_option.tax_group_id
                 WHERE tax_group.alias = \''. $key .'\' AND tax_option.alias IN (\'' . implode('\',\'', $param) . '\'))
                        )
                        ) AS table_name
                    )'
                    );
            }


        }






        public static function productCountQuery($category = NULL, $params, $excludeKeys = [ ])
        {
            $p = [ ];
            foreach($params as $key => $param) {
                if(in_array($key, $excludeKeys)) {
                    $p[ $key ] = $param;
                }
            }
            /** @var ActiveQuery $query */
            if(!empty( $category )) {
                $query = $category->getProducts();
            } else {
                $query = Product::find();
            }
            ProductHelper::_setQueryParams($query, $params);
            $query->select([ 'COUNT(product.product_id)' ]);
            
            return $query;
        }
        
        public static function addLastCategory($category_id) {
            \Yii::$app->session->set('last_category_id', $category_id);
        }
        
        public static function getLastCategory() {
            return \Yii::$app->session->get('last_category_id');
        }
    }