<?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;
        
        public static function getCategories()
        {
            return Category::find()
                           ->getTree(null, 'lang');
        }
        
        public static function getBrands()
        {
            return Brand::find();
        }
        
        /*
         * 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() . '.stock',
                                            0,
                                        ])
                                        ->all();
            }
            return array_reverse($last_products);
        }
        
        public static function getSpecialProducts($type, $count, $sort = NULL)
        {
            $data = [];
            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() . '.stock',
                              0,
                          ])
                          ->limit($count)
                          ->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()
                            ->select('product.product_id')
                            ->innerJoinWith('variant')
                            ->joinWith('category')
                            ->where([
                                '!=',
                                'product_variant.stock',
                                0,
                            ])
                            ->andWhere([ 'product_category.category_id' => $product_categories ]);
            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->asArray()
                              ->all();
            foreach($products as &$_product) {
                $_product = Product::findOne($_product[ 'product_id' ]);
            }
            return $products;
        }
        
        /**
         * @param ActiveQuery $query
         * @param             $params
         * @param bool        $setPriceLimits
         */
        public static function _setQueryParams(&$query, $params, $setPriceLimits = true)
        {
            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:
                        /**
                         * @todo Refactor this
                         */
                        $query->andWhere(
                            Product::tableName() . '.product_id IN (       
                        SELECT DISTINCT products
                            FROM (
                                SELECT product_id AS products
                                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 LIKE \''. $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 LIKE \''. $key .'\' AND tax_option.alias IN (\'' . implode('\',\'', $param) . '\'))
                                ) 
                                ) AS table_name      
                        )'
                        );
                }
                
            }
            
        }
    
        /**
         * @param null|Category $category
         * @param array         $params
         * @param array         $excludeKeys
         *
         * @return ActiveQuery
         */
        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');
        }
    }