<?php

namespace common\modules\product\models;

use common\models\EventsToProducts;
use common\modules\product\helpers\ProductHelper;
use common\modules\product\models\Category;
use common\modules\product\models\CategoryName;
use common\modules\product\models\ProductImage;
use common\modules\product\models\ProductVariantType;
use common\modules\rubrication\models\TaxGroup;
use common\modules\rubrication\models\TaxOption;
use common\modules\rubrication\models\TaxValueString;
use Yii;
use common\modules\product\models\Brand;
use common\modules\product\models\BrandName;
use common\modules\product\models\Product;
use common\modules\product\models\ProductVariant;
use common\modules\product\models\RemoteProducts;
use yii\base\Model;
use yii\helpers\ArrayHelper;

class Import extends Model {
    public $file;
    public $type;

    public $errors = [];
    public $output = [];

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['type'], 'required'],
            [['type'], 'string'],
//            [['file'], 'safe'],
            [['file'], 'file', 'extensions' => 'csv'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'file' => Yii::t('product', 'File'),
        ];
    }

    public function getType() {
        if (!$this->type) {
            $this->type = 'products';
        }
        return $this->type;
    }

    public function goPrices($from = 0, $limit = null) {
        set_time_limit(0);
        $new_products = $linked_products = 0;

        if ( !($handle = $this->getProductsFile('uploadFilePrices')) ) {
            $this->errors[] = 'File not found';
            return FALSE;
        }

        $filesize = filesize(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFilePrices'));
        if ($from) {
            fseek($handle, $from);
        }

        $j = 0;

        $is_utf = (preg_match('//u', file_get_contents(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFilePrices'), null, null, null, 1000000)));


        if($from == 0){
            ProductStock::updateAll(['quantity' => 0 ]);
            ProductVariant::updateAll(['status' => 1 ]);
        }



        while (empty($limit) || $j++ < $limit)
        {


            if(!(($data = fgetcsv ($handle, 10000, ";")) !== FALSE)){
                break;
            }

            foreach ($data as &$value)
            {
                if (!$is_utf) {
                    $value = iconv ('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value);
                }
                $value = trim ($value);
            }

            // данные строк
            $modification_code = @$data[0];
            $price             = floatval(@$data[1]);
            $price_promo       = floatval(@$data[2]);
            $count             = intval(@$data[3]);
            $city_name         = @$data[4];
            $product_title     = @$data[5];

            if (empty ($modification_code)) {
                continue;
            }
            // товары в пути
            if (empty ($city_name))
            {
//                $this->saveNotFoundRecord (
//                    [$modification_code, $product_title],
//                    Yii::getAlias('@uploadFilePricesAway')
//                );

                $this->output[] = 'Товар '. $product_title . ' в пути';

                continue;
            }

            if ( ($productVariant = ProductVariant::find()->filterWhere(['sku' => $modification_code])->one()) === null ) {
                // 'Нет даной модификации в базе';
//                $this->saveNotFoundRecord (
//                    [$modification_code, $product_title],
//                    Yii::getAlias('@uploadFilePricesNoVariant')
//                );

                $this->output[] = 'Для товара '. $product_title . ' не найдено соотвествие';

                continue;
            }




            // ===== Set stock ====
            if ( $city_name ) {
                if ( ($stock = Stock::find()->filterWhere(['name' => trim($city_name)])->one()) === null ) {

                    // Create stock
                    $stock = new Stock();
                    $stock->name = trim($city_name);
                    $stock->save();
                }

                $productStock = ProductStock::find()->where(['product_variant_id' => $productVariant->product_variant_id, 'stock_id' => $stock->stock_id])->one();
                if(!$productStock instanceof ProductStock) {
                    $productStock = new ProductStock;
                    $productStock->product_variant_id = $productVariant->product_variant_id;
                    $productStock->stock_id = $stock->stock_id;
                    $productStock->product_id = $productVariant->product_id;
                }
                $productStock->quantity = $count;

                $productStock->save();
                $productStocks = ProductStock::find()->where(['product_variant_id' => $productVariant->product_variant_id])->andWhere(['<>', 'stock_id', $stock->stock_id])->all();

                $quantity = array_sum(ArrayHelper::getColumn($productStocks, 'quantity')) + $count;
            } else {

                $productStocks = ProductStock::find()->where(['product_variant_id' => $productVariant->product_variant_id])->all();

                if($productStocks instanceof  ProductStock){
                    $quantity = array_sum(ArrayHelper::getColumn($productStocks, 'quantity')) + $count;
                } else {
                    $quantity = 0;
                }

            }

            if ($price_promo) {
                $productVariant->price_old = $price;
                $productVariant->price = $price_promo;
            } else {
                $productVariant->price = $price;
                $productVariant->price_old = $price_promo;
            }

            $productVariant->stock = $quantity;
            $productVariant->status = 0;
            $productVariant->save();

            $this->output[] = '<font style="color:blue">Товар '. $product_title .' успешно сохранен</font>';
        }

        $result = [
            'end' => feof($handle),
            'from' => ftell($handle),
            'totalsize' => $filesize,
            'items' => $this->output,

        ];

        fclose ($handle);

        if ($result['end']) {
            unlink(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFilePrices'));
        }

        return $result;
    }

    public function goProducts($from = 0, $limit = null) {

        set_time_limit(0);
        $new_products = $linked_products = 0;

        if ( !($handle = $this->getProductsFile('uploadFileProducts')) ) {
            $this->errors[] = 'File not found';
            return FALSE;
        }

        $filesize = filesize(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'));


        if ($from) {
            fseek($handle, $from);
        }

        $j = 0;

        $is_utf = (preg_match('//u', file_get_contents(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'), null, null, null, 1000000)));

        $result_items = [];



        while ( empty($limit) || $j++ < $limit)
        {
            if(!(($data = fgetcsv ($handle, 10000, ";")) !== FALSE)){
                break;
            }

            foreach ($data as &$value)
            {
                if (!$is_utf) {
                    $value = iconv ('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value);
                }
                $value = trim ($value);
            }

            // будет всегда 19 элементов
            for ($i = 0; $i <= 18; $i++)
            {
                if (! isset ($data[$i]))
                {
                    $data[$i] = null;
                }
            }


            // 1  Группа (категория)
            $catalog_names = explode(',',$data[0]);

            if (empty ($catalog_names))
            {
                $result_items[] = "Не указана категория (строка $j) ";
                continue;
            }

            // 2  Бренд
            $brand_name = $data[1];
            if (empty ($brand_name))
            {
                $result_items[] = "Не указан бренд (строка $j)";
                continue;
            }

            // 3  Название товара
            $product_name = $data[2];
            if (empty ($product_name))
            {
                $result_items[] = "Не указано наименование товара (строка $j)";
                continue;
            }

            // 4  Описание Укр
            $product_body_uk = $data[3];

            // 5  Описание Рус
            $product_body_ru = $data[4];

            // 6  Фильтр [god:2013-2014]*[pol:мужской]*[naznacenie-germo-beg:Для вещей]*[material-germo-bag:нет]*[value-germo-bag:нет]*[weight-germo-bag:нет]*[ipx-germo-bag:нет]*[in-pacage-bag:нет]*[size-germo-bag:нет]*[rekomend-germo-bag:нет]
            $filters = explode ('*', $data[5]);

            // 11 Цена акция
            $product_cost_old = floatval($data[7]);
            $product_cost = '';
            // 10 Цена
            if ($product_cost_old) {
                $product_cost_old = floatval($data[6]);
                $product_cost = floatval($data[7]);
            }

            // 12 Акция
            $product_akciya = (bool)$data[8];

            // 13 Сопуд. Тов.
            $similar = explode (',', $data[9]);

            // 14 Новинки
            $product_new = (bool)$data[10];

            // 15 Топ продаж
            $product_top = (bool)$data[11];


            // 17 ВИДЕО КОД
            $product_video = $data[12];

            // 18 Галлерея фото
            if (trim($data[13])) {
                $fotos = explode (',', trim($data[13]));
            }

            // 19 Штрих код товара.
            // расшифровал - это модификации товара!

            $product_image = explode ('=', $data[14]);
            $product_image = @$product_image[3];

            if ( ($_product = Product::find()->filterWhere(['name' => trim($product_name)])->one()) === null ) {
                $_product = new Product();
            }

            $is_new_product = empty($_product->product_id);
            $category_id = [];
            foreach($catalog_names as $catalog_name){

                // ==== Set category ====
                if ( ($category = Category::find()->filterWhere([ 'name' => trim($catalog_name)])->one()) === null ) {
                    // Create category
                    $category = new Category();
                    $category->name = trim($catalog_name);
                    $category->save();
                }

                $category_id[] = $category->category_id;
            }


            $_product->categories = $category_id;

            // ===== Set brand ====
            if ( $brand_name ) {
                if ( ($brand = Brand::find()->filterWhere(['name' => trim($brand_name)])->one()) !== null ) {
                    $_product->brand_id = $brand->brand_id;
                } else {
                    // Create brand
                    $brand = new Brand();
                    $brand->name = trim($brand_name);
                    $brand->save();
                    $_product->brand_id = $brand->brand_id;
                }
            }

            $_product->name = $product_name;
            $_product->video = $product_video;
            $_product->description = $product_body_ru;
            $_product->is_top = $product_top;
            $_product->akciya = $product_akciya;
            $_product->is_new = $product_new;

            if (!$_product->save()) {
                $result_items[] = 'Product #'. $_product->name .' not saved' . " (строка $j)";
                continue;
            }



            if (!empty($fotos)) {
                foreach($fotos as $foto) {
                    $source_image = Yii::getAlias('@uploadDir') . '/product_images/'. urlencode($foto);

                    if (file_exists($source_image)) {
                        if (($productImage = ProductImage::find()->andFilterWhere(['image'=> $foto])->andFilterWhere(['product_id' => $_product->product_id])->one()) === null) {
                            copy($source_image, Yii::getAlias('@productsDir') . "/" . $foto);
                            $productImage = new ProductImage();
                            $productImage->product_id = $_product->product_id;
                            $productImage->image = $foto;
                            $productImage->save();
                        }
                    }
                }
            }


            // нужно для проставления характеристик относящихся к модификациям
            $MOD_ARRAY = [];

            for ($i = 14; $i < count ($data); $i ++)
            {
                if (! empty ($data[$i]))
                {
                    $mod_arr    = explode ('=', $data[$i]);
                    $mod_art    = $mod_arr[0];
                    $variant_filters   = explode ('*', $mod_arr[1]);
                    $mod_color  = $mod_arr[2];
                    $mod_image  = $mod_arr[3];
                    $mod_stock  = isset($mod_arr[4]) ?$mod_arr[4]:1;
                    $mod_cost   = isset($product_cost) ? floatval($product_cost) : 0;
                    $mod_old_cost = floatval($product_cost_old);

                    // Check product variant
                    if ( ($_productVariant = ProductVariant::find()->andFilterWhere([ 'sku'=> $mod_art])->andFilterWhere(['product_id' => $_product->product_id])->one()) === null ) {
                        $_productVariant = new ProductVariant();
                        $_productVariant->product_id = $_product->product_id;
                    }
                    $_productVariant->product_unit_id = 1;

                    $_productVariant->sku = $mod_art;
                    $_productVariant->price = $mod_cost;
                    $_productVariant->price_old = $mod_old_cost;
                    $_productVariant->stock = $mod_stock;

                    $product_variant_type_name = '';
                    if (! empty ($mod_color)) {
                        $product_variant_type_name = 'Цвет';
                        $_productVariant->name = $mod_color;
                    }

                    if (! empty ($variant_filters)) {

                        $variants_options = $this->saveFilters($variant_filters,1,$category_id);

                    }


                    if (isset($variants_options) && !empty($variants_options)) {
                        $_productVariant->options = $variants_options;
                    }


                    // ===== Set variant type ====
                    if ( $product_variant_type_name ) {
                        if ( ($product_variant_type = ProductVariantType::find()->filterWhere([ 'name'=> $product_variant_type_name])->one()) !== null ) {
                            $_productVariant->product_variant_type_id = $product_variant_type->product_variant_type_id;
                        } else {
                            $product_variant_type = new ProductVariantType();
                            $product_variant_type->name = $product_variant_type_name;
                            $product_variant_type->save();
                            $_productVariant->product_variant_type_id = $product_variant_type->product_variant_type_id;
                        }
                    }

                    $_productVariant->save();

                    $MOD_ARRAY[] = $_productVariant->product_variant_id;

                    if ($mod_image) {
                        $source_image = Yii::getAlias('@productsDir') . '/'. urlencode($mod_image);
                        if (file_exists($source_image)) {
                            if (($variantImage = ProductImage::find()->andFilterWhere([ 'image' => $mod_image])->andFilterWhere(['product_variant_id' => $_productVariant->product_variant_id])->one()) === null) {
//                                copy($source_image, Yii::getAlias('@productsDir') . "/" . $mod_image);
                                $variantImage = new ProductImage();
                                $variantImage->product_id = $_product->product_id;
                                $variantImage->product_variant_id = $_productVariant->product_variant_id;
                                $variantImage->image = $mod_image;
                                $variantImage->save();
                            }
                        }
                    }
                }
            }



            if (! empty ($filters)) {

                $options = $this->saveFilters($filters,0,$category_id);

            }


            if (isset($options) && !empty($options)) {
                $_product->options = $options;
            }

            $_product->save();

            $result_items[] = "Product {$_product->name} #{$_product->product_id} saved (". ($is_new_product ? 'new product' : 'exists product') .")" . " (строка $j)";
        }

        $result = [
            'end' => feof($handle),
            'from' => ftell($handle),
            'totalsize' => $filesize,
            'items' => $result_items,

        ];

        fclose ($handle);

        if ($result['end']) {
            unlink(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'));
        }

        return $result;
    }


    public function goEvent($file) {

        set_time_limit(0);


        $handle =  fopen($file, 'r');


        while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
            if(isset($data[0]) && isset($data[1])){
                $product = ProductVariant::find()->where(['sku' => $data[1]])->joinWith('product')->one();
                if($product instanceof  ProductVariant){
                    $model= EventsToProducts::find()->where(['event_id' =>$data[0], 'product_id' => $product->product->product_id ])->one();
                    if(!$model instanceof EventsToProducts){
                        $model =  new EventsToProducts;
                        $model->event_id = $data[0];
                        $model->product_id = $product->product->product_id;
                        $model->save();
                    }
                }
            }

        }
        fclose($handle);
        unlink($file);

    }

    private function getProductsFile($file_type) {
        $filename = Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@'. $file_type);
        if (!is_file($filename)) {
            $this->errors[] = "File $filename not found";
            return FALSE;
        }
        return fopen ($filename, 'r');
    }

    private function saveNotFoundRecord (array $line, $filename)
    {
        $str = implode (';', $line)."\n";
        $str = iconv ("UTF-8//TRANSLIT//IGNORE", "windows-1251", $str);

        $fg = fopen (Yii::getAlias('@uploadDir') .'/'. $filename, 'a+');
        fputs ($fg, $str);
        fclose ($fg);
    }


    /**
     * @param $filters array of filters like [['pol'='мужской'],['god' = '2013'],['volume'='25 л']*['size'='49 x 30 x 20см'],['composition'='600D полиэстер']]
     * @param $level 0 for products and 1 for product variant
     * @param $catalog_names array catalogs id
     * @return array
     */
    private function saveFilters($filters, $level,$catalog_names){
        $options = [];
        foreach($filters as $filter) {

            preg_match_all('/\[(.*):(.*)\]/',$filter,$filter);

            if (empty($filter[1][0])) {
                continue;
            }
            $filter_name = trim($filter[1][0]);

            $taxGroup = TaxGroup::find()->where(['alias'=>$filter_name])->one();
            if(!$taxGroup instanceof TaxGroup){
                $taxGroup = new TaxGroup();
                $taxGroup->alias = $filter_name;
                $taxGroup->level = $level;
                $taxGroup->name = $filter_name;
                $taxGroup->module = 'string';
                $taxGroup->hierarchical = FALSE;
                $taxGroup->categories = $catalog_names;
                $taxGroup->is_filter = FALSE;
                $taxGroup->save();
            }

            $filters_options = explode(',',$filter[2][0]);

            foreach($filters_options as $filter_options){
                $value = TaxValueString::find()->innerJoinWith('taxOption')->andWhere(['value'=>$filter_options])->andWhere(['tax_option.tax_group_id' => $taxGroup->tax_group_id])->one();

                if (!$value instanceof TaxValueString) {
                    // Create option
                    $option = new TaxOption();
                    $option->tax_group_id = $taxGroup->tax_group_id;
                    $option->name = $filter_options;
                    $option->save();

                    $value = new TaxValueString();
                    $value->tax_option_id = $option->tax_option_id;
                    $value->value = $filter_options;
                    $value->save();

                    $option->default_value = $value->tax_value_id;
                    $option->save();
                }
                $options[] = $value->tax_option_id;

            }


        }

        return $options;
    }
}