<?php
namespace App\Controllers\Client;
use App\Controllers\BaseController;
use App\Core\Library\Mailer;
use App\Core\Service\Logger;
use App\Model\MasterDataRulesModel;
use App\Model\MasterDataSetModel;
use App\Model\OrderModel;
use App\Model\FxModel;
use App\Config\Main;
use App\Library\BlueDart;
use App\Library\Delhivery;
use App\Library\Shiprocket;

class CourierController extends BaseController
{
    private $MasterDataRulesModel;
    private $MasterDataSetModel;
    private $OrderModel;
    private $FxModel;
    public function __construct() {
        parent::__construct();
        $this->MasterDataRulesModel = new MasterDataRulesModel();
        $this->MasterDataSetModel = new MasterDataSetModel();
        $this->OrderModel  = new OrderModel();
        $this->FxModel     = new FxModel();
    }
    
    function getOrderCourierFormData() {
        try {
            $rules = [
                'courier_id'=> array('rules' => 'required|max_length[50]', 'label' => "Courier Id"),
                'order_id'=> array('rules' => 'required|max_length[50]', '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']));
            }
            $orsp = $this->FxModel->getOrderDetailForCourier($this->user_data->comp_id, "t1.id=".$this->input['order_id'], 1);
            if(empty($orsp['status'])) {
                throw new \Exception($orsp['error']);
            }
            if(empty($orsp['data'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Order detail not found', 'data' => null));
            }
            $arsp = $this->FxModel->getOrderFullAddressDetail($this->user_data->comp_id, $orsp['data']);
            if(empty($arsp['status'])) {
                throw new \Exception($arsp['error']);
            }
            $orsp['data'] = $arsp['data'];

            $crsp = $this->FxModel->getCourierDetail($this->user_data->comp_id, "t1.id=".$this->input['courier_id']);
            if(empty($crsp['status'])) {
                throw new \Exception($crsp['error']);
            }
            if(empty($crsp['data'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Courier detail not found', 'data' => null));
            }
            
            $button_status = false;
            
            if(!empty($crsp['data']['api_create_awbno_url'])) {
                if(strtolower($crsp['data']['courier_api']) == 'bluedart') {
                    if(!empty($crsp['data']['courier_api']['customer_id']) && 
                    !empty($crsp['data']['courier_api']['api_key_password']) && 
                    !empty($crsp['data']['courier_api']['login_id']) && 
                    !empty($crsp['data']['courier_api']['vendor_code'])) {
                        $button_status = true;
                    }
                }  else if(strtolower($crsp['data']['courier_api']) == 'delhivery') {
                    if(!empty($crsp['data']['courier_api']['token'])) {
                        $button_status = true;
                    }
                }  else if(strtolower($crsp['data']['courier_api']) == 'shiprocket') {
                    if(!empty($crsp['data']['courier_api']['login_id']) && 
                    !empty($crsp['data']['courier_api']['api_key_password'])) {
                        $button_status = true;
                    }
                } else {
                    $button_status = false;
                }
            }

            if (!empty($this->input['is_update'])) {
			    $button_status = false;
            }
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => [
                'courier_api_type'=> $crsp['data']['courier_api'],
                'data' => $orsp['data'],
                'courierDetail' => $crsp['data'],
                'create_button' => $button_status
            ]));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 400, 'message' => "Something went wrong while verifying courier serviceability", 'data' => $e->getMessage()));
        }
    }

    function verifyCourierServiceability() {
        try {
            $rules = [
                'courier_id'=> array('rules' => 'required|max_length[50]', 'label' => "Courier Id"),
                'pincode'=> array('rules' => 'required|exact_length[6]', 'label' => "Pincode"),
            ];
            $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']));
            }
            $crsp = $this->FxModel->getCourierDetail($this->user_data->comp_id, "t1.id=".$this->input['courier_id']);
            if(empty($crsp['status'])) {
                throw new \Exception($crsp['error']);
            }
            if(empty($crsp['data'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Courier detail not found', 'data' => null));
            }
            if(strtolower($crsp['data']['courier_api']) == 'bluedart') {
                $bluedart = new BlueDart($crsp['data']);
                $rs = $bluedart->checkPincodeServiceability($this->input['pincode']);
                if(empty($rs['status'])) {
                    throw new \Exception($rs['error']);
                }
                if(empty($rs['serviceable'])) {
                    $this->sendResponse(array('code' => 400, 'message' => 'Not Serviceable! Check Pincode', 'data' => null));
                }
            }  else if(strtolower($crsp['data']['courier_api']) == 'delhivery') {
                $delhivery = new Delhivery($crsp['data']);
                $rs = $delhivery->checkPincodeServiceability($this->input['pincode']);
                if(empty($rs['status'])) {
                    throw new \Exception($rs['error']);
                }
                if(empty($rs['serviceable'])) {
                    $this->sendResponse(array('code' => 400, 'message' => 'Not Serviceable! Check Pincode', 'data' => null));
                }
            } else {
                $table  = $this->FxModel->client_db_prefix . $this->user_data->comp_id.".".$this->FxModel->tables['courier_pincode'];
                $rsp = $this->FxModel->getFromTable($table, "courier_id=:courierid AND pincode=:pin", [':courierid'=>$this->input['courier_id'], ':pin'=>$this->input['pincode']]);
                if(empty($rsp['status'])) {
                    throw new \Exception($rsp['error']);
                }
                if(empty($rsp['data'])) {
                    $this->sendResponse(array('code' => 400, 'message' => 'Not Serviceable! Check Pincode', 'data' => null));
                }
            }
            $this->sendResponse(array('code' => 200, 'message' => 'Serviceable!', '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 verifying courier serviceability", 'data' => $e->getMessage()));
        }
    }

    function saveOrderCourierDetail(){
        try {
            $rules = $this->MasterDataRulesModel->getMasterTableRules('order_courier', 'insert');
            $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']));
            }
            $update_data = [
                "courier_expected_del_date" => date('Y-m-d', strtotime($this->input['courier_expected_del_date'])),
                "updated_time" => date('Y-m-d H:i:s')
            ];
            $insert_data = $this->MasterDataSetModel->getOrderCourierData($this->input);
            if(empty($insert_data['status'])) {
                throw new \Exception($insert_data['error']);
            }
            $insrsp = $this->OrderModel->addOrderCourierDetail($this->user_data->comp_id, $update_data, $insert_data['dbData']);
            if(empty($insrsp['status'])) {
                throw new \Exception($insrsp['error']);
            }
            $this->sendResponse(array('code' => 200, 'message' => 'Courier detail saved successfully', '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 saving courier detail", 'data' => $e->getMessage()));
        }
    }

    function createDocketNumber() {
        try {
            $rules = $this->MasterDataRulesModel->getMasterTableRules('order_courier', 'insert');
            $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']));
            }
            $insert_data = $this->MasterDataSetModel->getOrderCourierData($this->input);
            if(empty($insert_data['status'])) {
                throw new \Exception($insert_data['error']);
            }
            
            $crsp = $this->FxModel->getCourierDetail($this->user_data->comp_id, "t1.id=".$this->input['courier_id']);
            if(empty($crsp['status'])) {
                throw new \Exception($crsp['error']);
            }
            if(empty($crsp['data'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Courier detail not found', 'data' => null));
            }
            $orsp = $this->FxModel->getOrderDetailForCourier($this->user_data->comp_id, "t1.id=".$this->input['order_id'], 1);
            if(empty($orsp['status'])) {
                throw new \Exception($orsp['error']);
            }
            if(empty($orsp['data'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Order detail not found for Order ID:'.$this->input['order_id'], 'data' => null));
            }
            
            $arsp = $this->FxModel->getOrderFullAddressDetail($this->user_data->comp_id, $orsp['data']);
            if(empty($arsp['status'])) {
                throw new \Exception($arsp['error']);
            }
            $orsp['data'] = $arsp['data'];
            $ordItemrs = $this->OrderModel->getOrderItemList($this->user_data->comp_id, "order_id=".$this->input['order_id'], 0, 0);
            if(empty($ordItemrs['status'])) {
                throw new \Exception($ordItemrs['error']);
            }
            if(empty($ordItemrs['data'])) {
                throw new \Exception("Order Item detail not found");
            }

            $item_total_qty = $this->FxModel->getOrderItemsTotalQty($this->user_data->comp_id, $this->input['order_id']);
            if(empty($item_total_qty['status'])) {
                throw new \Exception($item_total_qty['error']);
            }
            $orsp['data']['total_item_qty'] = $item_total_qty['data'];
            $docket_no = '';
            if(strtolower($crsp['data']['courier_api']) == 'bluedart') {
                $bluedart = new BlueDart($crsp['data']);
                $rs = $bluedart->createDocketNo($orsp['data'], $ordItemrs['data'], $this->input);
                if(empty($rs['status'])) {
                    throw new \Exception($rs['error']);
                }
                if(empty($rs['data'])) {
                    $this->sendResponse(array('code' => 400, 'message' => 'Unable to create BlueDart Docket Number.', 'data' => null));
                }
                $docket_no = $rs['data']['AWBNo'];
                $insert_data['dbData']['customer_origin_area'] = $rs['data']['DestinationArea'] ?? NULL;
                $insert_data['dbData']['ClusterCode'] = $rs['data']['ClusterCode'] ?? NULL;
                $insert_data['dbData']['DestinationLocation'] = $rs['data']['DestinationLocation'] ?? NULL;
            }  else if(strtolower($crsp['data']['courier_api']) == 'delhivery') {
                $delhivery = new Delhivery($crsp['data']);
                $rs = $delhivery->createDocketNo($orsp['data'], $ordItemrs['data'], $this->input);
                if(empty($rs['status'])) {
                    throw new \Exception($rs['error']);
                }
                if(empty($rs['data'])) {
                    $this->sendResponse(array('code' => 400, 'message' => 'Unable to create Delhivery Docket Number.' . !empty($rs['message'])?$rs['message']:'', 'data' => null));
                }
                $docket_no = $rs['data'];
            }  else if(strtolower($crsp['data']['courier_api']) == 'shiprocket') {
                $shiprocket = new Shiprocket($crsp['data']);
                $rs = $shiprocket->createDocketNo($orsp['data'], $ordItemrs['data'][0], $this->input);
                if(empty($rs['status'])) {
                    throw new \Exception($rs['error']);
                }
                if(empty($rs['data'])) {
                    $this->sendResponse(array('code' => 400, 'message' => 'Unable to create Shiprocket Docket Number.', 'data' => null));
                }
                $docket_no = $rs['data']['awb_code'];
            } else {
                $this->sendResponse(array('code' => 400, 'message' => 'Invalid request to create Docket Number', 'data' => null));
            }
            
            if(empty($docket_no)) {
                $this->sendResponse(array('code' => 400, 'message' => 'Unable to create Docket Number.', 'data' => null));
            }
            $update_data = [
                "courier_expected_del_date" => date('Y-m-d', strtotime($this->input['courier_expected_del_date'])),
                "updated_time" => date('Y-m-d H:i:s')
            ];
            $insert_data['dbData']['awb_gen_using_api'] = 1;

            $insrsp = $this->OrderModel->addOrderCourierDetail($this->user_data->comp_id, $update_data, $insert_data['dbData']);
            if(empty($insrsp['status'])) {
                throw new \Exception($insrsp['error']);
            }
            $this->sendResponse(array('code' => 200, 'message' => 'Docket No. created successfully', 'data' => ["docket_no"=>$docket_no]));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 400, 'message' => "Something went wrong while creating Docket No.: ". $e->getMessage(), 'data' => NULL));
        }
    }

    function trackCourierDetail() {
        try {
            $rules = [
                'order_id'=> array('rules' => 'required|max_length[50]', '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']));
            }
            $orsp = $this->FxModel->getOrderDetailForCourier($this->user_data->comp_id, "t1.id=".$this->input['order_id'], 1);
            if(empty($orsp['status'])) {
                throw new \Exception($orsp['error']);
            }
            if(empty($orsp['data'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Order detail not found for Order ID:'.$this->input['order_id'], 'data' => null));
            }
            if(empty($orsp['data']['courier_id']) || empty($orsp['data']['docket_no'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Courier or Docket No not found for Order ID:'.$orsp['data']['customer_order_id'], 'data' => null));
            }
            $crsp = $this->FxModel->getCourierDetail($this->user_data->comp_id, "t1.id=".$orsp['data']['courier_id']);
            if(empty($crsp['status'])) {
                throw new \Exception($crsp['error']);
            }
            if(empty($crsp['data'])) {
                $this->sendResponse(array('code' => 400, 'message' => 'Courier detail not found', 'data' => null));
            }
            $tracking_info = [];
            if(strtolower($crsp['data']['courier_api']) == 'bluedart') {
                $bluedart = new BlueDart($crsp['data']);
                $rs = $bluedart->trackDocketNo($this->input['docket_no']);
                if(empty($rs['status'])) {
                    throw new \Exception($rs['error']);
                }
                $tracking_info = $rs['data'];
            }  else if(strtolower($crsp['data']['courier_api']) == 'shiprocket') {
                $shiprocket = new Shiprocket($crsp['data']);
                $rs = $shiprocket->trackDocketNo($this->input['docket_no']);
                if(empty($rs['status'])) {
                    throw new \Exception($rs['error']);     
                }   
                $tracking_info = $rs['data'];
            }  else {
                $this->sendResponse(array('code' => 400, 'message' => 'Invalid request to track Courier', 'data' => null));
            }
            $tracking_info['courier_name'] = $crsp['data']['courier_name'];
            $tracking_info['courier_api'] = $crsp['data']['courier_api'];
            $this->sendResponse(array('code' => 200, 'message' => null, 'data' => $tracking_info));
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            $this->sendResponse(array('code' => 400, 'message' => "Something went wrong while tracking courier detail", 'data' => $e->getMessage()));
        }
    }
}