<?php

namespace backend\models;

use Yii;
use yii\base\Model;
use common\models\Card;
use common\models\Customer;
use common\models\Ticket;
use common\models\Account;
use yii\web\UploadedFile;
use common\models\Inventory;
use yii\base\Exception;
use common\models\Product;
use common\models\InventoryGroup;
use common\models\InventoryItem;
use yii\db\Query;
use common\models\Procurement;
use common\models\Transfer;
use common\models\Sale;

/**
 * ContactForm is the model behind the contact form.
 * @property \Yii\web\UploadedFile $file
 */
class InventoryItemForm extends Model{
	
	/**Form data*/
	public $count;
	public $id_product;
	public $type;
	public $name;
	
	/**common data*/
	public $inventory;
	public $last_inventory;
	public $id_inventory;
	public $products;
	public $inventoryGroups;
	
	public $productOptions;
	
	/**save data*/
	public $product;
	public $inventoryGroup;
	public $prevInventoryItem;
	
	/** internal stuff*/
	public $product_in;
	public $product_out;
	public $product_stock;
	public $last_inventory_item;
	public $inventory_item;
	
	public function rules(){
		return [
			[[ 'name',  'count'], 'required'],
			[['id_product','type','name'], 'string'],	
			[['count'], 'integer'],	
			['type','validateType','skipOnEmpty' => false, 'skipOnError' => false],
			['id_product','validateId','skipOnEmpty' => false, 'skipOnError' => false]
				
		];
	}
	
	public function validateType($attribute,$params){
		if ( array_search($this->type, ['product','group']) === false ){
			\Yii::error("Típus nem megfelelő: " . $this->type);
			$this->addError("name","Nincs termék vagy termék csoport kiválasztva");
		}
	}

	public function validateId($attribute,$params){
		if ( !$this->hasErrors('type')){
			if ( $this->type == 'group'){
				$this->inventoryGroup = InventoryGroup::findOne($this->id_product);
				if ( !isset($this->inventoryGroup)){
					\Yii::error("Termék csoport nem található");
					$this->addError("name","Nincs termék vagy termék csoport kiválasztva");
				}
			}else{
				$this->product = Product::findOne($this->id_product);
				if ( !isset($this->product )){
					\Yii::error("Termék nem található");
					$this->addError("name","Nincs termék vagy termék csoport kiválasztva");
				}
			}
		}
	}
	
	public function save(){

			
			$this->loadLastInventory();
			
			$this->loadLastInventoryItem();
			$this->loadProductIn();
			$this->loadProductSold();
			$this->loadProductStock();
			
			$item = new InventoryItem();
			$item->count_in = $this->product_in;
			$item->count_sold = $this->product_out;
			$item->count = $this->count;
			$item->count_system = $this->product_stock;
			
		
			if ( isset( $this->last_inventory_item ) ){
				$item->id_inventory_item_prev = $this->last_inventory_item->id_inventory_item;
				$item->count_prev = $this->last_inventory_item->count;
				if ( !isset($item->count_prev)){
					$item->count_prev = 0;
				}
			}else{
				$item->count_prev = 0;
			}
			
			
			$item->id_user = \Yii::$app->user->id;
			
			if ( $this->type == 'product'){
				$item->price_brutto = $this->product->sale_price;
				$item->type =  InventoryItem::$TYPE_PRODUCT;
				$item->id_product = $this->product->id_product; 
			}else{
				$item->id_inventory_group = $this->inventoryGroup->id_inventory_group;
				$item->type =  InventoryItem::$TYPE_INVENTORY_GROUP;
			}
			$item->id_inventory = $this->inventory->id_inventory;
			
			
			$item->recalculateTotalPriceBrutto();
			
			
			if ( !$item->save(false) ){
				throw new \Exception("Nem sikerült a leltár végrehajtása");
			}
			$this->inventory_item = $item;
			return true;
			
	}
	
	
	protected function loadProductIn(){
		$query = new Query();
		$query->select(['coalesce(sum(procurement.count),0) as total_in']);
		$query->from(Procurement::tableName());
		$query->innerJoin(Product::tableName(),"product.id_product = procurement.id_product");
		
		if ( isset($this->last_inventory_item ) ){
			$query->andWhere([ '>', 'procurement.created_at' ,$this->last_inventory_item->created_at]);
		}
		
		if ( $this->type == 'product') {
			$query->andWhere(['product.id_product' => $this->product->id_product]);
		}else{
			$query->andWhere(['product.id_inventory_group' => $this->inventoryGroup->id_inventory_group]);
		}
		
		$this->product_in = $query->scalar();
		
	}
	
	protected function loadProductSold(){
	
		$query = new Query();
		$query->select(['coalesce(sum(transfer.count),0) as total_sold']);
		$query->from(Transfer::tableName());
		$query->innerJoin(Sale::tableName(),"sale.id_sale = transfer.id_object and transfer.type = " .Transfer::TYPE_PRODUCT);
		$query->innerJoin(Product::tableName(),"product.id_product = sale.id_product ");
		$query->andWhere(['in', 'transfer.status'  ,[Transfer::STATUS_PAID ,Transfer::STATUS_NOT_PAID ] ]);
		$query->andWhere(['transfer.type' => Transfer::TYPE_PRODUCT]);
		
		if ( $this->type == 'product') {
			$query->andWhere(['product.id_product' => $this->product->id_product]);
		}else{
			$query->andWhere(['product.id_inventory_group' => $this->inventoryGroup->id_inventory_group]);
		}
		
		$this->product_out = $query->scalar();
	}

	protected function loadProductStock(){
	
		$query = new Query();
		$query->select(['coalesce(sum(product.stock),0) as total_stock']);
		$query->from(Product::tableName());
		
		if ( $this->type == 'product') {
			$query->andWhere(['product.id_product' => $this->product->id_product]);
		}else{
			$query->andWhere(['product.id_inventory_group' => $this->inventoryGroup->id_inventory_group]);
		}
		
		$this->product_stock = $query->scalar();
	}
	
	
	
	
	public function addProductItem(){
		
	}
	
	public function addGroupItem(){
		
	}
	
	/**
	 * Load previous inventory item, if exists
	 * */
	protected function loadLastInventoryItem( ){
		if ( isset( $this->last_inventory ) ){
			$query = InventoryItem::find();
			
			$query->andWhere(['id_inventory' => $this->last_inventory->id_inventory]);
			
			if ( $this->type == 'product'){
				$query->andWhere(['id_product' => $this->product->id_product]);
			}else{
				$query->andWhere(['id_inventory_group' => $this->inventoryGroup->id_inventory_group]);
			}
			
			$this->last_inventory_item = $query->one();
		}
	}
	
	public function read(){
		
		$this->loadInventory();
		
		$this->loadProducts();
		$this->loadInventoryGroups();
		
		$this->buildProductList();
		
	}
	
	public function loadInventory(){
		$this->inventory = Inventory::findOne($this->id_inventory);
		if ( !isset( $this->inventory) ){
			throw new Exception("Nem található a leltár objektum");
		}
	}
	public function loadLastInventory(){
		$query = Inventory::find();
		$query->innerJoin(InventoryItem::tableName(),"inventory_item.id_inventory = inventory.id_inventory");
		
		if ( $this->type == 'product'){
			$query->andWhere(['inventory_item.id_product' => $this->product->id_product]);
		}else{
			$query->andWhere(['inventory_item.id_inventory_group' => $this->inventoryGroup->id_inventory_group]);
		}
		
		$query->andWhere(['<', 'inventory.created_at'  , $this->inventory->created_at]);
		$query->orderBy(['created_at' => SORT_DESC ]);
		$this->last_inventory =$query->limit(1)->one();
	}
	
	public function loadProducts(){
		$query = Product::find();
		$query->andWhere("id_inventory_group is null");
		$query->andWhere(['status' => Product::STATUS_ACTIVE]);
		$this->products =  $query->all();
	}
	
	public function loadInventoryGroups(){
		$query = InventoryGroup::find();
		$query->andWhere(['status' => Product::STATUS_ACTIVE]);
		$this->inventoryGroups =  $query->all();
	}
	
	public function buildProductList(){
		$this->productOptions = [];
		
		foreach ($this->products as $product ){
			$this->productOptions[]= [ 'type' =>'product', 'id' => $product->id_product ,'name' => $product->name . " (Termék/" .$product->productCategoryName ."/" . $product->accountName .")" ];
			
		}
		
		foreach ($this->inventoryGroups as $inventoryGroup ){
			$this->productOptions[] = ['type' =>'group',  'id' =>$inventoryGroup->id_inventory_group ,'name' =>$inventoryGroup->name ."/Termékcsoport" ];
				
		}
		
	}
	
	public function attributeLabels()
	{
		return [
				'count' => 'Mennyiség',
				'name' => "Termék/Termék csoport neve"
		];
	}
	
	
}