<?php
namespace App\Controllers\Client;
use App\Controllers\BaseController;
use App\Core\Service\Logger;
use App\Model\MasterDataRulesModel;
use App\Model\MasterModel;
use App\Model\OrderModel;
use App\Model\FxModel;
use App\Model\AuthModel;
use App\Library\Fx;
use App\Library\Utilities;
use App\Service\Api;
class OrderController extends BaseController
{
    protected $MasterModel;
    protected $masterDataRulesModel;
    protected $OrderModel;
    protected $FxModel;
    protected $AuthModel;
    protected $fx;
    protected $Utilities;
    public  $api;
    public $Kafkam;
    public function __construct() {
        parent::__construct();
        $this->MasterModel = new MasterModel();
        $this->OrderModel  = new OrderModel();
        $this->FxModel     = new FxModel();
        $this->AuthModel   = new AuthModel();
        $this->masterDataRulesModel = new MasterDataRulesModel();
        $this->Utilities   = new Utilities();
        $this->fx = new Fx();   
        $this->api = new Api();
    }

    public function geItemDetails() {
        try {
            $rules = [
                'item_id'=> array('rules' => 'required|greater_than[0]', 'label' => "Item ID"),
                'branch_id'=> array('rules' => 'required|greater_than[0]', 'label' => "Branch ID"),
                'customer_type' => array('rules' => 'required|greater_than[0]', 'label' => "Customer Type")
            ];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            $dropdown_list = [
                'itemList' => [
                    'id' => 't1.item_id',
                    'text' => 't1.item_name',
                    'table' => 'item_master',
                    'where' => 't1.status=1 AND t2.sale=1',
                    'order_by' => 'item_name',
                    'preselect' => false,
                    'use_client' => true,
                    'selectOtherField' => 't1.item_id,t1.item_name,item_code,variant_id,category_id,group_id,group_name,item_desc,unit,rate,total_rate,including_tax,allow_negative_stock,img_path AS image,t3.hsn_code,t3.total_tax,IF(t4.item_rate IS NOT NULL,t4.item_rate,t1.rate) as rate',
                    'left_join' => [
                        ['table'=>'item_group_master', 'join_predicate'=>'t2.id=t1.group_id', 'use_client' => true],
                        ['table'=>'itemcategory_master', 'join_predicate'=>'t3.itemcat_id=t1.category_id', 'use_client' => true],
                        ['table'=>'item_rate_master', 'join_predicate'=>'t4.item_id=t1.item_id AND customer_type='.$this->input['customer_type'], 'use_client' => true],
                    ],
                    'table_alias' => ['item_master'=>'t1', 'item_group_master'=>'t2', 'itemcategory_master'=>'t3', 'item_rate_master'=>'t4']
                ]
            ];
            $where = ['itemList'=>['t1.item_id'=>$this->input['item_id']]];
            $retData = $this->MasterModel->getOptionList(['itemList'], $this->user_data->comp_id, $where, $dropdown_list);
            if (!$retData['status']) {
                throw new \Exception($retData['error']);
            }
            if(empty($retData['data'])) {
                throw new \Exception("Item detail not found");
            }
            if(empty($retData['data']['itemList'])) {
                throw new \Exception("Item detail not found");
            } 
            
            $retData['data']['itemList'][0]['stock_qty'] = 0;
            
            $dbname = $this->MasterModel->client_db_prefix . $this->user_data->comp_id;
            $stockrs = $this->MasterModel->stockCheck($this->input['item_id'], $this->input['branch_id'], $dbname);
            if($stockrs['status'] === false) {
                throw new \Exception($stockrs['error']);
            }  
            if(!empty($stockrs['data'])) {
                $retData['data']['itemList'][0]['stock_qty'] = $stockrs['data'][0]['stock'];
            }
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => $retData['data']['itemList'][0]));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while getting Item details. '.$e->getMessage(), 'data' => null, 'error' => $e->getMessage()));
        }
    }

    public function getItemTax() {
        try {
            $rules = [
                'item_id'=> array('rules' => 'required', 'label' => "Item ID"),
                'branch_id'=> array('rules' => 'required|greater_than[0]', 'label' => "Branch ID"),
                'state_id' => array('rules' => 'required|greater_than[0]', 'label' => "State")
            ];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            $tax_type_arr = $this->OrderModel->getAllTaxType($this->user_data->comp_id, $this->input['branch_id'], $this->input['state_id']);
            if($tax_type_arr['status'] === false) {
                throw new \Exception($tax_type_arr['error']);
            }  
            $tax_arr = [];
            $item_total_tax = [];
            $total_tax = 0;
            foreach($this->input['item_id'] as $index=>$item_id) {
                $taxrs = $this->OrderModel->getItemTaxDetail($this->user_data->comp_id, $item_id, $tax_type_arr['data']);
                if(empty($taxrs['status'])) {
                    throw new \Exception($taxrs['error']);
                }
                if(!empty($taxrs['data'])) {
                    $tax_arr[$item_id] = $taxrs['data'];
                    $item_total_tax[$item_id] = 0;
                    foreach($taxrs['data'] as $inx => $tax) {
                        $total_tax += $tax["tax_percentage"];
                        $item_total_tax[$item_id] += $tax["tax_percentage"];
                    }
                }
            }
            
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => ["tax_list"=>$tax_arr, "item_total_tax"=>$item_total_tax, "total_tax"=>$total_tax]));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while getting Item details. '.$e->getMessage(), 'data' => null, 'error' => $e->getMessage()));
        }
    }

    private function checkOrderStatus($data, $comp_id) {
        try {
            $table = $this->OrderModel->client_db_prefix.$comp_id.".".$this->MasterModel->tables['order_status'];
            if(empty($data['id'])) {
                $ordrs = $this->MasterModel->getFromMaster($table, "mark_as_default_complete=1", []);
                if(empty($ordrs['status'])) {
                    throw new \Exception($ordrs['error']);
                } else if(empty($ordrs['data'])) {
                    throw new \Exception("Please Set default Order Status value in Order Status Master");
                }
                $data['current_order_status'] = $ordrs['data'][0]['id'];
            } else {
                $ordrs = $this->MasterModel->getFromMaster($table, "id=".$data['current_order_status'], []);
                if(empty($ordrs['status'])) {
                    throw new \Exception($ordrs['error']);
                } else if(empty($ordrs['data'])) {
                    throw new \Exception("Current Order Status detail not found in Order Status Master");
                } else if($ordrs['data'][0]['order_editable'] != 1) {
                    throw new \Exception("Sorry! You can not update order at this stage");
                }
            }
            return ["status" => true, "data" => $data, "order_status_detail"=>$ordrs['data'][0]];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function checkOrderItemStock($data, $comp_id) {
        try {
            $filter_arr = [];
            if(!empty($data['id'])) {
                $filter_arr = ["order_id"=>$data['id'], "stock_status"=>$data['stock_status']];
            }
            $item_id = [];
            foreach ($data['item_list'] as $key => $item) {
                $item_id[] = $item['item_id'];
            }
            $stockrs = $this->OrderModel->getStockDetail($comp_id, $item_id, $data['branch_id'], '', $filter_arr);
            if(empty($stockrs['status'])) {
                throw new \Exception($stockrs['error']);
            }
            foreach ($data['item_list'] as $key => $item) {
				if (!isset($stockrs['data'][$item['item_id']])) {
					throw new \Exception("Invalid Item stock found");
				}
				if ($item['qty'] > $stockrs['data'][$item['item_id']]['stock_qty'] && $stockrs['data'][$item['item_id']]['allow_negative_stock'] != 1) {
                    throw new \Exception($stockrs['data'][$item['item_id']]['item_name'] . ' Not in stock for that much quantity !!');
				}
			}
            return ["status" => true, "data"=>$data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function checkOrderCustomer($data, $comp_id) {
        try {
            $custrs = $this->OrderModel->validateAndAddNewCustomer($data, $comp_id);
            if(empty($custrs['status'])) {
                throw new \Exception($custrs['error']);
            }
            $data['customer_id'] = $custrs['data']['customer_id'];
			$data['address_id'] = $custrs['data']['address_id'];
            $data['customer_detail'] = $custrs['data']['customer'];
            $data['address_detail'] = $custrs['data']['address'];
            $data['customer_type'] = $custrs['data']['customer']['customer_type'];
            return ["status" => true, "data"=>$data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }
    
    private function setUserAndManagerForOrder($comp_id, $data, $user) {
        try {
            $data['bookchangeRights'] = $rights = !empty($user['orderby_change_rights']) ? true : false;
			$data['order_booked_by_id'] = ($rights && !empty($data['order_booked_by_id'])) ? $data['order_booked_by_id'] : $user['user_id'];
            $data['order_booked_by_name'] = ($rights && !empty($data['order_booked_by_name'])) ? $data['order_booked_by_name'] : $user['user_name'];
            
            $mngr = $this->OrderModel->getManagerAndTLById($comp_id, $data['order_booked_by_id']);
            if(empty($mngr['status'])) {
                throw new \Exception($mngr['error']);
            }
            
            $data['o_tl_id'] = isset($mngr['data']['tl_id']) ? $mngr['data']['tl_id'] : NULL;
			$data['o_tl_name'] = isset($mngr['data']['tl_name']) ? $mngr['data']['tl_name'] : NULL;
			$data['o_manager_id'] = isset($mngr['data']['manager_id']) ? $mngr['data']['manager_id'] : NULL;
			$data['o_manager_name'] = isset($mngr['data']['manager_name']) ? $mngr['data']['manager_name'] : NULL;
			$data['o_group_id'] = isset($mngr['data']['profile']) ? $mngr['data']['profile'] : NULL;
            $data['o_group_name'] = isset($mngr['data']['group_name']) ? $mngr['data']['group_name'] : NULL;
            $data['order_platform_origin'] = 1;
            return ["status" => true, "data"=>$data, "rights"=>$rights];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function checkOrderStatusPermissionForUser($order, $user_data, $curr_status) {
        try {
            
            $permission = true;
            if(!empty($user_data->show_all)) {
                if(!empty($user_data->self_update)) { 
                    if($user_data->id != $order['order_booked_by_id']) {
                        $permission = false;
                    }
                }
            } else if(!empty($user_data->order_status_id)){
                if(!in_array($order['current_order_status'], explode(",", $user_data->order_status_id))) {
                    $permission = false;
                }
            } else if(empty($user_data->order_status_id)) {
                $permission = false;
            }

            if(!empty($order['shopify_id']) && $curr_status['status_type'] == 2) {
                if(empty($user_data->update_address_after_shopify)) {
                    $permission = false;
                }
            }
            return ["status" => true, "data"=>$permission];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function checkCouponRelatedData($data, $comp_id) {
        try {
            $chk5 = $this->fx->getCouponApplicableAmount($data);
            if(empty($chk5['status'])) {
                throw new \Exception($chk5['error']);
            }
            if($chk5['data'] > 0) {
                $chk6 = $this->fx->getCouponDiccountAmt($comp_id, $data['coupon_code'], $chk5['data'], $data['customer_id']);
                if(empty($chk6['status'])) {
                    throw new \Exception($chk6['error']);
                }
                $data['discount_amt'] = round($data['discount_amt']);
                if ($data['discount_amt'] != $chk6['discount']) {
                    throw new \Exception("Oops discount mistatch, please refresh and apply coupon code!!");
                }
                $data['order_coupon_id'] = $chk6['coupon_detail']['coupon_id'];
                $data['coupon_detail'] = $chk6['coupon_detail'];
                return ["status" => true, "data"=>$data];
            }  else {
                throw new \Exception("Coupon is not applicable for this order amount which is ".$chk5['data']);
            }  
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    public function addUpdateOrder($params=NULL, $comp_id=NULL, $user_id=NULL) {
        try {
            $rules  = $this->masterDataRulesModel->getMasterTableRules('order', 'insert');
            $validation = $this->validateReqData($rules, $this->input);
            if(!empty($params)) {
                $validation = $this->validateReqData($rules, $params);
            }
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                if(!empty($params)) {
                    throw new \Exception($this->getFirstValidationError());
                } else {
                    $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
                }
                
            }
            $data = $this->input;
            if(!empty($params)) {
                $data = $params;
            }
            if(empty($comp_id)) {
                $comp_id = $this->user_data->comp_id;
            }
            if(empty($user_id)) {
                $user_id = $this->user_data->id;

            }
            $users = $this->AuthModel->getClientUser($comp_id, "user_id=".$user_id, 1);
            if(empty($users['status'])) {
                throw new \Exception("Error in geting User detail to create order".$users['error']);
            }
            if(empty($users['data'])) {
                throw new \Exception("User detail not found to create order");
            }
            $chk1 = $this->checkOrderStatus($data, $comp_id);
            $order_status_detail = [];
            if(empty($chk1['status'])) {
                throw new \Exception($chk1['error']);
            } else if(!empty($chk1['data'])) {
                $data = $chk1['data'];
                $order_status_detail = !empty($chk1['order_status_detail']) ? $chk1['order_status_detail'] : [];
            }
            
            $chk2 = $this->checkOrderItemStock($data, $comp_id);
            if(empty($chk2['status'])) {
                throw new \Exception($chk2['error']);
            } else if(!empty($chk2['data'])) {
                $data = $chk1['data'];
            }
            $chk3 = $this->checkOrderCustomer($data, $comp_id);
            if(empty($chk3['status'])) {
                throw new \Exception($chk3['error']);
            } else if(!empty($chk3['data'])) {
                $data = $chk3['data'];
            }
            $chk4 = $this->setUserAndManagerForOrder($comp_id, $data, $users['data']);
            if(empty($chk4['status'])) {
                throw new \Exception($chk4['error']);
            } else if(!empty($chk4['data'])) {
                $data = $chk4['data'];
            }
            echo "<pre>";
            echo "Before preapring data to save order";
            print_r($data);
            if(!empty($data['coupon_code'])) {
                if(!empty($data['id'])) {
                    $table = $this->FxModel->client_db_prefix . $comp_id.".".$this->FxModel->tables['order_master'];
                    $ord = $this->FxModel->getFromTable($table, "id=:order_id", [":order_id"=>$data['id']]);
                    if(empty($ord['status'])) {
                        throw new \Exception($ord['error']);
                    }
                    if(empty($ord['data'])) {
                        throw new \Exception("Order detail not found to apply coupon code");
                    }
                    if($ord['data'][0]['coupon_code'] != $data['coupon_code']) {
                        $couponrs = $this->checkCouponRelatedData($data, $comp_id);    
                        if(empty($ord['status'])) {
                            throw new \Exception($ord['error']);
                        }
                        $data = $couponrs['data'];
                        $data['delete_coupon_used_where'] = ["order_id"=>$data['id'], 'coupon_id'=>$ord['data'][0]['order_coupon_id']];
                        $data['save_coupon_data'] = [
                            'coupon_name' => $data['coupon_detail']['coupon_name'], 
                            'coupon_id' => $data['coupon_detail']['coupon_id'], 
                            'user_id' => $user_id, 
                            'customer_id' => $data['customer_id'],
                            'coupon_description' => json_encode($data['coupon_detail'])
                        ];
                        $data['update_coupon_used_where'] = ['coupon_code'=>$ord['data'][0]['coupon_code']] ;
                    }
                } else {
                    $couponrs = $this->checkCouponRelatedData($data, $comp_id);    
                    if(empty($couponrs['status'])) {
                        throw new \Exception($couponrs['error']);
                    }
                    $data = $couponrs['data'];
                    $data['save_coupon_data'] = [
                        'coupon_name' => $data['coupon_detail']['coupon_name'], 
                        'coupon_id' => $data['coupon_detail']['coupon_id'], 
                        'user_id' => $user_id, 
                        'customer_id' => $data['customer_id'],
                        'coupon_description' => json_encode($data['coupon_detail'])
                    ];
                }
            } 
            echo "<pre>";
            echo "After preapring data to save order";
            print_r($data);
            $rsord = $this->OrderModel->saveOrderData($comp_id, $data, $order_status_detail);
            if(empty($rsord['status'])) {
                throw new \Exception($rsord['error']);
            }
            if(!empty($params)) {
                return ["status"=>true];
            }
            $this->sendResponse(array('code' => 200, 'message' => 'Order saved successfully', 'data'=> null)); 
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            if(!empty($params)) {
                return ["status"=>false, "error"=>$e->getMessage()];
            }
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while adding new order. '.$e->getMessage(), 'data' => null, 'error' => $e->getMessage()));
        }
    }

    public function getCustomerDetail() {
        try {
            $where = ['c.mobile_number'=>$this->input['mobile_number']];
            $cusrs = $this->FxModel->searchCustomerByMobile($this->user_data->comp_id, $where, array(), true);
            if(empty($cusrs['status'])) {
                throw new \Exception($cusrs['error']);
            }
            if(empty($cusrs['data'])) {
                $this->sendResponse(array('code' => 200, 'message' => 'Customer not found', 'data' => NULL));
            }
            $cusaddrs = $this->FxModel->getCustomerAddress($this->user_data->comp_id, 'customer_id='.$cusrs['data'][0]['id'], 0);
            if(empty($cusaddrs['status'])) {
                throw new \Exception($cusaddrs['error']);
            }
            $cusrs['data'][0]['address_list'] = !empty($cusaddrs['data']) ? $cusaddrs['data'] : [];
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => $cusrs['data'][0]));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while getting cutomer detail.', 'data' => $e->getMessage()));
        }
    }

    public function getOrderDetail(){
        try {
            $rules = ['order_id'=> array('rules' => 'required|greater_than[0]', 'label' => "Order ID")];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            $retarr = ['id'=>$this->input['order_id'], 'reorder'=>0, 'has_status_per'=>1, 'agent_maximum_discount'=>0, 'customerArray'=>[]];

            $ordrs = $this->OrderModel->getOrderDetail($this->user_data->comp_id, "o.id=".$this->input['order_id']);
            if(empty($ordrs['status'])) {
                throw new \Exception($ordrs['error']);
            }
            if(empty($ordrs['data'])) {
                throw new \Exception("Order detail not found");
            }
            $retarr['orderArray'] = $ordrs['data'];
            $statusrs = $this->OrderModel->getStatusDetails($this->user_data->comp_id, "id=".$ordrs['data']['current_order_status']);
            if(empty($statusrs['status'])) {
                throw new \Exception($statusrs['error']);
            }
            // $retarr['current_order_status_details'] = $statusrs['data'];
            $cond = "o.id != ".$this->input['order_id']." AND date(booking_time)<=current_date() AND o.customer_id=".$ordrs['data']['customer_id'];
            $samedayorder = $this->OrderModel->getOrderDetail($this->user_data->comp_id, $cond, 0, 0);
            if(empty($samedayorder['status'])) {
                throw new \Exception($samedayorder['error']);
            }
            $retarr['sameDayOrderArray'] = $samedayorder['data'];
            $retarr['CustomerBillingAddress'] = (array) json_decode($ordrs['data']['customer_billing_address']);
            $retarr['orderArray']['address_pincode']  = '';
            $retarr['orderArray']['address_city_id']  = '';
            $retarr['orderArray']['address_state_id'] = '';
            $retarr['orderArray']['address_mobile']  = '';
            $retarr['orderArray']['gst'] = '';
            $retarr['orderArray']['address'] = '';
            $cusaddrs = $this->FxModel->getCustomerAddress($this->user_data->comp_id, 'customer_id='.$ordrs['data']['customer_id'], 0);
            if(empty($cusaddrs['status'])) {
                throw new \Exception($cusaddrs['error']);
            }
            $retarr['address_list'] = !empty($cusaddrs['data']) ? $cusaddrs['data'] : [];
            foreach($retarr['address_list'] as $k => $v) {
                if($v['address_id'] == $retarr['orderArray']['address_id']){
                    $retarr['orderArray']['address_pincode'] = $v['address_pincode'];
                    $retarr['orderArray']['address_city_id'] = $v['address_city_id'];
                    $retarr['orderArray']['address_state_id'] = $v['address_state_id'];
                    $retarr['orderArray']['address_mobile'] = $v['address_mobile'];
                    $retarr['orderArray']['gst'] = $v['gst'];
                    $retarr['orderArray']['address'] = $v['address'];
                }
            }
            $custrs = $this->fx->getOrderCustomerDetail($this->user_data->comp_id, $ordrs['data']);
            if(empty($custrs['status'])) {
                throw new \Exception($custrs['error']);
            }
            if(empty($custrs['data'])) {
                throw new \Exception("Customer detail not found");
            }
            $retarr['customerArray'] = $custrs['data'];
            $retarr['agent_name'] = $ordrs['data']['order_booked_by_name'];
            $ordItemrs = $this->OrderModel->getOrderItemList($this->user_data->comp_id, "order_id=".$this->input['order_id'], $ordrs['data']['branch_id'], $ordrs['data']['stock_status']);
            if(empty($ordItemrs['status'])) {
                throw new \Exception($ordItemrs['error']);
            }
            // if(empty($ordItemrs['data'])) {
            //     throw new \Exception("Order detail not found");
            // }
            $retarr['orderItemArray'] = $ordItemrs['data'];

            $ordTax = $this->OrderModel->getOrderItemTaxList($this->user_data->comp_id, "order_id=".$this->input['order_id']);
            if(empty($ordTax['status'])) {
                throw new \Exception($ordTax['error']);
            }
            $retarr['orderItemTaxArray'] = $ordTax['data'];
            
            $ordLogs = $this->OrderModel->getOrderLogList($this->user_data->comp_id, "order_id=".$this->input['order_id']);
            if(empty($ordLogs['status'])) {
                throw new \Exception($ordLogs['error']);
            }
            
            if(!empty($retarr['customerArray'])) {
                $retarr['orderArray']['phone_code'] = !empty($retarr['customerArray']['country_code'])?$retarr['customerArray']['country_code']:'91';
                $retarr['orderArray']['mobile_number'] = $retarr['customerArray']['mobile_number'];
                $retarr['orderArray']['customer_name'] = $retarr['customerArray']['customer_name'];
                $retarr['orderArray']['customer_type'] = (int) $retarr['customerArray']['customer_type'];
                $retarr['orderArray']['email_id'] = !empty($retarr['customerArray']['email_id']) ? $retarr['customerArray']['email_id'] : '';
            }
            $retarr['order_editable'] = $ordrs['data']['order_editable'];
            $retarr['whatsapp_hit_api_to_client'] = 0;
            $retarr['tel_payment_gateway'] = 0;
            $retarr['nextOrderStatusArray'] = array();
			$retarr['default_courier_id'] = '';
            $retarr['order_booked_by_name'] = '';
            $retarr['order_booked_by_id'] = '';
            $retarr['order_created_by_id'] = '';
            $retarr['bookchangeRights'] = true;
            
            if(empty($this->input['reorder'])) {
                $cmprs = $this->fx->getCompanyDetail($this->user_data->comp_id);
                if(empty($cmprs['status'])) {
                    throw new \Exception($cmprs['error']);
                }
                $pgtbl = $this->MasterModel->client_db_prefix.$this->user_data->comp_id . "." . $this->MasterModel->tables['payment_gateway'];
                $pgrs  = $this->MasterModel->getFromMaster($pgtbl, "isDefault=:default", [':default'=>1]);
                if(empty($pgrs['status'])) {
                    throw new \Exception($pgrs['error']);
                }
                $retarr['button_pannel'] = [
                    'new_order' => 1,
                    'reorder'   => 1,
                    'call'      => 1,
                    'hangup'    => 1,
                    'email_sms' => 1,
                    'eway_bill' => 0,
                    'track_courier' => 0,
                    'payment_link'  => 0,
                    'move_to_shopify'  => 0,
                    'print_items' => 0,
                    'print_pdf' => 0,
                    'print_courier_slip' => 0,
                    'print_invoice' => 0,
                    'print_label' => 0,
                ];
                
                if(!empty($ordrs['data']['net_amt']) && (int)$ordrs['data']['net_amt'] > 50000) {
                    $retarr['button_pannel']['eway_bill']   = 1;
                }
                if(!empty($ordrs['data']['courier_id']) && !empty($ordrs['data']['courier_api_type'])) {
                    $retarr['button_pannel']['track_courier'] = 1;
                }
                if(!empty($pgrs['data'])) {
                    if(!empty($pgrs['data'][0]['key']) && !empty($statusrs['data'][0]['show_payment_link'])) {
                        $retarr['button_pannel']['payment_link']   = 1;
                    }
                }
                // echo "<pre>";
                // print_r($cmprs);
                // print_r($statusrs['data'][0]);
                if(!empty($cmprs['data']['move_order_to_shopify']) && $statusrs['data'][0]['status_type'] == 12 && empty($ordrs['data']['shopify_id'])) {
                    $perm = $this->checkOrderStatusPermissionForUser($ordrs['data'], $this->user_data, $statusrs['data'][0]);
                    if(empty($perm['status'])) {
                        throw new \Exception($perm['error']);
                    }
                    
                    if(!empty($perm['data']) || !empty($this->user_data->master_type)) {
                        $retarr['button_pannel']['move_to_shopify']   = 1;
                    }
                }
                
                if($statusrs['data'][0]['status_type'] == 6) { //Item Verified
                    $retarr['button_pannel']['print_items'] = 1;
                }
                if(!empty($ordrs['data']['dispatch_date'])) {
                    $retarr['button_pannel']['print_invoice'] = 1;
                }
                if(!empty($ordrs['data']['dispatch_date'])) {
                    $retarr['button_pannel']['print_pdf']   = 1;
                    $retarr['button_pannel']['print_label'] = 1;
                    $retarr['button_pannel']['print_courier_slip'] = 1;
                }
            }
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => $retarr));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while getting order detail. '.$e->getMessage(), 'data' => null, 'error' => $e->getMessage()));
        }
    }
    
    function getOrderLogList() {
        try {
            $rules = ['order_id'=> array('rules' => 'required|greater_than[0]', 'label' => "Order ID")];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            $ordLogs = $this->OrderModel->getOrderLogList($this->user_data->comp_id, "order_id=".$this->input['order_id']);
            if(empty($ordLogs['status'])) {
                throw new \Exception($ordLogs['error']);
            }
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => $ordLogs['data']));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while getting order detail. '.$e->getMessage(), 'data' => null, 'error' => $e->getMessage()));
        }
    }

    function getOrderNextStatusList() {
        try {
            $rules = [
                'order_id'=> array('rules' => 'greater_than_equal_to[0]', 'label' => "Order ID"),
                'current_order_status'=> array('rules' => 'greater_than_equal_to[0]', 'label' => "Current Status ID")
            ];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            $current_order_status = !empty($this->input['current_order_status']) ? $this->input['current_order_status'] : 0;
            if($current_order_status == 0) {
                if($this->input['order_id'] <= 0) {
                    throw new \Exception("Either Order ID or Current Status ID required to fetch next status list");
                }
                $ordrs = $this->OrderModel->getOrderDetail($this->user_data->comp_id, "o.id=".$this->input['order_id']);
                if(empty($ordrs['status'])) {
                    throw new \Exception($ordrs['error']);
                }
                if(empty($ordrs['data'])) {
                    throw new \Exception("Order detail not found");
                }
                $current_order_status = $ordrs['data']['current_order_status'];
            }
            $statusrs = $this->OrderModel->getNextOrderList($this->user_data->comp_id, $current_order_status);
            if(empty($statusrs['status'])) {
                throw new \Exception($statusrs['error']);
            }
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => $statusrs['data']));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while getting order next status list. '.$e->getMessage(), 'data' => null, 'error' => $e->getMessage()));
        }
    }
    
    private function validateAndUpdateOrderStatus($order, $input, $next_status_detail, $user_data) {
        try {
            $udata = ['current_order_status' => $input['next_order_status']];
            if(!empty($input['remarks'])) {
                $udata['remarks'] = \addslashes($input['remarks']);
            }
            
            $logmsg = "Order Status updated to <b>" . $next_status_detail['status_name'] . "</b> By :: " . $user_data->user_name;
            if($next_status_detail['status_type'] == 1) {  //Invoice
                $invrs = $this->fx->generateInvoiceNumberPrefix($user_data->comp_id, $order['branch_id'], $order['state_code']);
                if(empty($invrs['status'])) {
                    print_r($invrs['error']);
                    Logger::error($invrs['error'], ['File' => __FILE__, 'Line' => __LINE__]);
                    throw new \Exception("Something went wrong while generating Invoice No.");
                } else if(empty($invrs['data'])) {
                    throw new \Exception("Unable to generate Invoice No.");
                }
                $udata['invoice_series'] = $invrs['data']['invoice_series'];
                $udata['invoice_prefix_id'] = $invrs['data']['invoice_prefix_id'];
                $udata['invoice_number'] = $invrs['data']['invoice_number'];
                $udata['invoice_date'] = date('Y-m-d');

                $logmsg = "Order Status updated to <b>" . $next_status_detail['status_name'] . " On " . date('d-m-Y') . "</b> By :: " . $user_data->user_name;
            } else if($next_status_detail['status_type'] == 2) {   //Dispatch
                $resval = $this->validateOrderForDispatch($input, $user_data);
                if(empty($resval['status'])) {
                    throw new \Exception($resval['error']);
                } else {
                    $udata['dispatch_date'] = $resval['data']['dispatch_date'];
                    $udata['courier_id'] = $resval['data']['courier_id'];
                    $udata['docket_number'] = $resval['data']['docket_number'];
                    $udata['courier_name'] = $resval['data']['courier_name'];
                }
                $logmsg = "Order has been <b>" . $next_status_detail['status_name'] . "</b> via ".$udata['courier_name']." on " . $udata['dispatch_date'] . " with Docket Number - " . $udata['docket_number'] . " By :: " . $user_data->user_name;
            } else if($next_status_detail['status_type'] == 3) {   //payment received status
                $rules = [
                    'payment_date'=> array('rules' => 'required|max_length[10]', 'label' => "Payment Date"),
                    'payment_confirm_id'=> array('rules' => 'trim|max_length[30]', 'label' => "Transaction No.")
                ];
                $validation = $this->validateReqData($rules, $input);            
                if(empty($validation['status'])) {
                    throw new \Exception($validation['error'] );
                }
                if(!$validation['valid']) {
                    throw new \Exception($this->getFirstValidationError() );
                }
                $udata['payment_date'] = date('Y-m-d', strtotime($input['payment_date']));
				$udata['payment_confirm_id'] = $input['payment_confirm_id'];

                $logmsg = "<b>" . $next_status_detail['status_name'] . "</b> on " . $udata['payment_date'] . ", Status Updated By :: " . $user_data->user_name;

            } else if($next_status_detail['status_type'] == 4) {   //Delivery Date
                $rules = ['delivery_date'=> array('rules' => 'required|max_length[10]', 'label' => "Delivery Date")];
                $validation = $this->validateReqData($rules, $input);            
                if(empty($validation['status'])) {
                    throw new \Exception($validation['error']);
                }
                if(!$validation['valid']) {
                    throw new \Exception($this->getFirstValidationError() );
                }
                $udata['delivery_date'] = date('Y-m-d', strtotime($input['delivery_date']));
                $logmsg = "<b>" . $next_status_detail['status_name'] . "</b> on " . $udata['delivery_date'] . ", Status Updated By :: " . $user_data->user_name;
            } else if($next_status_detail['status_type'] == 5) {   //Hold Date
                $rules = ['hold_till'=> array('rules' => 'required|max_length[10]', 'label' => "Hold Till Date")];
                $validation = $this->validateReqData($rules, $input);            
                if(empty($validation['status'])) {
                    throw new \Exception($validation['error'] );
                }
                if(!$validation['valid']) {
                    throw new \Exception($this->getFirstValidationError() );
                }
                $udata['hold_till'] = date('Y-m-d', strtotime($input['hold_till']));
                $logmsg = "On <b>" . $next_status_detail['status_name'] . "</b> till " . $udata['hold_till'] . ", Status Updated By :: " . $user_data->user_name;
            } else if($next_status_detail['status_type'] == 8) {   //ROT Date
                $rules = ['rto_date'=> array('rules' => 'required|max_length[10]', 'label' => "RTO Date")];
                $validation = $this->validateReqData($rules, $input);            
                if(empty($validation['status'])) {
                    throw new \Exception($validation['error']);
                }
                if(!$validation['valid']) {
                    throw new \Exception($this->getFirstValidationError() );
                }
                $udata['rto_date'] = date('Y-m-d', strtotime($input['rto_date']));
                $logmsg = "<b>" . $next_status_detail['status_name'] . "</b> on " . $udata['rto_date'] . ", Status Updated By :: " . $user_data->user_name;
            } else if($next_status_detail['status_type'] == 21) {   //Invoice Return Date
                $rules = ['invoice_return_date'=> array('rules' => 'required|max_length[10]', 'label' => "Invoice Return Date")];
                $validation = $this->validateReqData($rules, $input);            
                if(empty($validation['status'])) {
                    throw new \Exception($validation['error']);
                }
                if(!$validation['valid']) {
                    throw new \Exception($this->getFirstValidationError() );
                }
                $udata['invoice_return_date'] = date('Y-m-d', strtotime($input['invoice_return_date']));
                $logmsg = "<b>" . $next_status_detail['status_name'] . "</b> on " . $udata['invoice_return_date'] . ", Status Updated By :: " . $user_data->user_name;
            } else if($next_status_detail['status_type'] == 11) {  //MANUAL CONFIRM
                $udata['confirm_by'] = 2;
            }
            $updrs = $this->FxModel->updateOrderStatus($user_data->comp_id, $user_data->id, $order, $udata, $next_status_detail, $logmsg);
            if(empty($updrs['status'])) {
                throw new \Exception($updrs['error']);
            }
            return ["status" => true, "data"=>$updrs['data']];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    function updateOrderStatusRequest() {
        try {
            $rules = [
                'current_order_status'=> array('rules' => 'required|greater_than[0]', 'label' => "Current Order Status"),
                'next_order_status'=> array('rules' => 'required|greater_than[0]', 'label' => "Next Order Status"),
                'update_data'=> array('rules' => 'required', 'label' => "Update Status Data"),
            ];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }

            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            if(!is_array($this->input['update_data'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Provide a list of status update data', 'data' => null));
            }
            $log_data = [];
            $req_id = $this->Utilities->random_string('alnum');
            foreach($this->input['update_data'] as $data) {
                if(!empty($data)) {
                    $log_data[] = [
                        "request_id" => $req_id,
                        "order_id"   => $data['order_id'],
                        "current_status_id" => $this->input['current_order_status'],
                        "next_status_id" => $this->input['next_order_status'],
                        "request_data"   => json_encode($data),
                        "cr_usr"     => $this->user_data->id
                    ];
                }
            }
            if(empty($log_data)) {
                $this->sendResponse(array('code' => 400, 'message' => 'Provide a list of status update data', 'data' => null));
            }
            $tbl = $this->FxModel->client_db_prefix.$this->user_data->comp_id . "." . $this->FxModel->tables['order_status_update_logs'];
            $insrs = $this->FxModel->batchInsert($tbl, $log_data);
            if(empty($insrs['status'])) {
                throw new \Exception($insrs['error']);
            }
            // $event_data = [
            //     "success"=>true,
            //     "message"=>"Status updated for selected Orders"
            // ];
            // $this->api->emitSocketEvent($this->user_data->comp_id , $this->user_data->id, "message", json_encode($event_data));
            $this->Kafkam->sendMessage("sanordo_update_order_status", ['comp_id'=>$this->user_data->comp_id, 'req_id'=>$req_id]);
            Logger::debug("Kafka topic sanordo_update_order_status called", ['File' => __FILE__, 'Line' => __LINE__]);
            $this->sendResponse(array('code' => 200, 'message' => 'Order Status update request submitted successfully. Request ID:'.$req_id, 'data' => NULL));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 400, 'message' => "Something went wrong while updating order status", 'data' => $e->getMessage()));
        }
    }
    
    public function processUpdateOrderStatus($comp_id, $req_id) {
        try {
            if(empty($comp_id)) {
                throw new \Exception("company ID is required to update order status");
            }
            if(empty($req_id)) {
                throw new \Exception("Request ID is required to update order status");
            }
            $tbl = $this->FxModel->client_db_prefix.$comp_id . "." . $this->FxModel->tables['order_status_update_logs'];
            $orsp = $this->FxModel->fetchAllData("SELECT * FROM $tbl WHERE status=:st AND request_id=:req_id ORDER BY cr_date", [":st"=>0, ':req_id'=>$req_id]);
            if(empty($orsp['status'])) {
                throw new \Exception($orsp['error']);
            }
            if(empty($orsp['data'])) {
                throw new \Exception("No Pending logs found to update order status for Request ID:$req_id");
            }
            $users = $this->AuthModel->getClientUser($comp_id, "user_id=".$orsp['data'][0]['cr_usr'], 1);
            if(empty($users['status'])) {
                throw new \Exception("Error in geting User detail to update order status for Request ID:$req_id".$users['error']);
            }
            if(empty($users['data'])) {
                throw new \Exception("User detail not found to update order status for Request ID:$req_id");
            }
            $users['data']['id'] = $users['data']['user_id'];
            $user_data = json_decode(json_encode($users['data']));
            foreach($orsp['data'] as $log) {
                $log['request_data'] = json_decode($log['request_data'], true);
                $ordrs = $this->OrderModel->getOrderDetail($user_data->comp_id, "o.id IN(".$log['order_id'].") AND current_order_status=".$log['current_status_id'], 0 , 1);
                if(empty($ordrs['status'])) {
                    Logger::error($ordrs['error'], ['File' => __FILE__, 'Line' => __LINE__]);
                    continue;
                }
                if(empty($ordrs['data'])) {
                    Logger::error("Order detail not found to update current status. ReqID:".$req_id.", OrderID:".$log['order_id'].", Current Status ID:".$log['current_status_id'], ['File' => __FILE__, 'Line' => __LINE__]);
                    continue;
                }
                $updrs = $this->updateOrderStatus($comp_id, $ordrs['data'], $log, $user_data);
                $uplog = [];
                if(empty($updrs['status'])) {
                    Logger::error("Update Order status log ReqID:".$req_id.", Order ID:".$log['order_id']." Error:".$updrs['error'], ['File' => __FILE__, 'Line'=>__LINE__]);
                    $uplog['status'] = 2;
                    $uplog['fail_reason'] = $updrs['error'];
                } else {
                    Logger::error("Order status updated. ReqID:".$req_id.", Order ID:".$log['order_id'], ['File' => __FILE__, 'Line'=>__LINE__]);
                    $uplog['status'] = 1;
                }
                $updrs1 = $this->FxModel->update($tbl, $uplog, ['id'=>$log['id']]);
                if(empty($updrs1['status'])) {
                    Logger::error("Update Order status log ReqID:".$req_id.", Order ID:".$log['order_id']." Error:".$updrs1['error'], ['File' => __FILE__, 'Line'=>__LINE__]);
                } else {
                    Logger::debug("ReqID:".$req_id.", Order ID:".$log['order_id']." is processed for update status", ['File' => __FILE__, 'Line'=>__LINE__]);
                }
            }
            
            return ["status"=>true, "data"=>NULL];
        } catch(\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status"=>false, "error"=>$e->getMessage()];
        }
    }
    
    public function updateOrderStatus($comp_id, $order, $log, $user_data) {
        try {
            if(empty($comp_id)) {
                throw new \Exception("company ID is required to update order status");
            }
            if(empty($order)) {
                throw new \Exception("Order Detail is required to update order status");
            }
            if(empty($log)) {
                throw new \Exception("Order status update requesst log is required to update order status");
            }
            
            $statusrs = $this->OrderModel->getNextOrderList($comp_id, $log['current_status_id']);
            if(empty($statusrs['status'])) {
                throw new \Exception($statusrs['error']);
            }
            if(empty($statusrs['data'])) {
                throw new \Exception("Invalid Next Order status");
            }       
            $next_status_detail = [];
            foreach($statusrs['data'] as $st) {
                if($st['status_action_id'] == $log['next_status_id']) {
                    $next_status_detail = $st;
                    break;
                }
            }
            if(empty($next_status_detail)) {
                throw new \Exception("Invalid Next Order Status selected");
            }
            if(empty($next_status_detail['logic_id'])) {
                throw new \Exception("Wrong Order status selected");
            }
            if($next_status_detail['status_type'] == 10) {
                throw new \Exception("The status is updated automatically and can not be modified manually for Order ");
            }
            if($order['mark_as_default_complete'] == 2) {
                throw new \Exception('Sorry! You can not update the order, as the status is marked as completed, Order:'.$order['customer_order_id']);
            }
            $perm = $this->checkOrderStatusPermissionForUser($order, $user_data, $next_status_detail);
            if(empty($perm['status'])) {
                throw new \Exception($perm['error']);
            }
            if(empty($perm['data']) && empty($user_data->master_type)) {
                throw new \Exception('You do not have permission to update this order status'.$order['customer_order_id']);
            }
            $log['request_data']['next_order_status'] = $log['next_status_id'];
            $res = $this->validateAndUpdateOrderStatus($order, $log['request_data'], $next_status_detail, $user_data);
            if(empty($res['status'])) {
                throw new \Exception($res['error']);
            }
            return ["status"=>true];
        } catch(\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status"=>false, "error"=>$e->getMessage()];
        }
    }

    private function validateOrderForDispatch(Array $input, $user_data) {
        try {
            $rules = [
                'dispatch_date'=> array('rules' => 'required|max_length[10]', 'label' => "Dispatch Date"),
                'courier_id'=> array('rules' => 'required|greater_than[0]', 'label' => "Courier"),
                'docket_number'=> array('rules' => 'required|max_length[30]', 'label' => "Docket Number")
            ];
            $validation = $this->validateReqData($rules, $input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                return ["status"=>false, "error"=>$this->getFirstValidationError()];
            }
            $dbname = $this->MasterModel->client_db_prefix . $user_data->comp_id;
            $order_table  = $dbname.".".$this->MasterModel->tables['order'];
            $staters = $this->MasterModel->getFromMaster($order_table, "docket_number=:docket_number", [":docket_number"=>$input['docket_number']]);
            if(empty($staters['status'])) {
                throw new \Exception($staters['error']);
            } else if(!empty($staters['data'])) {
                throw new \Exception("Docket/AWB Number already exists");
            }
            $retrs = [
                "dispatch_date" => date('Y-m-d', strtotime($input['dispatch_date'])),
                "courier_id" => $input['courier_id'],
                "docket_number" => $input['docket_number']
            ];
            $courier_table  = $dbname.".".$this->MasterModel->tables['order'];
            $staters = $this->MasterModel->getFromMaster($courier_table, "id=:courier_id", [":courier_id"=>$input['courier_id']]);
            if(empty($staters['status'])) {
                throw new \Exception($staters['error']);
            } else if(!empty($staters['data'])) {
                $retrs['courier_name'] = $staters['data'][0]['courier_name'];
            }
            return ["status"=>true, "data"=>$retrs];
        } catch(\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status"=>false, "error"=>$e->getMessage()];
        }
    }
    
    public function getLeadList() {
        try {
            $rules = [
                'country_code'=> array('rules' => 'required|max_length[10]', 'label' => "Country Code"),
                'mobile_number'=> array('rules' => 'required|max_length[10]', 'label' => "Mobile No."),
            ];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            $order_id = ($this->input['order_id'])?$this->input['order_id']:0;
            $statusrs = $this->OrderModel->leadList($this->user_data->comp_id, $this->input['order_id'], $this->input['country_code'], $this->input['mobile_number']);
            if(empty($statusrs['status'])) {
                throw new \Exception($statusrs['error']);
            }
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => $statusrs['data']));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while getting order next status list. '.$e->getMessage(), 'data' => null, 'error' => $e->getMessage()));
        }
    }

    public function getPackageItems() {
        try {
            $rules = [
                'package_id'=> array('rules' => 'required', 'label' => "Package ID"),
            ];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            $package_id = is_array($this->input['package_id']) ? implode(',', $this->input['package_id']) : $this->input['package_id'];
            $itemrs = $this->OrderModel->getPackageItemList($this->user_data->comp_id, "p.package_id IN($package_id)");
            if(empty($itemrs['status'])) {
                throw new \Exception($itemrs['error']);
            }
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => $itemrs['data']));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while getting Package Items. '.$e->getMessage(), 'data' => null, 'error' => $e->getMessage()));
        }
    }
    
    public function applyCoupon() {
        try {
            $rules = [
                'country_code'=> array('rules' => 'required|max_length[10]', 'label' => "Country Code"),
                'mobile_number'=> array('rules' => 'required|max_length[10]', 'label' => "Mobile No."),
                'amount'=> array('rules' => 'required|integer|greater_than[0]', 'label' => "Amount"),
                'coupon_code'=> array('rules' => 'required|max_length[20]', 'label' => "Coupon Code"),
            ];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            $tbl = $this->FxModel->client_db_prefix.$this->user_data->comp_id . "." . $this->FxModel->tables['customer_master'];
            $custrs = $this->FxModel->getFromTable($tbl, 'country_code=:code AND mobile_number=:mobno', [':code'=>$this->input['country_code'], ':mobno'=>$this->input['mobile_number']]);
            
            if(empty($custrs['status'])) {
                throw new \Exception($custrs['error']);
            }
            $customer_id = 0;
            
            if(!empty($custrs['data'])) {
                $customer_id = $custrs['data'][0]['id'];
            }
            $resp = $this->fx->getCouponDiccountAmt($this->user_data->comp_id, $this->input['coupon_code'], $this->input['amount'], $customer_id);
            if(empty($resp['status'])) {
                throw new \Exception($resp['error']);
            }
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => $resp['discount']));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 500, 'message' => $e->getMessage(), 'data' => null));
        }
    }

    public function archiveUnarchiveOrder() {
        try {
            $rules = [
                'order_id'=> array('rules' => 'required', 'label' => "Order ID"),
                'archive_status'=> array('rules' => 'required|in_list[0,1]', 'label' => "Archive Status"),
            ];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            $data = ['archive' => !empty($this->input['archive_status']) ? 1 : 0];
            $where = "id IN (".implode(",",$this->input['order_id']).")";
            $updrs = $this->OrderModel->updateOrder($this->user_data->comp_id, $data, $where,[]);
            if(empty($updrs['status'])) {
                throw new \Exception($updrs['error']);
            }
            $msg = ($this->input['archive_status'] == 1) ? 'archived' : 'unarchived';
            $this->sendResponse(array('code' => 200, 'message' => "Order $msg successfully", 'data' => null));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);                
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while updating order archive status. '.$e->getMessage(), 'data' => null, 'error' => $e->getMessage()));
        }
    }

    public function assignUnassignOrder() {
        try {
            $rules = [
                'order_id'=> array('rules' => 'required', 'label' => "Order ID"),
                'user_id'=> array('rules' => 'greater_than[0]', 'label' => "User ID"),
                'assign_status'=> array('rules' => 'required|in_list[0,1]', 'label' => "Assign Status"),
            ];
            $validation = $this->validateReqData($rules, $this->input);            
            if(empty($validation['status'])) {
                throw new \Exception($validation['error']);
            }
            if(!$validation['valid']) {
                $this->sendResponse(array('code' => 400, 'message' => $this->getFirstValidationError(), 'data'=>$validation['validation_error']));
            }
            if($this->input['assign_status'] == 1 && empty($this->input['user_id'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Please select user to assign order', 'data'=>null));
            }
            if(empty($this->user_data->master_type) && empty($this->user_data->assign_order)) {
                $this->sendResponse(array('code' => 403, 'message' => 'You do not have permission to assign/unassign orders', 'data'=>null));
            }
            $ord = is_array($this->input['order_id']) ? implode(",",$this->input['order_id']) : $this->input['order_id'];
            $where = "id IN ($ord)";
            $tbl = $this->FxModel->client_db_prefix.$this->user_data->comp_id . "." . $this->FxModel->tables['order'];
            
            $orders = $this->FxModel->getFromTable($tbl, $where, []);
            if(empty($orders['status'])) {
                throw new \Exception($orders['error']);
            }
            if(empty($orders['data'])) {
                throw new \Exception("Order(s) not found to assign/unassign");
            }
            
            $data = [
                'order_booked_by_id' => NULL,
                'order_booked_by_name' => NULL,
                'o_tl_id' => NULL,
				'o_tl_name' => NULL,
				'o_manager_id' => NULL,
				'o_manager_name' => NULL,
				'o_group_id' => NULL,
				'o_group_name' => NULL
            ];
            if(!empty($this->input['assign_status'])) {
                $mngr = $this->OrderModel->getManagerAndTLById($this->user_data->comp_id, $this->input['user_id']);
                if(empty($mngr['status'])) {
                    throw new \Exception($mngr['error']);
                }
                $data['order_booked_by_id'] = $this->input['user_id'];
                $data['order_booked_by_name'] = isset($mngr['data']['user_name']) ? $mngr['data']['user_name'] : NULL;
                $data['o_tl_id'] = isset($mngr['data']['tl_id']) ? $mngr['data']['tl_id'] : NULL;
                $data['o_tl_name'] = isset($mngr['data']['tl_name']) ? $mngr['data']['tl_name'] : NULL;
                $data['o_manager_id'] = isset($mngr['data']['manager_id']) ? $mngr['data']['manager_id'] : NULL;
                $data['o_manager_name'] = isset($mngr['data']['manager_name']) ? $mngr['data']['manager_name'] : NULL;
                $data['o_group_id'] = isset($mngr['data']['profile']) ? $mngr['data']['profile'] : NULL;
                $data['o_group_name'] = isset($mngr['data']['group_name']) ? $mngr['data']['group_name'] : NULL;
            }
            $assign_logs = [];
            $order_logs  = [];
            foreach($orders['data'] as $order) {
                
                $log_message = '';
                if(!empty($this->input['assign_status']))  {
                    $log_message = "Order assigned to <b>".$data['order_booked_by_name']."</b> by <b>".$this->user_data->user_name ."</b>";
                } else if(!empty($order['order_booked_by_id'])) {
                    $log_message = "Order unassigned from <b>".$order['order_booked_by_name']."</b> by <b>".$this->user_data->user_name ."</b>";
                }
                    
                $logs = [
                    'is_assign' => !empty($this->input['assign_status']) ? 1 : 0,
					'order_id' => $order['id'],
					'assigned_by' => $this->user_data->id,
					'assigned_on' => date('Y-m-d H:i:s'),
					'assigned_to' => !empty($this->input['assign_status']) ? $this->input['user_id'] : 0,
					'last_assigned' => !empty($order['order_booked_by_id']) ? $data['order_booked_by_id'] : 0,
					'o_tl_id' => null,
					'o_tl_name' => null,
					'o_manager_id' => null,
					'o_manager_name' => null,
					'o_group_id' => null,
					'o_group_name' => null
                ];
                if(!empty($this->input['assign_status'])) {
                    $logs['o_tl_id'] = isset($mngr['data']['tl_id']) ? $mngr['data']['tl_id'] : NULL;
                    $logs['o_tl_name'] = isset($mngr['data']['tl_name']) ? $mngr['data']['tl_name'] : NULL;
                    $logs['o_manager_id'] = isset($mngr['data']['manager_id']) ? $mngr['data']['manager_id'] : NULL;
                    $logs['o_manager_name'] = isset($mngr['data']['manager_name']) ? $mngr['data']['manager_name'] : NULL;
                    $logs['o_group_id'] = isset($mngr['data']['profile']) ? $mngr['data']['profile'] : NULL;
                    $logs['o_group_name'] = isset($mngr['data']['group_name']) ? $mngr['data']['group_name'] : NULL;
                }
                $assign_logs[] = $logs;
                if(!empty($log_message)) {
                    $order_logs[] = [
                        "order_id" => $order['id'],
                        "last_status_id" => $order['current_order_status'],
                        "current_status_id" => $order['current_order_status'],
                        "log_message" => $log_message,
                        "user_id" => $this->user_data->id
                    ];
                }
            }
                           
            $updrs = $this->OrderModel->assignUnassignOrder($this->user_data->comp_id, $data, $where, $assign_logs, $order_logs);
            if(empty($updrs['status'])) {
                throw new \Exception($updrs['error']);
            }            
            $msg = ($this->input['assign_status'] == 1) ? 'assigned' : 'unassigned';
            $this->sendResponse(array('code' => 200, 'message' => "Order $msg successfully", 'data' => null));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);                
            $this->sendResponse(array('code' => 500, 'message' => 'Something went wrong while updating order archive status. '.$e->getMessage(), 'data' => null, 'error' => $e->getMessage()));
        }
    }
}