<?php
    
    namespace common\modules\product\models;
    
    use common\behaviors\MultipleImgBehavior;
    use common\behaviors\SaveMultipleFileBehavior;
    use common\modules\language\behaviors\LanguageBehavior;
    use common\modules\rubrication\models\TaxGroup;
    use common\modules\rubrication\models\TaxOption;
    use Yii;
    use yii\db\ActiveQuery;
    use yii\db\ActiveRecord;
    use yii\helpers\ArrayHelper;
    use yii\web\Request;
    
    /**
     * This is the model class for table "product_variant".
     * @todo Refactor
     * @property integer              $product_variant_id
     * @property integer              $product_id
     * @property integer              $remote_id
     * @property string               $sku
     * @property double               $price
     * @property double               $price_old
     * @property double               $stock
     * @property integer              $product_unit_id
     * @property TaxOption[]          $options
     * @property ProductUnit          $productUnit
     * @property Product              $product
     * * From language behavior *
     * @property ProductVariantLang   $lang
     * @property ProductVariantLang[] $langs
     * @property ProductVariantLang   $object_lang
     * @property string               $ownerKey
     * @property string               $langKey
     * @property ProductVariantLang[] $model_langs
     * @property bool                 $transactionStatus
     * @method string           getOwnerKey()
     * @method void             setOwnerKey( string $value )
     * @method string           getLangKey()
     * @method void             setLangKey( string $value )
     * @method ActiveQuery      getLangs()
     * @method ActiveQuery      getLang( integer $language_id )
     * @method ProductVariantLang[]    generateLangs()
     * @method void             loadLangs( Request $request )
     * @method bool             linkLangs()
     * @method bool             saveLangs()
     * @method bool             getTransactionStatus()
     * * End language behavior *
     * * From multipleImage behavior
     * @property ProductImage         $image
     * @property ProductImage[]       $images
     * @method ActiveQuery getImage()
     * @method ActiveQuery getImages()
     * @method array getImagesConfig()
     * @method array getImagesHTML( string $preset )
     * * End multipleImage behavior
     */
    class ProductVariant extends ActiveRecord
    {
        
        public $sum_cost;
        
        public $product_name;
        
        private $_options;
        
        /** @var array $_images */
        public $imagesUpload = [];
        
        /**
         * @inheritdoc
         */
        public static function tableName()
        {
            return 'product_variant';
        }
        
        public function behaviors()
        {
            return [
                'language'      => [
                    'class' => LanguageBehavior::className(),
                ],
                'images'        => [
                    'class'     => SaveMultipleFileBehavior::className(),
                    'name'      => 'imagesUpload',
                    'directory' => 'products',
                    'column'    => 'image',
                    'links'     => [
                        'product_id'         => 'product_id',
                        'product_variant_id' => 'product_variant_id',
                    ],
                    'model'     => ProductImage::className(),
                ],
                'multipleImage' => [
                    'class'  => MultipleImgBehavior::className(),
                    'links'  => [
                        'product_variant_id' => 'product_variant_id',
                    ],
                    'model'  => ProductImage::className(),
                    'config' => [
                        'caption'       => 'image',
                        'delete_action' => '/product/variant/delimg',
                        'id'            => 'product_image_id',
                    ],
                ],
            ];
        }
        
        /**
         * @inheritdoc
         */
        public function rules()
        {
            return [
                [
                    [
                        'product_id',
                        'product_unit_id',
                    ],
                    'required',
                ],
                [
                    [
                        'product_id',
                        'product_unit_id',
                    ],
                    'integer',
                ],
                [
                    [
                        'price',
                        'price_old',
                        'stock',
                    ],
                    'number',
                ],
                [
                    [
                        'sku',
                    ],
                    'string',
                    'max' => 255,
                ],
                [
                    [
                        'options',
                    ],
                    'safe',
                ],
                [
                    [ 'product_unit_id' ],
                    'exist',
                    'skipOnError'     => true,
                    'targetClass'     => ProductUnit::className(),
                    'targetAttribute' => [ 'product_unit_id' => 'product_unit_id' ],
                ],
            ];
        }
        
        /**
         * @inheritdoc
         */
        public function attributeLabels()
        {
            return [
                'product_variant_id' => Yii::t('product', 'Product Variant ID'),
                'product_id'         => Yii::t('product', 'Product ID'),
                'sku'                => Yii::t('product', 'Sku'),
                'price'              => Yii::t('product', 'Price'),
                'price_old'          => Yii::t('product', 'Price Old'),
                'stock'              => Yii::t('product', 'Stock'),
                'product_unit_id'    => Yii::t('product', 'Product Unit ID'),
                'stock_caption'      => Yii::t('product', 'Stock'),
                'image'              => Yii::t('product', 'Image'),
                'images'             => Yii::t('product', 'Images'),
            ];
        }
        
        /**
         * @return \yii\db\ActiveQuery
         */
        public function getProductUnit()
        {
            return $this->hasOne(ProductUnit::className(), [ 'product_unit_id' => 'product_unit_id' ]);
        }
        
        /**
         * @return \yii\db\ActiveQuery
         */
        public function getProduct()
        {
            return $this->hasOne(Product::className(), [ 'product_id' => 'product_id' ]);
        }
        
        public function getProductStock()
        {
            return $this->hasMany(ProductStock::className(), [ 'product_variant_id' => 'product_variant_id' ]);
        }
        
        public function getQuantity()
        {
            return ProductStock::find()
                               ->where([ 'product_variant_id' => $this->product_variant_id ])
                               ->sum('quantity');
        }
        
        public function getStock_caption()
        {
            return is_null($this->stock) ? '∞' : ( $this->stock > 0 ? Yii::t('product', 'Enable') : Yii::t('product', 'Disable') );
        }
        
        public function getVariantStocks()
        {
            
            return $this->hasMany(ProductStock::className(), [ 'product_variant_id' => 'product_variant_id' ])
                        ->joinWith('stock');
        }
        
        public function getStocks()
        {
            
            return $this->hasMany(Stock::className(), [ 'stock_id' => 'stock_id' ])
                        ->viaTable(ProductStock::tableName(), [ 'product_variant_id' => 'product_variant_id' ]);
        }
        
        public function getFilters()
        {
            
            return $this->hasMany(TaxOption::className(), [ 'tax_option_id' => 'option_id' ])
                        ->viaTable('product_variant_option', [ 'product_variant_id' => 'product_variant_id' ])
                        ->joinWith('taxGroup.lang', true, 'INNER JOIN')
                        ->joinWith('lang', true, 'INNER JOIN');
        }
        
        public function getFullname()
        {
            return empty( $this->product ) ? NULL : ( $this->product->lang->name . ( empty( $this->lang->name ) ? '' : ' ' . $this->lang->name ) );
        }
        
        public function setOptions($values)
        {
            $this->_options = $values;
        }
        
        public function getOptions()
        {
            return $this->hasMany(TaxOption::className(), [ 'tax_option_id' => 'option_id' ])
                        ->viaTable('product_variant_option', [ 'product_variant_id' => 'product_variant_id' ]);
        }
        
        /**
         * @return TaxGroup[]
         */
        public function getProperties()
        {
            $groups = $options = [];
            foreach($this->getOptions()
                         ->with('lang')
                         ->all() as $option) {
                $options[ $option->tax_group_id ][] = $option;
            }
            foreach(TaxGroup::find()
                            ->where([ 'tax_group.tax_group_id' => array_keys($options) ])
                            ->orderBy([ 'sort' => SORT_ASC ])
                            ->with('lang')
                            ->all() as $group) {
                if(!empty( $options[ $group->tax_group_id ] )) {
                    $group->_options = $options[ $group->tax_group_id ];
                    $groups[] = $group;
                }
            }
            return $groups;
        }
        
        public function getId()
        {
            return $this->product_variant_id;
        }
        
        public function setStocks($stocks)
        {
            $this->stocks = (array) $stocks;
        }
        
        public function getCategory()
        {
            return $this->hasOne(Category::className(), [ 'category_id' => 'category_id' ])
                        ->viaTable('product_category', [ 'product_id' => 'product_id' ]);
        }
        
        public function getCategories()
        {
            return $this->hasMany(Category::className(), [ 'category_id' => 'category_id' ])
                        ->viaTable('product_category', [ 'product_id' => 'product_id' ]);
        }
        
        public function getTaxGroupsByLevel($level)
        {
            $categories = ArrayHelper::getColumn($this->categories, 'category_id');
            return TaxGroup::find()
                           ->distinct()
                           ->innerJoin('tax_group_to_category', 'tax_group_to_category.tax_group_id = tax_group.tax_group_id')
                           ->where([ 'tax_group_to_category.category_id' => $categories ])
                           ->where([ 'level' => $level ]);
        }
        
        public function afterSave($insert, $changedAttributes)
        {
            parent::afterSave($insert, $changedAttributes);
            if(!empty( $this->_options )) {
                $options = TaxOption::findAll($this->_options);
                $this->unlinkAll('options', true);
                foreach($options as $option) {
                    $this->link('options', $option);
                }
            }
            
            if(!empty( $this->stocks )) {
                ProductStock::deleteAll([ 'product_variant_id' => $this->product_variant_id ]);
                foreach($this->stocks as $id => $quantity) {
                    $productStock = ProductStock::find()
                                                ->where([
                                                    'product_variant_id' => $this->product_variant_id,
                                                    'stock_id'           => $id,
                                                ])
                                                ->one();
                    $productStock->quantity = $quantity;
                    $productStock->save();
                }
            }
        }
        
    }
