<?php
namespace App\Services;
use Carbon\Carbon;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Config;

use App\Models\Users\CustomersModel;
use App\Models\Users\CustomersAddressModel;
use App\Models\Sales\SalesModel;
use App\Models\Sales\SalesDetailsModel;
use App\Models\Sales\SalesItemsModel;
use App\Models\Sales\SalesItemsTaxesModel;
use App\Models\Sales\SalesChargesModel;
use App\Models\Sales\SalesPromoModel;
use App\Models\Stores\PromoCodesModel;
use App\Models\Sales\SalesPaymentsModel;
use App\Models\Sales\SalesDeliveriesModel;
use App\Models\Sales\SalesItemsModifiersModel;
use App\Models\Sales\SalesNotificationsModel;
use App\Models\Sales\SalesLogsModel;
use App\Models\Stores\ReservationsModel;

class SalesService {
	/*
	 *  
	 * saves the order
	 */
	public function get($sale_id){
		$sale = SalesModel::with([
				'sales_items.item_details',
				'sales_items.sales_item_modifiers_list.modifier_details',
				'sales_details',
				'sales_charges',
				'sales_payments',
				'sales_store',
				'sales_delivery'
				])
				->with(['sales_items.sales_item_modifiers_list' => function($query) use ($sale_id){
					$query->where('sale_id',$sale_id);
				}])
				->where('sale_id',$sale_id);
		// echo str_replace_array('?',$sale->getBindings(),$sale->toSql());
		return $sale->first();
	}
	/*
	 *  
	 * saves the order
	 */
	public function save($customer_id,$details,$items,$charges=array(),$payments=array(),$employee_id="",$order_no="",$total_amount_per_brand="",$brand_name="",$km_away=0,$promos=array(),$brand_id="",$no_of_brands=0){
		$sale = null; $error = "";

		# VALIDATE
		if(empty($items)){
			$error = "Items are empty";
		}
		else if(!$customer_id) $error = "Invalid customer.";

		# IF VALID
		if($error == ""){
			# SAVE AND GENERATE NEW SALES ID 
			$sale = new SalesModel();
			$date_time_now  = DATE("Y-m-d H:i:s");
			$total_promo_amount = 0;
			if(!empty($promos)){
				$prev_percentage = 0;
				foreach ($promos as $promo) {
					if ($prev_percentage > $promo->promo_percentage) {
						// echo "<pre>",$prev_percentage,"</pre>";
						continue;
					}
					if($promo->brand_id && $promo->brand_id == $brand_id){
						$total_promo_amount += $promo->promo_amount;
					}
					else{
						if(empty($promo->brand_id) && $promo->promo_amount < $total_amount_per_brand ){
							$total_promo_amount += $total_amount_per_brand * ($promo->promo_percentage*0.01);
						}
					}
					if($promo->brand_id == $brand_id || empty($promo->brand_id) ){
						$prev_percentage = $promo->promo_percentage;
					}
				}
			}
			// die(); 
			$sale->sale_time = DB::raw('Now()');
			$sale->order_no = $order_no;
			$sale->customer_id = $customer_id;
			$sale->payment_type = $details->payment;
			$sale->employee_id = ($employee_id != "" ? $employee_id : 1);
			// $sale->payment_type = $details->payment;
			$sale->comment = (isset($details->notes) ? $details->notes : null);
			$sale->store_account_payment = 0;
			$sale->location_id = $details->store_id;
			$sale->register_id = 1;
			$sale->dispatched = 0;
			$sale->received = 0;
			$sale->suspended = 2;
			$sale->name = (isset($details->first_name) ?  $details->first_name : null)." ".(isset($details->last_name) ?  $details->last_name : null)." ";
			$sale->email = (isset($details->email) ? $details->email : null);
			$sale->phone = (isset($details->phone) ? $details->phone : null);			
			$sale->transaction_type = $details->trans_type;
			$sale->pump_number = $brand_name;
			// $sale->order_date = DB::raw('NOW()');
			$sale->order_date = $date_time_now;
			// $sale->promo_id = $details->promo_id;
			if($no_of_brands > 1){
				$sale_type = 2;
			}else{
				$sale_type = 1;
			}
			$sale->promo_amount = $total_promo_amount;
			if(isset($details->sale_type)){
				// $sale->sale_type = $details->sale_type;
				$sale->sale_type = $sale_type;
			}
			
			$delivery_fee = 0;
			$tip_amount = 0;
			if(!empty($charges)){
				foreach ($charges as $chg) {
					if($chg['code'] == 'delivery_fee'){
						$delivery_fee += $chg['amount'];
					} 
					if($chg['code'] == 'tip'){
						$tip_amount += $chg['amount'];
					} 
				}
			}
			$sale->delivery_fee = $delivery_fee;
			$sale->km_away = $km_away;
			$sale->tip_amount = $tip_amount;
			$sale->total_amount = ($total_amount_per_brand + $tip_amount + $delivery_fee) - $total_promo_amount;

			$address = (isset($details->street1) ? $details->street1 : "");
			$address .= (isset($details->street2) ? $details->street2 : "");
			$address .= (isset($details->city) ? $details->city : "");
			$address .= (isset($details->zip) ? $details->zip : "");
			$sale->address = $address;
			$sale->delivery_lat = (isset($details->lat) &&  $details->lat ? $details->lat : null);
			$sale->delivery_long = (isset($details->lng) &&  $details->lng ? $details->lng : null);
			$sale->address_city = (isset($details->city) ? $details->city : "");
			if(!empty($payments)){
				$sale->ref_no = $payments[0]['code'];
			}
			$sale->save();
			if($sale->sale_id){
				$sale_id = $sale->sale_id;
				# SAVE DETAILS AND GENERATE NEW SALES ID 
					$sales_detail = new SalesDetailsModel();
					$sales_detail->sale_id = $sale_id;
					$sales_detail->first_name = (isset($details->first_name) ? $details->first_name : null);
					$sales_detail->last_name = (isset($details->last_name) ? $details->last_name : null);
					$sales_detail->email = (isset($details->email) ? $details->email : null);
					$sales_detail->phone = (isset($details->phone) ? $details->phone : null);
					$sales_detail->loyalty_card_num = (isset($details->loyalty_card_num) ? $details->loyalty_card_num : null);	
					$sales_detail->loyalty_card_email = (isset($details->loyalty_card_email) ? $details->loyalty_card_email : null);
					$sales_detail->loyalty_card_tier = (isset($details->loyalty_card_tier) ? $details->loyalty_card_tier : null);
					$sales_detail->street_1 = (isset($details->street1) ? $details->street1 : null);
					$sales_detail->street_2= (isset($details->street2) ? $details->street2 : null);
					$sales_detail->city = (isset($details->city) ? $details->city : null);
					$sales_detail->zip = (isset($details->zip) ? $details->zip : null);
					$sales_detail->lat = (isset($details->lat) &&  $details->lat ? $details->lat : null);
					$sales_detail->lng = (isset($details->lng) && $details->lng ? $details->lng : null);
					$sales_detail->notes = (isset($details->notes) ? $details->notes : null);
					$sales_detail->billing_address = (isset($details->billing_address) ? $details->billing_address : null);
					$sales_detail->billing_city = (isset($details->billing_city) ? $details->billing_city : null);
					$sales_detail->billing_country = (isset($details->billing_country) ? $details->billing_country : null);
					$sales_detail->actual_address = (isset($details->actual_address) ? $details->actual_address : null);
					$sales_detail->save();
				# SAVE CURRENT ADDRESS TO CUSTOMER
					if(isset($details->save_address) && (bool)$details->save_address){
						CustomersAddressModel::where('customer_id',$customer_id)->update(['default'=>0]);
						$new_address = new CustomersAddressModel();
						$new_address->customer_id = $customer_id;
						$new_address->name = (isset($details->street1) ? $details->street1 : null);
						$new_address->street_1 = (isset($details->street1) ? $details->street1 : null);
						$new_address->street_2= (isset($details->street2) ? $details->street2 : null);
						$new_address->city = (isset($details->city) ? $details->city : null);
						$new_address->zip = (isset($details->zip) ? $details->zip : null);
						$new_address->lat = (isset($details->lat) &&  $details->lat ? $details->lat : null);
						$new_address->lng = (isset($details->lng) && $details->lng ? $details->lng : null);
						$new_address->default = 1;
						$new_address->save();
					}
				# SAVE SALES ITEMS
					$line_no = 1;
					foreach ($items as $item) {
						$sales_item = new SalesItemsModel();
						$sales_item->sale_id = $sale_id;
						$sales_item->item_id = $item['item_id'];
						$sales_item->item_cost_price = 0;
						$sales_item->item_unit_price = $item['item_unit_price'] - ($item['item_unit_price'] / 1.12 * 0.12);
						$sales_item->quantity_purchased = $item['quantity_purchased'];
						$sales_item->comment = (!empty($item['notes']) ? implode (", ", $item['notes']) : '' );
						$sales_item->is_promo_item = (!empty($item['is_promo_item']) ?  $item['is_promo_item'] : 0 );
						$sales_item->line = $line_no;
						$sales_item->save();
						if(isset($item['modifiers'])){
							foreach ($item['modifiers'] as $mod_group_id => $modifiers) {
								foreach ($modifiers as $mod) {
									$sales_mod_item = new SalesItemsModifiersModel();
									$sales_mod_item->sale_id = $sale_id;
									$sales_mod_item->item_id = $item['item_id'];
									$sales_mod_item->item_line = $line_no;
									$sales_mod_item->mod_group_id = $mod_group_id;
									$sales_mod_item->line = $line_no;
									$sales_mod_item->mod_id = $mod->mod_id;
									$sales_mod_item->mod_price = $mod->cost;
									$sales_mod_item->mod_unit_price = $mod->cost - ($mod->cost / 1.12 * 0.12);
									$sales_mod_item->qty = $item['quantity_purchased'];
									$sales_mod_item->datetime = DB::raw('NOW()');
									$sales_mod_item->save();
								}
							}
						}

						$sale_item_tax = new SalesItemsTaxesModel();
						$sale_item_tax->sale_id = $sale_id;
						$sale_item_tax->item_id = $item['item_id'];
						$sale_item_tax->line = $line_no;
						$sale_item_tax->name = 'VAT';
						$sale_item_tax->percent = 12.000;
						$sale_item_tax->cumulative = 0;
						$sale_item_tax->save();

						$line_no++;
					}
				# SAVE ITEM TAXES HERE
				# ------------------------------------------------------
				# SAVE CHARGES
					if(!empty($charges)){
						foreach ($charges as $chg) {
							$sales_charge = new SalesChargesModel();
							$sales_charge->sale_id = $sale_id;
							$sales_charge->code = $chg['code'];
							$sales_charge->description = $chg['description'];
							$sales_charge->charge_cost = $chg['amount'];
							$sales_charge->save();
						}
					}
				# SAVE PAYMENTS
					if(!empty($payments)){
						foreach ($payments as $pay) {
							$sales_payment = new SalesPaymentsModel();
							$sales_payment->sale_id = $sale_id;
							$pay_type = $pay['type'];
							if($pay_type == 'ipay88')
								$pay_type = 'credit';
							$sales_payment->payment_type = $pay_type;
							$sales_payment->payment_code = $pay['code'];
							$sales_payment->payment_amount = $pay['amount'];
							$sales_payment->approve_code = $pay['approve_code'];
							$sales_payment->payment_date = DB::raw('Now()');
							$sales_payment->save();
						}
					}
				# SAVE TO DELIVERIES
					// isset($details->trans_type) && $details->trans_type == 'delivery' 
					if(isset($details->deliver_date) && $details->deliver_date != ""){
						$sales_deliveries = new SalesDeliveriesModel();
						$sales_deliveries->sale_id = $sale_id;
						$sales_deliveries->store_id = $details->store_id;
						$sales_deliveries->customer_id = $customer_id;
						$sales_deliveries->deliver_date = Carbon::parse($details->deliver_date)->format('Y-m-d');
						$sales_deliveries->deliver_time = Carbon::parse($details->deliver_time)->format('H:i');
						$sales_deliveries->order_type = $details->order_type;
						$sales_deliveries->status = 'pending';
						$sales_deliveries->save();	
					}
				# SAVE TO PROMO
					if(!empty($promos)){
						foreach ($promos as $promo) {
							$total_promo_amount_table = 0;
							$prev_percentage = 0;
							if ($prev_percentage > $promo->promo_percentage) {
								continue;
							}
							// echo "<pre>",print_r($promo),"</pre>";die();
							$sales_promo = new SalesPromoModel();
							$promo_code_table = new PromoCodesModel();
							$sales_promo->sale_id = $sale_id;
							$sales_promo->promo_id = $promo->promo_id;
							$sales_promo->promo_type = $promo->promo_type;
							$sales_promo->promo_code = $promo->promo_code;
							$sales_promo->base_amount = $promo->base_amount;
							$sales_promo->percentage = $promo->promo_percentage;
							$sales_promo->free_delivery = $promo->free_delivery;
							$sales_promo->base_item_id = (isset($promo->base_item_id) ? $promo->base_item_id : null);
							$sales_promo->item_id = (isset($promo->item_id) ? $promo->item_id : null);
							$sales_promo->brand_id = (isset($promo->brand_id) ? $promo->brand_id : null);
							$sales_promo->location_id = (isset($promo->location_id) ? $promo->location_id : null);
							if($promo->brand_id && $promo->brand_id == $brand_id){
								#UPDATE THE QTY REDEEMED OF PROMO
								$sales_promo->amount = $promo->promo_amount;
								$promo_code_table->where('promo_id',$promo->promo_id)
								->update([
									'qty_redeemed'=>(isset($promo->qty_redeemed) ? $promo->qty_redeemed+1 : 1)
								]);
								$sales_promo->save();
							}
							else{
								if(empty($promo->brand_id) && $promo->promo_amount < $total_amount_per_brand ){
									#UPDATE THE QTY REDEEMED OF PROMO
									$sales_promo->amount = $total_amount_per_brand * ($promo->promo_percentage*0.01);
									$promo_code_table->where('promo_id',$promo->promo_id)
									->update([
										'qty_redeemed'=>(isset($promo->qty_redeemed) ? $promo->qty_redeemed+1 : 1)
									]);
									$sales_promo->save();
								}
							}
							// echo "<pre>",print_r($total_promo_amount),"</pre>";
							if($promo->brand_id == $brand_id || empty($promo->brand_id) ){
								$prev_percentage = $promo->promo_percentage;
							}
						}
					}
				# SAVE LOGS
					$this->log($sale_id,[
						'customer_id' 	=> $customer_id,
						'description' 	=> 'Added a new sales order',
						'action' 		=> 'create',
						'from' 			=> 'new',
						'to' 			=> 'pending',
						'created_type' 	=> 'customer',
						'created_by' 	=> $customer_id,
					]);

			}			
		}
		return ['sales'=>$sale,'error'=>$error];
	}
	/*
	 *  
	 * saves the order
	 */
	public function reserve($customer_id,$employee_id=null,$reserve_details=array(),$sale_id=null){
		$error = "";
		if(empty($reserve_details)){
			$reserve_details = "reservation details are empty";
		}
		else if(!$customer_id) $error = "Invalid customer.";

		$reserve = null;
		if($error == ""){
			$reserve = new ReservationsModel();
			$reserve->sale_id = $sale_id;
			$reserve->employee_id = $employee_id;
			$reserve->customer_id = $customer_id;
			$reserve->brand_id = $reserve_details->brand_id;
			$reserve->location_id = $reserve_details->store_id;
			$reserve->first_name = $reserve_details->first_name;
			$reserve->last_name = $reserve_details->last_name;
			$reserve->email = $reserve_details->email;
			$reserve->phone = $reserve_details->mobile;
			$reserve->guest_no = $reserve_details->guest_no;
			$reserve->reserve_date = $reserve_details->reserve_date;
			$reserve->reserve_time = $reserve_details->reserve_time;
			$reserve->save();
		}
		return ['reserve'=>$reserve,'error'=>$error];
	}
	/*
	 *  
	 * updates the sales items
	 */
	public function log($sale_id,$details=array(),$notifs=array()){
		$log = new SalesLogsModel();
		$log->sale_id = $sale_id;
		foreach ($details as $column => $value) {
			$log->$column = $value;
		}
		$log->save();

		if(!empty($notifs)){
			foreach ($notifs as $nt_details) {
				$notify = new SalesNotificationsModel();
				foreach ($nt_details as $column => $value) {
					$notify->$column = $value;
				}
				$notify->log_id = $log->id;
				$notify->save();
			}
		}
		return $log;
	}
	/*
	 *  
	 * updates the sales items
	 */
	public function updateItems($sale_id,$items,$employee_id=null,$customer_id=null){
		$items_saved = [];
		$sale = SalesModel::with(['sales_delivery'])->where('sale_id',$sale_id)->first();

		if($sale){
			# DELETE THE ITEMS
			SalesItemsModel::where('sale_id',$sale_id)->delete();
			# DELETE THE MODIFIERS
			SalesItemsModifiersModel::where('sale_id',$sale_id)->delete();
			SalesItemsTaxesModel::where('sale_id',$sale_id)->delete();
			$line_no = 1;
			foreach ($items as $item) {
				$sales_item = new SalesItemsModel();
				$sales_item->sale_id = $sale_id;
				$sales_item->item_id = $item['item_id'];
				$sales_item->item_cost_price = 0;
				$sales_item->item_unit_price = $item['item_unit_price'];
				$sales_item->quantity_purchased = $item['quantity_purchased'];
				$sales_item->comment = (!empty($item['notes']) ? implode (", ", $item['notes']) : '' );
				$sales_item->line = $line_no;
				$sales_item->save();

				if(isset($item['modifiers'])){
					foreach ($item['modifiers'] as $mod_group_id => $modifiers) {
						foreach ($modifiers as $mod) {
							$sales_mod_item = new SalesItemsModifiersModel();
							$sales_mod_item->sale_id = $sale_id;
							$sales_mod_item->item_id = $item['item_id'];
							$sales_mod_item->item_line = $line_no;
							$sales_mod_item->mod_group_id = $mod_group_id;
							$sales_mod_item->line = $line_no;
							$sales_mod_item->mod_id = $mod->mod_id;
							$sales_mod_item->mod_price = $mod->cost;
							$sales_mod_item->mod_unit_price = $mod->cost;
							$sales_mod_item->qty = 1;
							$sales_mod_item->datetime = DB::raw('NOW()');
							$sales_mod_item->save();
						}
					}
				}

				$sale_item_tax = new SalesItemsTaxesModel();
				$sale_item_tax->sale_id = $sale_id;
				$sale_item_tax->item_id = $item['item_id'];
				$sale_item_tax->line = $line_no;
				$sale_item_tax->name = 'VAT';
				$sale_item_tax->percent = 12.000;
				$sale_item_tax->cumulative = 0;
				$sale_item_tax->save();

				$line_no++;
				$items_saved[] = $items_saved;
			}
			# LOG UPDATE
				$from = "";
				$to = "";
				$store_id = null;
				if(isset($sale->sales_delivery->status)){
					$from = $sale->sales_delivery->status;
					$to = $sale->sales_delivery->status;
				}
				if(isset($sale->sales_delivery->store_id)){
					$store_id = $sale->sales_delivery->store_id;
				}
				$log = [
					'store_id' 		=> $store_id,
					'description' 	=> 'Modified sales order items',
					'action' 		=> 'update',
					'from' 			=> $from,
					'to' 			=> $to,
				];
				if($employee_id != null){
					$log['employee_id'] = $employee_id;
					$log['created_by'] = $employee_id;
					$log['created_type'] = 'employee';
				}
				if($customer_id != null){
					$log['customer_id'] = $customer_id;
					$log['created_by'] = $customer_id;
					$log['created_type'] = 'customer';
				}
				$this->log($sale_id,$log);
		}
		return $items_saved;
	}
	/*
	 *  
	 * merge items order
	 */
	public function mergeItems($cart_items){
		$cart_total = 0;
		# COMBINE ITEMS
		$items = array(); 
		foreach ($cart_items as $ci) {
			$plus_code = '';
			if(isset($ci->modifiers)){
				foreach ($ci->modifiers as $mod_group_id => $modifiers) {
					foreach ($modifiers as $mod) {
						$plus_code .= $mod_group_id . $mod->mod_id;
					}
				}
			}
			$line_item_code = $ci->item_id . $plus_code; 
			if(!isset($items[$line_item_code])){
				$notes = [];
				if(isset($ci->remarks) && $ci->remarks != "")
					$notes[] = $ci->quantity." - ".$ci->remarks;
				$items[$line_item_code] = [
					'item_id' => $ci->item_id,
					'item_unit_price' => $ci->unit_price,
					'quantity_purchased' => $ci->quantity,
					'modifiers' => (isset($ci->modifiers) ? $ci->modifiers : []),
					'notes' => $notes,
					'is_promo_item'=>$ci->is_promo_item
				];
			}
			else{
				$temp = $items[$line_item_code];
				$temp['quantity_purchased'] += $ci->quantity;
				if(isset($ci->remarks) && $ci->remarks != "")
					$temp['notes'][] = $ci->quantity." QTY - ".$ci->remarks;
				$items[$line_item_code] = $temp;						
			}
			$cart_total += $ci->quantity * $ci->unit_price;
		}
		return ['items'=>$items,'total_amount'=>$cart_total];
	}
	/*
	 *  
	 * merge items order
	 */
	public function mergeItemsByBrandStore($cart_items){
		$brand_stores = array();
			$line_total = 0;
		foreach ($cart_items as $key=>$ci) {
			$code = $ci->brand_id . '-' . $ci->brand_location_id;
			$line_total = (($ci->unit_price + $ci->total_modifier_price) * $ci->quantity );
			$ci->line_total = $line_total;
			if(!isset($brand_stores[$code])){
				$brand_stores[$code] = array(
					'brand_id' => $ci->brand_id,
					'store_id' => $ci->brand_location_id,
					'brand_name'=>$ci->brand_name,
					'location_code'=>$ci->location_code,
					'brand_code'=>$ci->brand_code,
					'line_total' => $line_total,
					'items' => array($ci)
				);
			}
			else{
				$temp = $brand_stores[$code];
				$temp['items'][] = $ci;
				$brand_stores[$code] = $temp;
			}

		}
		foreach ($brand_stores as $code => $bs) {
			$total_amount_per_brand = 0;
			foreach ($brand_stores[$code]['items'] as $value) {
				$total_amount_per_brand += $value->line_total;
			}
			$items = $this->mergeItems($bs['items']);
			$temp = $brand_stores[$code];
			$temp['items'] = $items['items'];
			$brand_stores[$code] = $temp;
			$brand_stores[$code]['brand_total'] = $total_amount_per_brand;
		}

		return $brand_stores;
	}
}
