<?php

namespace App\Http\Libraries;

use App\Http\Common\DBUtil;
use App\Http\Common\Util;
//use GuzzleHttp\Client;
//use GuzzleHttp\Psr7\Request;
use DB;
use App\Http\Classes\Aws\S3Bucket;
use Illuminate\Support\Facades\Storage;

use App\Http\Common\TMailing;
use App\Http\Libraries\Strongholdpay;
use App\Http\Libraries\Ticker;
use App\Http\Libraries\Swifter;
use App\Http\Libraries\Birdeye;
use Carbon\Carbon;
use App\Http\Libraries\CSPW;
use Exception;
use App\Http\Controllers\Ecommerce\SMSController;

class Treez
{

    //private static $api_url = 'https://api.treez.io/v2.0/dispensary/';
    //private static $s3_bucket_url = 'https://fteecomuserdoc.s3-us-west-1.amazonaws.com/';

    public function __construct()
    {
        //$api_url = Self::$api_url;

        //$s3_bucket_url = $_ENV['AWS_S3_DOCUMENT_BUCKET_URL'];
    }

    /**
     * Request = client_id,apikey
     */
    // public static function sendTimeSLots($data)
    // {
    //     // {
    //     //     "treez_store_id": "ftesandbox",
    //     //     "order_number": "sa123456",
    //     //     "treez_order_number": "APPQI5",
    //     //     "full_name": "Oren Levy",
    //     //     "email_address": "orenl@fteusa.com",
    //     //     "mobile_number": "3103103101",
    //     //     "preferred_time_slot": "12 PM - 4 PM",
    //     //     "preferred_time_slot2": "7 PM - 9 PM"
    //     // }

    //     $data = $data['data'];
    //     if (!isset($data['data']['selectedTimeSlots']['prefered']) || !isset($data['data']['selectedTimeSlots']['alternate']) || !isset($data['user']['mobile'])) {
    //         return '';
    //     }
    //     $authData = Self::getToken($data['dispensary'], $data['cmp']);
    //     $storeid = $authData['integDispId'];
    //     $params = array();

    //     $params["treez_store_id"] = $storeid;
    //     $params["order_number"] = $data['data']['ecomordernum'];
    //     $params["treez_order_number"] = $data['data']['posordernum'];
    //     $params["full_name"] = $data['user']['name'];
    //     $params["email_address"] = $data['user']['email'];
    //     $params["mobile_number"] = $data['user']['mobile'];
    //     $params["preferred_time_slot"] = $data['data']['selectedTimeSlots']['prefered'];
    //     $params["preferred_time_slot2"] = $data['data']['selectedTimeSlots']['alternate'];

    //     $rawparams = json_encode($params);
    //     $header = array(
    //         'Content-Type:  application/json',
    //     );
    //     $url = "https://prod-125.westus.logic.azure.com:443/workflows/6f2e1ad303c74fa4a6d46480573b4f22/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=3Dle7Lmyraymiq1MHrRIyMZOfdttMqPm7e0-269x7Zc";
    //     return $response = Util::HandleCurl('POST', $header, $rawparams, $url);
    // }
    public static function orders($data)
    {
        try {
        //print_r($data);

        // if($data['ordertype'] == 'preview'){

        //   $authData = Self::getToken($data['dispensary'], $data['cmp']);
        //   return Self::orderApi("previewticket",$authData,$data);
        // }elseif($data['ordertype'] == 'makereqdata'){
        //     return Self::makeReqData($data['data']);
        // }

        if ($data['ordertype'] == 'preview') {

            // TMailing::dummyreq('user');
            // exit;
            $authData = Self::getToken($data['data']['dispensary'], $data['data']['cmp']);
            //$data['data']['tickettype'] = Self::checkTicketType($data['data']['checkoutData']['paymentType']);
            $madereq = Self::makeReqData($data);
            $previewresponse = Self::orderApi("previewticket", $authData, $madereq);
            DB::select("update cmp" . $data['data']['cmp'] . ".customercart set previewon=current_timestamp where custid=" . $data['data']['ecom_custid']);
            $previewresponsearray = json_decode($previewresponse, true);

            //unwanted code
            // $previewresponsearray['resultCode'] = 'FAIL';
            // $previewresponsearray['resultReason'] = "UNKNOWN";
            // $previewresponsearray['resultDetail'] = "This is new msg";
            // $previewresponse = json_encode($previewresponsearray);
            //

            $jsonreq = json_encode($madereq, JSON_PRETTY_PRINT);
            $separator = "\n===========================" . date('Y-m-d H:i:s') . "======================" . PHP_EOL;
            //file_put_contents('previewall.json', $separator, FILE_APPEND);
            //file_put_contents('previewall.json', $jsonreq, FILE_APPEND);
            //file_put_contents('previewall.json', $previewresponse, FILE_APPEND);

            Util::wlog('previewall', $separator);
            Util::wlog('previewall', $jsonreq);
            Util::wlog('previewall', $previewresponse);
            if(!isset($previewresponsearray['resultCode'])) {
                $maderesponse = array();
                $maderesponse['status'] = 'FAIL';
                $maderesponse['isCommonError'] = true;
                $maderesponse['commonReasonCode'] = $previewresponsearray['resultReason'];
                $maderesponse['commonReasonMsg'] = $previewresponsearray['resultDetail'];
                return $maderesponse;
            }
            else if ($previewresponsearray['resultCode'] == 'FAIL') {
                $jsonreq = json_encode($madereq, JSON_PRETTY_PRINT);
                $separator = "\n===========================" . date('Y-m-d H:i:s') . "======================" . PHP_EOL;
                //file_put_contents('previewfailresponse.json', $separator, FILE_APPEND);
                //file_put_contents('previewfailresponse.json', $jsonreq, FILE_APPEND);
                //file_put_contents('previewfailresponse.json', $previewresponse, FILE_APPEND);
                Util::wlog('previewfailresponse', $separator);
                Util::wlog('previewfailresponse', $jsonreq);
                Util::wlog('previewfailresponse', $previewresponse);
                if (isset($previewresponsearray['resultReason']) && $previewresponsearray['resultReason'] == "PURCHASE_LIMIT_EXCEEDED") {
                    $maderesponse = array();
                    $maderesponse['status'] = 'FAIL';
                    $maderesponse['isCommonError'] = true;
                    $maderesponse['commonReasonCode'] = 'PURCHASE_LIMIT_EXCEEDED';
                    $maderesponse['commonReasonMsg'] = $previewresponsearray['resultDetail'];

                    return $maderesponse;
                } else 
                if (isset($previewresponsearray['resultReason']) && $previewresponsearray['resultReason'] == "CUSTOMER_NOT_FOUND") {
                    $maderesponse = array();
                    $maderesponse['status'] = 'FAIL';
                    $maderesponse['isCommonError'] = true;
                    $maderesponse['commonReasonCode'] = 'CUSTOMER_NOT_FOUND';
                    $maderesponse['commonReasonMsg'] = 'Error while processing.Please contact support team for help';

                    return $maderesponse;
                } else
                if (isset($previewresponsearray['resultReason']) && $previewresponsearray['resultReason'] == "INACTIVE_CUSTOMER") {
                    $maderesponse = array();
                    $maderesponse['status'] = 'FAIL';
                    $maderesponse['isCommonError'] = true;
                    $maderesponse['commonReasonCode'] = 'INACTIVE_CUSTOMER';
                    $maderesponse['commonReasonMsg'] = 'Profile has been deactivated.Please contact support team for help';

                    return $maderesponse;
                }
                // else 
                // {
                //     $maderesponse = array();
                //     $maderesponse['status'] = 'FAIL';
                //     $maderesponse['isCommonError'] = true;
                //     $maderesponse['commonReasonCode'] = $previewresponsearray['resultReason'];
                //     $maderesponse['commonReasonMsg'] = $previewresponsearray['resultDetail'];
                //     return $maderesponse;
                // }

            }


            //file_put_contents('previewresponse.json', $previewresponse);
            Util::wlog('previewresponse', $previewresponse, __LINE__, false);
            $maderesponse = Self::makeResponse($madereq, $previewresponse,$data['ordertype']);
            //file_put_contents('previewmaderesponse.json', json_encode($maderesponse));
            Util::wlog('previewmaderesponse', $previewresponse, __LINE__, false);
            return $maderesponse;
        } else if ($data['ordertype'] == 'ticket') {

            //preview call
            //insert all preview order data as inactive data
            //return order id
            //place order at treez with orderid
            //update flags set to active
            $displocationdata = $data['data']['displocationdata'];
            $authData = Self::getToken($data['data']['dispensary'], $data['data']['cmp']);
            //$data['data']['tickettype'] = Self::checkTicketType($data['data']['checkoutData']['paymentType']);
            $madereq = Self::makeReqData($data);
            $madereqjson = json_encode($madereq, JSON_PRETTY_PRINT);
            $separator = "\n===========================" . date('Y-m-d H:i:s') . "======================" . PHP_EOL;
            //file_put_contents('orderslog.log', $separator, FILE_APPEND);
            //file_put_contents('orderslog.log', $madereqjson, FILE_APPEND);
            Util::wlog('orderslog', $separator);
            Util::wlog('orderslog', $madereqjson);
            $previewresponse = Self::orderApi("previewticket", $authData, $madereq);
            //file_put_contents('orderslog.log', $previewresponse, FILE_APPEND);
            Util::wlog('orderslog', $previewresponse);
            $maderesponse = Self::makeResponse($madereq, $previewresponse,$data['ordertype']);
            
            if ($maderesponse['status'] == 'SUCCESS') {
                $maderesponse = Self::modifyJSON($maderesponse);
                $maderesponse['selectedTimeSlots'] = $data['data']['checkoutData']['selectedDelSlot'];
                $disp = $data['data']['dispensary'];
                $address = $data['data']['checkoutData']['address'];
                $customer_id = $madereq['orderdata']['customer_id'];
                $ecom_custid = $madereq['orderdata']['ecom_custid'];
                $cust_order_status = $madereq['orderdata']['order_status'];
                $email = $madereq['orderdata']['email'];
                $ordertypecode = $data['data']['checkoutData']['paymentType'];
                $paydetails = [];
                @$paydetails['paytype'] = $data['data']['payment_opt'][$data['data']['paymentsourceid']];

                // if($data['data']['paymentsourceid']=='cash'){
                //     if($data['data']['checkoutData']['paymentType']=='del'){
                //         $paydetails['paytype']='Cash On Delivery';
                //     }
                //     else if($data['data']['checkoutData']['paymentType']=='pas'){
                //         $paydetails['paytype']='Pay in-store on Pickup';
                //     }
                //     else {
                //         $paydetails['paytype']='Cash';
                //     }
                // }
                // else if($data['data']['paymentsourceid']=='card'){
                //     if($data['data']['checkoutData']['paymentType']=='del'){
                //         $paydetails['paytype']='Debit Card On Delivery';
                //     }
                //     else if($data['data']['checkoutData']['paymentType']=='pas'){
                //         $paydetails['paytype']='Pay using debit card in store';
                //     }
                //     else {
                //         $paydetails['paytype']='Pay using debit card in store';
                //     }
                // }
                $params = array(
                    "dispensaryid" => $disp,
                    "address" => $address,
                    "pos_custid" => $customer_id,
                    "ecom_custid" => $ecom_custid,
                    "email" => $email,
                    "posmaderesponse" => $maderesponse,
                    "cust_order_status" => $cust_order_status,
                    "isvirtual" => $data['data']['isvirtual'],
                    "vir_dipid" => $data['data']['vir_dipid'],
                    "coupondetails"=>$data['data']['coupondetails'],
                    "paydetails"=>$paydetails,
                    "scheduled_datetime"=>$data['data']['scheduled_datetime'],
                    "device"=>$data['data']['device'],
                    "ordertypecode"=>$ordertypecode,
                );
                $params = json_encode(Util::FilterRequests($params), JSON_NUMERIC_CHECK | JSON_PRETTY_PRINT);
                //file_put_contents("prams.json", $params);
                Util::wlog('prams', $params, __LINE__, false);
                $sysparams = Util::sysParams($data['data']['cmp'], 'porder');

                $ecomorder = DBUtil::callProcedure('sp_orders', $sysparams, $params);
                Util::wlog('order_', $ecomorder);

                $ecomorderarray = json_decode($ecomorder['res'], true);

                // Add code here
                // $cspwData = DBUtil::callProcedure('sp_order_cspw', $sysparams, $ecomorderarray);
                // CSPW::cspwNewOrderApi('', $cspwData);
                if ($ecomorderarray['status'] == true) {
                    $orderid                    = $ecomorderarray['orderid'];
                    $custorderid                = $ecomorderarray['custorderid'];
                    $authData                   = Self::getToken($data['data']['dispensary'], $data['data']['cmp']);
                    //$data['data']['tickettype'] = Self::checkTicketType($data['data']['checkoutData']['paymentType']);
                    $madereq                    = Self::makeReqData($data, $custorderid);
                    Util::wlog('orderapiresponse', $madereq);
                    $previewresponse            = Self::orderApi("detailticket", $authData, $madereq);
                    Util::wlog('orderapiresponse', $previewresponse);
                    $maderesponse               = Self::makeResponse($madereq, $previewresponse,$data['ordertype']);
                    if ($maderesponse['status'] == 'SUCCESS') {
                        $params =  array(
                            'ticket_id'     => $maderesponse['ticket_id'],
                            'order_number'  => $maderesponse['order_number'],
                            'orderid'       => $orderid,
                        );
                        $params                         = json_encode($params);
                        $sysparams                      = Util::sysParams($data['data']['cmp'], 'activateorder');
                        $orderactivatedj                = DBUtil::callProcedure('sp_orders', $sysparams, $params);
                        $orderactivated                 = json_decode($orderactivatedj['res'], true);
                        $orderactivated['custorderid']  = $custorderid;

                        if ($orderactivated['status'] == true) {
                            $ecomorder = $orderactivatedj;
                        }
                        try {
                            if($data['ordertype'] == 'ticket')
                            {
                                $treez_payment_obj = ['payments' => [],'payment_authorization' => false];
                                // Alpine QI Rewards Redeem Code
                                $reward_response            = [];
                                $reward_points_amt          = 0;
                                $ticket_note                = $maderesponse['ticket_note'];
                                $ecom_payments              = [];
                                $actual_payment_gateway_res = [];

                                if(Self::checkOrGetRewards($data, true)) {
                                    $reward_response    = Self::checkOrGetRewards($data, false);
                                    Util::wlog('order_alpine_', $reward_response, __LINE__, true);
                                    $reward_points      = 0-$data['data']['reward_points'];
                                    $reward_points_amt  = $reward_response['amount_paid'];

                                    // Redeem points in Alpine IQ

                                    $alpine_res = AlpineIQ::modifyPoints(['alpine_contact_id'=> $data['data']['alpine_contact_id'],'amount'=>$reward_points,'cmp' => $data['data']['cmp'],'note' => 'Order Placed. Points Redeemed againt Order Id - #'.$maderesponse['order_number']]);
                                    //$alpine_res = true;
                                    if($alpine_res) {
                                        $ord_total_amt_withfull_reward_amt  = $maderesponse['total'] - $reward_points_amt;
                                        $ticket_note                       .= ', AlpineIQ Redeem Points = '. abs($reward_points);
                                        // Payment will be made manually by Cashier.
                                        // array_push($treez_payment_obj['payments'],[
                                        //     'payment_source'  => 'ECOMMERCE',
                                        //     'payment_method'  => 'CHECK',
                                        //     'amount_paid'     => $reward_points_amt,
                                        // ]);
                                        $ecom_payments[] = Self::makePaymentObject(['payment_method'=>'CHECK','amount'=>$reward_points_amt,'payment_status'=>'PAID','description' => abs($reward_points)],'AlpineIQ',$orderid);

                                        if($ord_total_amt_withfull_reward_amt == 0) {
                                            // Full payment is done by Rewards
                                            // return from Order Method
                                            Util::wlog('order_alpine_', $ecom_payments, __LINE__, true);
                                            goto orderupdate;
                                        }
                                    }
                                }

                                // Gift Card Code
                                $gcamount              = 0;
                                $gift_payment_response = [];
                                if(Self::checkOrUpdateGiftcard($data, $maderesponse, true)) {
                                    $gift_payment_response         = Self::checkOrUpdateGiftcard($data, $maderesponse, false);
                                    Util::wlog('order_giftcard_', $gift_payment_response, __LINE__, true);
                                    $gcamount                      = $gift_payment_response['amount_paid'];
                                    $ord_total_amt_withfull_gc_amt = $maderesponse['total'] - ($gcamount + $reward_points_amt);
                                    $ticket_note                  .= ', Gift cards = ';
                                    foreach($data['data']['giftcards'] as $key=>$value) {
                                        $ticket_note              .= $value->cardno . '(' . $value->expiry . ') | ';
                                    }
                                    $ticket_note                  .= ' GC Paid Amount =\$' . $gcamount;

                                    array_push($treez_payment_obj['payments'],[
                                        'payment_source'  => 'ECOMMERCE',
                                        'payment_method'  => 'GIFT_CARD_CUSTOM',
                                        'amount_paid'     => $gcamount,
                                    ]);
                                    $ecom_payments[] = Self::makePaymentObject(['payment_method'=>'CASH','amount'=>$gcamount,'payment_status'=>'PAID'],'Gift Card',$orderid);
                                    if($ord_total_amt_withfull_gc_amt == 0) {
                                        // Full payment is done by Gift Card.
                                        // return from Order Method
                                        Util::wlog('order_giftcard_', $ecom_payments, __LINE__, true);
                                        goto orderupdate;
                                    }
                                }

                                // Final amount for payment gateway
                                $final_amount = $maderesponse['total'] - ($reward_points_amt + $gcamount);

                                if($final_amount<0) {
                                    throw new Exception('Order placed successfully. There was an issue in final Payment Amount');
                                }

                                if($data['data']['enable_payment_gate']) {
                                    try
                                    {
                                        Util::wlog('order_stronghold_', $data, __LINE__, true);
                                        Util::wlog('order_stronghold_', $maderesponse, __LINE__, true);
                                        Util::wlog('order_stronghold_', $final_amount, __LINE__, true);
                                        $stronghold_data = Self::strongholdPayment($data,$maderesponse, $final_amount);
                                        Util::wlog('order_stronghold_', $stronghold_data, __LINE__, true);
                                        if(isset($stronghold_data['status']) && $stronghold_data['status'] === true) {
                                            $ticket_note               .= ', Stronghold ACH : Paid Amount =';
                                            @$ticket_note              .= $final_amount;
                                            $actual_payment_gateway_res = $stronghold_data['api_res'];
                                            // Remove Gift, Rewards Payment.
                                            // Treez requires full amount paid payment by all payments sources
                                            $treez_payment_obj['payments']              = []; 
                                            $treez_payment_obj['payment_authorization'] = true;
                                            $ecom_payments[]                            = Self::makePaymentObject($actual_payment_gateway_res,'Stronghold',$orderid);
                                        }  
                                        else {
                                            $ticket_note  .= ', Stronghold ACH = ';
                                            @$ticket_note .= $stronghold_data['ticket_note'];
                                        } 
                                    }
                                    catch(Exception $e) {
                                        Util::wlog('order_catch_stronghold_', $e, __LINE__, true);
                                        // Update Failed Payment status in Treez and DB.
                                        $_ecomorder         = json_decode($ecomorder['res'],true);
                                        $_ecomorder['msg']  = "Payment towards the Order could not be processed, our customer support will get back to you for processing payments";
                                        $_ecomorder['type'] = 99;
                                        $ecomorder['res']   = json_encode($_ecomorder);
                                    }
                                }
                                else if($data['data']['paymentsourceid']=='hypur') {
                                    try
                                    {
                                        Util::wlog('order_hypur_', $data, __LINE__, true);
                                        Util::wlog('order_hypur_', $final_amount, __LINE__, true);
                                        $hypur_data = Self::hypurPayment($data, $final_amount);
                                        Util::wlog('order_hypur_', $hypur_data, __LINE__, true);
                                        if(isset($hypur_data['status']) && $hypur_data['status'] === true) {
                                            if(isset($hypur_data['api_res']['result']['id'])) {
                                                $ticket_note               .= ', HYPUR ACH : Paid Amount =';
                                                @$ticket_note              .= $final_amount;
                                                $actual_payment_gateway_res = $hypur_data['api_res'];
                                                $ecom_payments[]            = Self::makePaymentObject($hypur_data['api_res']['result'],'Hypur',$orderid);
                                                if(isset($hypur_data['api_res']['result']['amount'])) {
                                                    array_push($treez_payment_obj['payments'],[
                                                        'payment_source'  => 'ECOMMERCE',
                                                        'payment_method'  => 'HYPUR_CUSTOM',
                                                        'amount_paid'     => $hypur_data['api_res']['result']['amount'],
                                                    ]);   
                                                }
                                                else {
                                                    // Need to add log here.
                                                    throw new Exception('Didnt get an amount from hypur response.');
                                                }
                                            }
                                            else {
                                                // payment response is successfull but api return some error. like (NoValidConsumerBankAccount)
                                                $error_result = $hypur_data['api_res']['result'];
                                                if(count($error_result)>0) {
                                                    $ticket_note               .= ', HYPUR ACH : Unpaid Amount = '.$final_amount.', Payment Failed Reason : '.$error_result[0]['Message'];
                                                    throw new Exception($error_result[0]['Message']);
                                                }
                                            }  
                                        }
                                        else {
                                            // This error occures when payment failed.
                                            throw new Exception('Error while processing Hypur payment.');
                                        }
                                    }
                                    catch(Exception $e) {
                                        Util::wlog('order_catch_hypur_', $e, __LINE__, true);
                                        // Update Failed Payment status in Treez and DB.
                                        $_ecomorder         = json_decode($ecomorder['res'],true);
                                        $_ecomorder['msg']  = "Payment towards the Order could not be processed, our customer support will get back to you for processing payments";
                                        $_ecomorder['type'] = 99;
                                        $ecomorder['res']   = json_encode($_ecomorder);
                                    }
                                }
                                else if($data['data']['paymentsourceid']=='swifter') {
                                    $swifterSessionData = [
                                        "orderid" => $orderid,
                                        "cmp" => $data['data']['cmp'],
                                        "dispensary" => $data['data']['dispensary'],
                                        "amount" => (int)$final_amount*100,
                                        "type" => "consumer_checkout",
                                        "consumer_info" => array(
                                            "first_name" => $data['data']['fname'],
                                            "last_name" => $data['data']['lname'],
                                            "email" => $data['data']['email'],
                                            "phone" => $data['data']['mobile']
                                        )
                                    ];
                                    $session = Swifter::create_session($swifterSessionData);
                                    $_ecomorder             = json_decode($ecomorder['res'],true);
                                    if(array_key_exists('status', $session) && $session['status'] == 0) {
                                        $_ecomorder['msg']  = "Order placed successfully. Payment could not be processed";
                                    } else {
                                        $_ecomorder['msg']  = "Order placed successfully.";
                                    }
                                    $_ecomorder['type']     = 88;
                                    $_ecomorder['session']  = $session;
                                    $ecomorder['res']       = json_encode($_ecomorder);
                                }
                                else if(in_array($data['data']['paymentsourceid'], ['cash','credit','debit','card'])) {
                                    $ticket_note                  .= ', Remaining Amount to be Paid = ';
                                    @$ticket_note                 .= $final_amount;
                                    $sourceid                      = strtoupper($data['data']['paymentsourceid']);
                                    $treez_payment_obj['payments'] = []; 
                                    $ecom_payments[] = Self::makePaymentObject(['payment_method'=>$sourceid,'amount'=>$final_amount,'payment_status'=>'UNPAID'],$sourceid,$orderid);
                                }

                                orderupdate:
                                $update_res = Self::updateTicket($authData, $data, $maderesponse, $treez_payment_obj, $ticket_note);
                                $treez_payment_status = 'UNPAID';
                                // if actual_payment_gateway_res is null then the payment has not done by hypur/stronghold 
                                if($update_res['status'] == false) {
                                    // The ticket update api has failed so paytype will not update
                                    // We store treez payment status in paytype column
                                    DB::select("update cmp".$data['data']['cmp'].".ordermaster set paytype=NULL, paydetails=('".json_encode($actual_payment_gateway_res)."')::jsonb, instruction = '".$ticket_note."' where id=(".$orderid.")::bigint;");
                                    $_ecomorder         = json_decode($ecomorder['res'],true);
                                    $_ecomorder['msg']  = "Order placed successfully.";
                                    $_ecomorder['type'] = 88;
                                    $ecomorder['res']   = json_encode($_ecomorder);
                                }
                                else if(isset($update_res['api_res']['data'])) {
                                    // The treez payment status will store in paytype column.
                                    $ticket_res = $update_res['api_res']['data'];
                                    DB::select("update cmp".$data['data']['cmp'].".ordermaster set paytype='".$ticket_res['payment_status']."', paydetails=('".json_encode($actual_payment_gateway_res)."')::jsonb, instruction = '".$ticket_note."' where id=(".$orderid.")::bigint;");
                                    $treez_payment_status = $ticket_res['payment_status'];
                                } 
                                else {
                                    // The ticket update api has failed so paytype will not update
                                    // We store treez payment status in paytype column
                                    DB::select("update cmp".$data['data']['cmp'].".ordermaster set paytype=NULL, paydetails=('".json_encode($actual_payment_gateway_res)."')::jsonb, instruction = '".$ticket_note."' where id=(".$orderid.")::bigint;");
                                }
                                DB::table("cmp".$data['data']['cmp'].".orderpayments")->insert($ecom_payments);
                                DB::table("cmp".$data['data']['cmp'].".orderpayments")->where('orderid',$orderid)->update(['treez_payment_status' => $treez_payment_status,'ticket_note'=>$ticket_note,'treez_update_response' => json_encode($update_res['api_res'])]);
                                Util::wlog('order_update_payments_', $ecom_payments, __LINE__, true);
                                try {
                                    if(DB::table("cmp".$data['data']['cmp'].".dispensary")->whereRaw("id=('".$disp."')::uuid")->whereNotNull('cspw_api_key')->count()>0)
                                    {
                                        $cspwData = DBUtil::callProcedure('sp_order_cspw', $sysparams, json_encode($ecomorderarray));
                                        Util::wlog('cspw_neworder_',$cspwData);
                                        CSPW::cspwNewOrderApi('', json_decode($cspwData['res'], true)[0]);
                                    }
                                } catch(Exception $e) {
                                    Util::wlog('order_catch_cspw_',$e->getMessage(), __LINE__, true);
                                }
                            }
                        } catch (\Throwable $th) {
                            Util::wlog('order_catch_ticket_', $th, __LINE__, true);
                            $ecomorder['res'] = json_encode(array("status" => false, "msg" => $th->getMessage(), "type" => 0));
                            return $ecomorder;
                        }
                        

                        // send mail to the customer.
                        try {
                            Self::sendOrderMail(['cmp'=>$data['data']['cmp'],'orderid'=>$orderid],'order', 'order_placed');
                        } catch (\Throwable $th) {
                            Util::wlog('order_catch_mail_', $th->getMessage(), __LINE__, true);
                        }

                        try {	
                            Self::sendOrderSms(['cmp'=>$data['data']['cmp'],'orderid'=>$orderid],'order','order_placed');	
                        } catch (\Throwable $th) {	
                            Util::wlog('sms order canceled',$th->getMessage());	
                        }
                    } 
                    else {
                        $ecomorder['res'] = json_encode(array("status" => false, "msg" => "Failed to place order", "type" => 0));
                    }
                }
            } 
            else {
                $ecomorder['res'] = json_encode(array("status" => false, "msg" => "Failed to place order", "type" => 0));
            }
            return $ecomorder;
        }
       } catch(Exception $e) {
            Util::wlog('treez_php_orders0_',$e->getMessage(), __LINE__);
            $ecomorder['res'] = json_encode(array("status" => false, "msg" => $e->getMessage(), "type" => 0));
            return $ecomorder;
       }
    }
    public static function checkTicketType($type)
    {
        $returntype = 'PICKUP';
        switch ($type) {
            case 'del':
                $returntype = 'DELIVERY';
                break;
            case 'pas':
                $returntype = 'PICKUP';
                break;
            case 'express':
                $returntype = 'EXPRESS';
                break;
            case 'curb':
                $returntype = 'EXPRESS';
                break;
            default:
                $returntype = 'PICKUP';
                break;
        }
        return $returntype;
    }
    public static function modifyJSON($maderesponse)
    {
        $items = $maderesponse['items'];
        $alltaxes = array();
        $alldiscounts = array();
        $allnames = array();
        foreach ($items as $item) {

            $puid = $item['product_id'];

            $taxes = $item['tax'];
            foreach ($taxes as $tax) {
                $itemtaxes = array(
                    "puid" => $puid,
                    "type" => 'TAX',
                    "amt_type" => 'PERCENT',
                    "rate" => $tax['rate'],
                    "name" => $tax['tax_name'],
                    "amount" => $tax['amount'],
                    "extrajson" => $tax,
                );
                array_push($alltaxes, $itemtaxes);
            }

            $discounts = $item['discounts'];
            foreach ($discounts as $discount) {
                $itemdiscounts = array(
                    "puid" => $puid,
                    "type" => 'DISCOUNT',
                    "amt_type" => $discount['discount_method'],
                    "rate" => $discount['discount_amount'],
                    "name" => $discount['discount_title'],

                    "amount" => $discount['savings'],

                    "extrajson" => $discount,
                );
                array_push($alldiscounts, $itemdiscounts);
            }

            array_push($allnames, $item['product_size_name']);
        }
        $allfees = array();
        foreach ($maderesponse['fees'] as $fee) {
            $subfees = array(
                "puid" => '',
                "type" => 'FEES',
                "amt_type" => 'DOLLAR',
                "rate" => null,
                "name" => $fee['type'],
                "amount" => $fee['total_amount'],
                "extrajson" => $fee,
            );
            array_push($allfees, $subfees);
        }

        $maderesponse['alltaxesdiscounts'] = array_merge($alltaxes, $alldiscounts, $allfees);

        $maderesponse['ordersummary'] = implode(', ', $allnames);

        return $maderesponse;
    }

    public static function makeResponse($madereq, $data,$operate=null)
    {
        $data = json_decode($data, true);
        if ($data['resultCode'] == 'FAIL') {
            $items = json_decode(json_encode($madereq['orderdata']['items']), true);
            $isCollectivePass = true;
            foreach ($items as &$item) {
                $dispensary = $madereq['dispensary'];
                $cmp = $madereq['cmp'];
                $puid = $item['size_id'];
                $qty = $item['quantity'];
                $location = isset($item['location_name']) ? $item['location_name'] : '';
                $extradata = array();
                if ($madereq['orderdata']['type'] == "DELIVERY" || $madereq['orderdata']['type'] == "EXPRESS") {
                    $extradata['delivery_address'] = $madereq['orderdata']['delivery_address'];
                }

                $stock = Self::checkProductInStock($puid, $qty, $dispensary, $cmp, $madereq['orderdata']['type'], $location, $extradata);
                $item['status'] = $stock['status'];
                if ($stock['status'] == false) {
                    $isCollectivePass = false;
                    $item['code'] = $stock['code'];
                    $item['msg'] = $stock['msg'];
                    if ($stock['code'] == 'INVENTORY_ERROR') {
                        $item['code'] = 'INSUFFICIENT_SELLABLE_QUANTITY';
                    } elseif ($stock['code'] == 'INSUFFICIENT_SELLABLE_QUANTITY') {
                        $item['availqty'] = $stock['availqty'];
                    } elseif ($stock['code'] == 'PURCHASE_LIMIT_EXCEEDED') {
                    } else {
                        $item['code'] = 'INSUFFICIENT_SELLABLE_QUANTITY';
                    }
                }
            }
            if ($isCollectivePass == false) {
                $response = array();
                $response['status'] = 'FAIL';
                $response['data'] = $items;
                $response['isCommonError'] = false;
                $response['commonReasonCode'] = '';
                return $response;
            } else {
                $previewresponsearray = $data;
                $response = array();
                $response['status'] = 'FAIL';
                $response['isCommonError'] = true;
                $response['commonReasonCode'] = 'UNKNOWN_ERROR';
                $response['commonReasonMsg'] = 'Unable to process your order. Please contact dispensary for details.';
                if (isset($previewresponsearray['resultReason']) && isset($previewresponsearray['resultDetail'])) {
                    $response['actualReason'] = $previewresponsearray['resultReason'] . "|" . $previewresponsearray['resultDetail'];
                }

                return $response;
            }
        }

        $apiresponse = $data['data'];
        $response = array();
        $discountCategory = null;
        $discount_saving = 0;
        foreach ($apiresponse['items'] as &$item) {
			// get discount label for front end
            if($item['apply_automatic_discounts']===false){
                $discountCategory = (count($item['discounts'])>0)?$item['discounts'][0]['discount_category']:null;
                $sel_req_item=array_filter($madereq['orderdata']['items'], function($element) use($item,$discountCategory){
                    return ($element->{'size_id'}==$item['size_id'] && count($item['discounts'])>0 && $discountCategory==$element->{'discount_type'});
                }); 
                if(count($sel_req_item)>0){
                    @$item['discount_lbl'] .='<ul>';
                    foreach($sel_req_item as $c){
                        if(empty($c->{'discount_lbl'})) continue;
                        @$item['discount_lbl'] .= "<li class='".$c->{'discount_lbl_class'}."'>".$c->{'discount_lbl'}."</li>";
                        if($operate=='ticket') {
                            $item['discount_id']=$c->discount_id;
                        }
                    }
                    @$item['discount_lbl'] .='</ul>';
                }
                else {
                    foreach($madereq['orderdata']['items'] as $i) {
                        if($i->size_id == $item['size_id']) {
                            $item['discount_id']=$i->discount_id;
                            $item['coupon_id']=$i->coupon_id;
                        }
                    }
                }
                $item['discount_medium']= (count($item['POS_discounts'])>0) ? 'Ecommerce':'';
            } else {
                $fil_discount = array_filter($item['discounts'],function($element){
                    return $element['discount_category'] != 'TIER_DISCOUNT';
                });
                $item['discount_medium']= (count($fil_discount)>0) ? 'In-Store':'';
                $item['discount_lbl']='';
                if($operate=='ticket') {
                    $item['discount_id']=0;
                }
            }
			
            $item['code'] = '';
            $item['tax_sum'] = 0;
            $item['discount_sum'] = 0;
            //$tax_sum = 0
            foreach ($item['tax'] as $it) {
                $item['tax_sum'] += $it['amount'];
            }
            foreach ($item['discounts'] as $dc) {
                if($dc['discount_category']!='TIER_DISCOUNT') {
                    $item['discount_sum'] += $dc['savings'];
                }
                $discount_saving += $dc['savings'];
            }
            //code for subtotal if automatic discount always true
            $item['price_sell']   = Self::calculateProductPrice($item['price_total'], $item['price_sell'],$item['tax'], $item['discounts']);
            // end
        }

        $totalextrafees = 0;
        foreach ($apiresponse['fees'] as $fee) {
            $totalextrafees += $fee['total_amount'];
        }

        $response['status'] = 'SUCCESS';
        $response['type'] = $apiresponse['type'];
        $response['ticket_id'] = $apiresponse['ticket_id'];
        $response['order_number'] = $apiresponse['order_number'];
        $response['customer_id'] = $apiresponse['customer_id'];
        $response['ticket_patient_type'] = $apiresponse['ticket_patient_type'];
        $response['order_status'] = $apiresponse['order_status'];
        $response['post_tax_pricing'] = $apiresponse['post_tax_pricing'];
        $response['sub_total'] = round($apiresponse['sub_total'] + abs($apiresponse['discount_total']),2);
        $response['tax_total'] = $apiresponse['tax_total'];
        $response['discount_total'] = $apiresponse['discount_total'];
        $response['total'] = $apiresponse['total'];
        $response['delivery_address'] = $apiresponse['delivery_address'];
        $response['items'] = $apiresponse['items'];
        $response['purchase_limit'] = $apiresponse['purchase_limit'];
        $response['ticket_note'] = $apiresponse['ticket_note'];
        $response['fees'] = $apiresponse['fees'];
        $response['totalextrafees'] = $totalextrafees;
        return $response;
    }

    public static function calculateProductPrice($price_total, $price_sell, $taxes, $discounts) {
        $product_price = $price_total;
        $final_discount = 0;
        for($i=count($taxes)-1;$i>=0;$i--) {
            $taxrow = $taxes[$i];
            $taxrate = 100 + ($taxrow['rate']*100);
            $product_price = ($product_price*100)/$taxrate;
        }
        foreach($discounts as $discount) {
            $discount_amount = $discount['discount_amount'];
            $discount_price  = ($product_price * $discount_amount)/100;
            // If discount is 40% then out of 100% (100-40)= 60%
            $final_discount += ($discount_price*100)/(100-$discount_amount);
        }
        return round($final_discount + $price_sell,2);
    }

    public static function makeReqData($param, $externalorderid = '')
    {
        $data = $param['data'];
        $add = array(
            "street" => "",
            "city" => "",
            "county" => "",
            "state" => "",
            "zip" => "",
        );
        if (isset($data['checkoutData']) && ($data['checkoutData']['paymentType'] == 'del' || $data['checkoutData']['paymentType'] == 'express')) {
            $address = $data['checkoutData']['address']['addressobject'];
            $add = array(
                "street" => $address['street'] . ' ' . $address['apartment'],
                "city" => $address['city'],
                //"county" => $address['country'],
                "state" => $address['state'],
                "zip" => $address['zip'],
            );
        }
        $items = array();
        if (isset($data['sql']) && sizeof($data['sql']) > 0) {
            $items = $data['sql'];
            foreach ($items as &$item) {
                if (isset($item->location_name)) {
                    if (trim($item->location_name) == '' || $item->location_name == null) {
                        unset($item->location_name);
                    }
                }
            }
        }
        $orderdata = array(
            "type" => $data['tickettype'],
            "order_source" => "ECOMMERCE",
            "customer_id" => $data['pos_custid'],
            "ecom_custid" => $data['ecom_custid'],
            "email" => $data['email'],
            "order_status" => $data['orderstatus'],
            "revenue_source"=>'E-commerce',
            "items" => $items,
            "delivery_address" => null,
        );
        if (isset($data['checkoutData']) && $data['checkoutData']['paymentType'] == 'del') {
            $orderdata['delivery_address'] = $add;
            $orderdata['scheduled_date'] = $data['scheduled_timestamp'];
        }
        if (isset($data['checkoutData']) && $data['checkoutData']['paymentType'] == 'express') {
            $orderdata['delivery_address'] = $add;
        }
        if ($param['ordertype'] == 'ticket') {
            $orderdata['external_order_number'] = $externalorderid;
            $orderdata['ticket_note'] = $data['checkoutData']['instructions'];
        }

        $posreq = array(
            //"method"=>"orders",
            "flag" => "getToken",
            "integration" => "treez",
            "cmp" => $data['cmp'],
            "dispensary" => $data['dispensary'],
            //"ordertype"=>"preview",
            "orderdata" => $orderdata,
        );
        return $posreq;
    }
    public static function orderApi($urltype, $authData, $data)
    {
        //https://api.treez.io/v2.0/dispensary/partnersandbox2/ticket/detailticket
        //$ENV = $_ENV;
        //$apipath = config('app.TREEZ_URL');
        $maxTries = 3;
        $try = 1;

        $envcache = Util::envCredential($data['cmp']);
        if(empty($envcache->treezurl)){
            Util::wlog('error_treezenv', 'Treez Url are missing ');
            throw new Exception("Treez Url are missing ");
        }
        $pos_url = $envcache->treezurl; //Self::$api_url;
        $url = $pos_url . $authData['integDispId'] . "/ticket/" . $urltype;
        //'https://api.treez.io/v2.0/dispensary/' . $_token['integDispId'] . '/config/api/gettokens'
        //file_put_contents('apicallurl.log',date('Y-m-d H:i:s').'|'.$url.PHP_EOL,FILE_APPEND);
        Util::wlog('apicallurl', date('Y-m-d H:i:s') . '|' . $url . PHP_EOL);
        $rawparams = json_encode($data['orderdata']);

        $header = array(
            'Content-Type:  application/json',
            'authorization: ' . $authData['access_token'],
            'client_id: ' . $authData['integClientID'],
        );
        retrylabel:
        $response = Util::HandleCurl('POST', $header, $rawparams, $url);
        $res = $response;
        $decoded = json_decode($response, true);
        if (isset($decoded['fault'])) {
            if ($try <= $maxTries) {
                $try++;
                sleep(1);
                goto retrylabel;
            }
        }

        if (isset($decoded['fault'])) {
            $res = '{"resultCode":"FAIL","resultReason":Spike arrest,"resultDetail":null}';
        }

        if ($response == false) {
            $res = '{"resultCode":"FAIL","resultReason":null,"resultDetail":null}';
        }
        return $res;
        //print_r(json_encode(json_decode($response),JSON_PRETTY_PRINT));

    }

    public static function isInStock($data)
    {
        //deprecated function
        $puid = $data['data']['product']['puid'];
        $authData = Self::getToken($data['data']['dispensary'], $data['data']['cmp']);

        $header = array(
            'Authorization:' . $authData['access_token'],
            'client_id:' . $authData['integClientID'],
        );
        $envcache = Util::envCredential($data['data']['cmp']);
        if(empty($envcache->treezurl)){
            Util::wlog('error_treezenv', 'Treez Url are missing ');
            throw new Exception("Treez Url are missing ");
        }
        //$url = Self::$api_url . $authData['integDispId'] . "/product/" . $puid;
        $url = $envcache->treezurl . $authData['integDispId'] . "/product/" . $puid;
        $response = Util::HandleCurl('GET', $header, null, $url);
        $response = json_decode($response, true);
        if ($response['resultCode'] == "FAIL" && $response["resultReason"] == "INSUFFICIENT_SELLABLE_QUANTITY") {
            $exp = explode(" ", $response['resultDetail']);
            $requested = $exp[3];

            $res = array(
                "resultCode" => "FAIL",
                "resultReason" => "INSUFFICIENT_SELLABLE_QUANTITY",
                "available" => rtrim($exp[12], '.'),
                "product_id" => $exp[7],
                "data" => null,
            );
        } else {
            $sellable_qty = $response['data']['sellable_quantity'];
            $product_id = $response['data']['product_id'];
            $res = array(
                "resultCode" => "SUCCESS",
                "resultReason" => "AVAILABLE_SELLABLE_QUANTITY",
                "available" => $sellable_qty,
                "product_id" => $product_id,
                "data" => null,
            );
        }
        return $res;
    }
    public static function callInStock($data)
    {

        if (isset($data['data']['callfrom']) && $data['data']['callfrom'] == 'addtocart') {
            $response = array('status' => true);
        } else {
            $puid = $data['data']['product']['puid'];
            $qty = $data['data']['product']['qty'];
            $dispensary = $data['data']['product']['dispensaryid'];
            $cmp = $data['data']['cmp'];
            $ordertype = Self::checkTicketType($data['data']['ordertype']);
            $response = Self::checkProductInStock($puid, $qty, $dispensary, $cmp, $ordertype, 'DELIVERY-PLATFORM');
        }
        return $response;
    }

    private static function checkProductInStock($productid, $qty, $dispensary, $cmp, $ordertype, $location = '', $extradata)
    {
        $authData = Self::getToken($dispensary, $cmp);
        $header = array(
            'Content-Type:  application/json',
            'Authorization:' . $authData['access_token'],
            'client_id:' . $authData['integClientID'],
        );

        $orderData = array(
            'type' => $ordertype,
            'external_order_number' => '000000',
            'order_source' => 'ECOMMERCE',
            'order_status' => 'AWAITING_PROCESSING',
            "revenue_source" => "E-commerce",
            'items' => array(
                array(
                    'size_id' => $productid,
                    'quantity' => $qty,
                )
            ),
        );
        if ($ordertype == "DELIVERY" || $ordertype == "EXPRESS") {
            $orderData['delivery_address'] = $extradata['delivery_address'];
        }
        // if (isset($authData['location'])) {
        //     $location = $authData['location'];
        //     $currentLoc = Self::getLocationName($ordertype, $location);
        //     $orderData['items'][0]['location_name'] = $currentLoc;
        // }
        if ($location != '') {
            $orderData['items'][0]['location_name'] = $location;
        }

        $orderData = json_encode($orderData);
        $envcache = Util::envCredential($cmp);
        if(empty($envcache->treezurl)){
            Util::wlog('error_treezenv', 'Treez Url are missing ');
            throw new Exception("Treez Url are missing ");
        }
        //$url = Self::$api_url . $authData['integDispId'] . "/ticket/previewticket";
        $url = $envcache->treezurl . $authData['integDispId'] . "/ticket/previewticket";
        $response = Util::HandleCurl('POST', $header, $orderData, $url);
        $response = json_decode($response, true);

        $resArr = array('status' => true);

        if (isset($response['resultCode']) && $response['resultCode'] == 'FAIL') {
            if(isset($response['resultDetail'])){
                $err = $response['resultDetail'];    
            }else{
                $err = '';
            }
            if ($response['resultReason'] == 'INSUFFICIENT_SELLABLE_QUANTITY' || $response['resultReason'] == 'ERROR_RESERVING_INVENTORY') {

                // $sizeid_start =  strpos($err,"size_id") + 7 ;
                $sizeid_end = strpos($err, "sellable quantity") + 17;
                $sizeid_end_qwend = strpos($err, ". Please");

                // $product_id = substr($data, $sizeid_start, 37);
                $availqty = trim(substr($err, $sizeid_end, $sizeid_end_qwend - $sizeid_end));
                $resArr = array('status' => false, 'availqty' => $availqty, 'msg' => $err, 'code' => $response['resultReason']);
                if ($availqty == 0 || $response['resultReason'] == 'ERROR_RESERVING_INVENTORY') {
                    $resArr = array('status' => false, 'availqty' => $availqty, 'msg' => $err, 'code' => 'OUT_OF_STOCK');
                }
            } elseif ($response['resultReason'] == 'INVENTORY_ERROR') {
                $resArr = array('status' => false, 'availqty' => 0, 'msg' => $response['resultReason'] . '|' . $err, 'code' => 'INSUFFICIENT_SELLABLE_QUANTITY');
            } elseif ($response['resultReason'] == 'PURCHASE_LIMIT_EXCEEDED') {

                $resArr = array('status' => false, 'msg' => $err, 'code' => $response['resultReason']);
            } else {
                $resArr = array('status' => false, 'availqty' => 0, 'msg' => $response['resultReason'] . '|' . $err, 'code' => 'INSUFFICIENT_SELLABLE_QUANTITY');
            }
        }

        return $resArr;
    }

    private static function getLocationName($ordertype, $locationarray)
    {

        if ($ordertype == "DELIVERY") {
            $ordertype = "del";
        } else {
            $ordertype = "pas";
        }

        for ($i = 0; $i < count($locationarray); $i++) {
            # code...
            $element = $locationarray[$i];
            if ($element['ordertype'] == $ordertype) {
                return $element['location'];
                break;
            }
        }
        return "";
    }

    public static function syncProducts($data)
    {
        ini_set('max_execution_time', 0);
        $params = [];
        $totalSyncedInventory = 0;
        //$queryParams = 'client_id=' . $data['client_id'] . '&apikey=' . $data['apikey'];
        $sql = DBUtil::callFunction('fn_lastsync', '{"schema":"cmp' . $data['cmp'] . '","operate":"ddl"}', json_encode($params));
        $lastsyncdate = null;
        if (!empty($result)) {
            return ['status' => 0, 'result' => $sql[0], 'errorcode' => null, 'msg' => null];
        } else {
            /** check auth token */
            //$token=Self::checkToken($params);
            $authData = Self::getToken($data['dispensary'], $data['cmp']);
            $header = array(
                'Authorization:' . $authData['access_token'],
                'client_id:' . $authData['integClientID'],
            );
            $flag = true;
            $page = 1;
            $products = array();
            do {
                $envcache = Util::envCredential($data['cmp']);
                if(empty($envcache->treezurl)){
                    Util::wlog('error_treezenv', 'Treez Url are missing ');
                    throw new Exception("Treez Url are missing ");
                }
                $url = $lastsyncdate == null ? $envcache->treezurl . $authData['integDispId'] . "/product/product_list?category_type=all&page=$page&pagesize=50" : $envcache->treezurl . $authData['integDispId'] . "/product/product_list/lastUpdated/after/$lastsyncdate?category_type=all&page=$page&pagesize=50";
                //$url = $lastsyncdate == null ? Self::$api_url . $authData['integDispId'] . "/product/product_list?category_type=all&page=$page&pagesize=50" : Self::$api_url . $authData['integDispId'] . "/product/product_list/lastUpdated/after/$lastsyncdate?category_type=all&page=$page&pagesize=50";

                $response1 = Util::HandleCurl('GET', $header, null, $url);

                $response = json_decode($response1);
                if (!isset($response->data)) {
                    $str = $page;
                    file_put_contents('syncproduct.log', print_r($response1, true), FILE_APPEND);
                    $flag = false;
                }
                // else if (sizeof($response->data->product_list) < 50) {
                //     $flag = false;
                // }
                else {
                    $products = array_merge($products, $response->data->product_list);
                    $page++;
                }
                sleep(1);
            } while ($flag);

            $productdtl = array();

            $guid = dechex(microtime(true) * 1000) . bin2hex(random_bytes(8));
            $qry = '';
            foreach ($products as $k => $value) {
                if (!isset($value->e_commerce)) {
                    continue;
                }
                if (!$value->e_commerce->hide_from_menu) {
                    $allImages = $value->e_commerce->all_images;
                    $primaryImage = $value->e_commerce->primary_image;
                    // Remove Primary Image element from $allImages array
                    $f_all_images = array_diff($allImages, [$primaryImage]);
                    $img2 = null;
                    $img3 = null;
                    if (count($f_all_images) >= 1) {
                        $img2 = $f_all_images[0];
                        $img3 = (isset($f_all_images[1])) ? $f_all_images[1] : null;
                    }

                    $productdtl[$value->product_id] = [
                        "processid" => $guid,
                        "product_id" => $value->product_id,
                        "product_status" => $value->product_status,
                        "category_type" => $value->category_type,
                        "amount" => isset($value->product_configurable_fields->amount) ? floatval($value->product_configurable_fields->amount) : 0.00,
                        "brand" => isset($value->product_configurable_fields->brand) ? trim($value->product_configurable_fields->brand) : "",
                        "classification" => isset($value->product_configurable_fields->classification) ? $value->product_configurable_fields->classification : "",
                        "name" => $value->product_configurable_fields->name,
                        "size" => isset($value->product_configurable_fields->size) ? floatval($value->product_configurable_fields->size) : 0.00,
                        "subtype" => isset($value->product_configurable_fields->subtype) ? $value->product_configurable_fields->subtype : "",
                        "total_mg_cbd" => isset($value->product_configurable_fields->total_mg_cbd) ? floatval($value->product_configurable_fields->total_mg_cbd) : 0.00,
                        "total_mg_thc" => isset($value->product_configurable_fields->total_mg_thc) ? floatval($value->product_configurable_fields->total_mg_thc) : 0.00,
                        "uom" => isset($value->product_configurable_fields->uom) ? $value->product_configurable_fields->uom : null,
                        "price_sell" => isset($value->pricing->price_sell) ? $value->pricing->price_sell : Self::ProcessSellingPrice($value->pricing->tier_pricing_detail),
                        "tier_price" => isset($value->pricing->tier_pricing_detail) ? $value->pricing->tier_pricing_detail : null,
                        "attr_general" => isset($value->attributes->general) ? $value->attributes->general : null,
                        "attr_flavors" => isset($value->attributes->flavors) ? $value->attributes->flavors : null,
                        "attr_effects" => isset($value->attributes->effects) ? $value->attributes->effects : null,
                        "attr_ingredients" => isset($value->attributes->ingredients) ? $value->attributes->ingredients : null,
                        "attr_internal_tags" => isset($value->attributes->internal_tags) ? $value->attributes->internal_tags : null,
                        "product_barcodes" => is_array($value->product_barcodes) ? Self::ProcessProductBarCode($value->product_barcodes) : null,
                        "images" => $value->e_commerce->all_images,
                        "menu_title" => $value->e_commerce->menu_title,
                        "product_description" => $value->e_commerce->product_description,
                        "dispensaryid" => $data['dispensary'],
                        "published" => ($value->e_commerce->hide_from_menu != 1) ? 'true' : 'false',
                        "sellableqty" => floatval(($value->sellable_quantity == 'null') ? 0 : $value->sellable_quantity),
                        "img2" => $img2,
                        "img3" => $img3,
                        "primary_image" => ($value->e_commerce->primary_image == 'null') ? null : $value->e_commerce->primary_image,
                    ];
                    //array_push($productdtl, );
                }
            }

            $groupProduct = array_values($productdtl);

            $strproductdtl = json_decode(str_replace("'", "''", json_encode($groupProduct)));
            // echo sizeof($productdtl);
            // exit;
            //echo json_encode($groupProduct);

            $sql = DBUtil::callProcedure('sp_savetreezproduct', Util::sysParams($data['cmp'], 'crud'), json_encode($strproductdtl));
            $totalSyncedInventory = count($productdtl);
            return ['status' => 1, 'result' => $sql, 'errorcode' => null, 'msg' => null, 'totalSynced' => $totalSyncedInventory];
        }
    }

    /**
     * Get Customer details by Customerid
     */
    public static function getCustomerById($data)
    {
        /** check auth token */
        $authData = Self::getToken($data['dispensary'], $data['cmp']);
        $header = array(
            'Authorization:' . $authData['access_token'],
            'client_id:' . $authData['integClientID'],
        );

        $envcache = Util::envCredential($data['cmp']);
        if(empty($envcache->treezurl)){
            Util::wlog('error_treezenv', 'Treez Url are missing ');
            throw new Exception("Treez Url are missing ");
        }
        $maxTries = 3;
        $try = 1;
        retrylabel:
        //$response = Util::HandleCurl('GET', $header, null, Self::$api_url . $authData['integDispId'] . '/customer/' . $data['customer_id']);
        $response = Util::HandleCurl('GET', $header, null, $envcache->treezurl . $authData['integDispId'] . '/customer/' . $data['customer_id']);
        $result = json_decode($response, true);
        if (isset($result['fault'])) {
            if ($try <= $maxTries) {
                $try++;
                sleep(1);
                goto retrylabel;
            }
        }
        return $result;
    }

    /**
     * Get Customer details by -
     * email    -  params (email={{value}})
     * phone number params (phone={{value}})
     * driving licence params (driverlicense={{value}})
     */
    public static function getCustomerByParam($data)
    {
        /** check auth token */
        $authData = Self::getToken($data['dispensary'], $data['cmp']);
        $header = array(
            'Authorization:' . $authData['access_token'],
            'client_id:' . $authData['integClientID'],
        );
        $envcache = Util::envCredential($data['cmp']);
        if(empty($envcache->treezurl)){
            Util::wlog('error_treezenv', 'Treez Url are missing ');
            throw new Exception("Treez Url are missing ");
        }
        $maxTries = 3;
        $try = 1;
        retrylabel:
        //$response = Util::HandleCurl('GET', $header, null, Self::$api_url . $authData['integDispId'] . '/customer/' . $data['param_key'] . '/' . $data['param_value']);
        $response = Util::HandleCurl('GET', $header, null, $envcache->treezurl . $authData['integDispId'] . '/customer/' . $data['param_key'] . '/' . $data['param_value']);
        $decoded = json_decode($response, true);
        if (isset($decoded['fault'])) {
            if ($try <= $maxTries) {
                $try++;
                sleep(1);
                goto retrylabel;
            }
        }
        if (isset($decoded['fault'])) {
            $decoded = ["resultCode" => "FAIL", "resultDetail" => 'Spike arrest'];
        }

        if ($response == false) {
            $decoded = ["resultCode" => "FAIL", "resultDetail" => 'No response from Api'];
        }
        Util::wlog('createCustomer', $response);
        //file_put_contents('createCustomer.log', $response, FILE_APPEND);
        return $decoded;
    }

    public static function checkCustomer($data)
    {
        $sql = DB::select("select ic.*,c.mobile,c.email,c.fname,c.lname,c.dob,temp.code2d as state,c.banned, ic.banned as dispban FROM cmp" . $data['cmp'] . ".integratedcustomer ic INNER JOIN cmp" . $data['cmp'] . ".customer c ON c.id=ic.custid LEFT JOIN (select id,name,code3d,code2d from sys.geolocation where type=3 and parentid=231) temp ON temp.id=c.state where ic.custid=" . $data['customer_id'] . " and ic.dispensaryid=('" . $data['dispensary'] . "')::uuid and ic.isactive=true LIMIT 1");
        if (count($sql) == 0) {
            $sql_1 = DBUtil::callFunction('fn_customer', Util::sysParams($data['cmp'], 'custfulldetail'), json_encode($data));
            if (count($sql_1[0]) == 0) {
                return Self::customerResponse(0, null, 'Customer doesnot exist.', 'FAIL', 'Customer doesnot exist.', null);
            }
            $result_1 = (array) $sql_1[0][0];

            $primeaddress = (array) json_decode($result_1['primeaddress']);
            $seconddress = (array) json_decode($result_1['seconddress']);
            $thrdddress = (array) json_decode($result_1['thrdddress']);
            // Data object for create customer
            $requestData = [
                'first_name' => $result_1['fname'],
                'last_name' => $result_1['lname'],
                'nickname' => $result_1['nickname'],
                'gender' => $result_1['gender'],
                'email' => $result_1['email'],
                'phone' => substr($result_1['mobile'], strlen($result_1['mobile']) - 10),
                'banned' => 'false',
                //'birthday' => (empty($result_1['dob']))?'1970-01-01':$result_1['dob'],
                'birthday' => $result_1['dob'],
                'drivers_license' => $result_1['drivlice'],
                'drivers_license_expiration' => $result_1['licexpdate'],
                'patient_type' => ($result_1['isadultuse']) ? 'ADULT' : 'MEDICAL_MMID',
                'status' => 'ACTIVE',
                'addresses' => [
                    [
                        'type' => 'ADDRESS_OF_RECORD',
                        'street1' => $primeaddress['street'],
                        'street2' => $primeaddress['apartmnt'],
                        'city' => $primeaddress['city'],
                        'state' => $primeaddress['state'],
                        'primary' => 'true',
                        'zipcode' => $primeaddress['zip'],
                    ],
                    // ,
                    //     [
                    //         'type' => 'ALTERNATIVE_ADDRESS',
                    //         'street1' => $seconddress['street'],
                    //         'city' => $seconddress['city'],
                    //         'state' => $seconddress['state'],
                    //         'primary' => 'false',
                    //         'zipcode' => $seconddress['zip'],
                    //     ],
                    //     [
                    //         'type' => 'SECONDARY_ADDRESS',
                    //         'street1' => $thrdddress['street'],
                    //         'city' => $thrdddress['city'],
                    //         'state' => $thrdddress['state'],
                    //         'primary' => 'false',
                    //         'zipcode' => $thrdddress['zip'],
                    //     ],
                ]
            ];

            if (!$result_1['isadultuse']) {
                $requestData['state_medical_id'] = $result_1['stmedid'];
                $requestData['permit_expiration'] = $result_1['medexpdate'];
            }

            $response = Self::createCustomer($requestData, $data);
            $response['profileData']=[
                    'mobile'=>$result_1['mobile'],
                    'email'=>$result_1['email'],
                    'fname'=>$result_1['fname'],
                    'lname'=>$result_1['lname'],
                    'country'=>'US',
                    'state'=>$primeaddress['state'],
                    'dob'=>$result_1['dob']
            ];
        } else {
            $result = (array) $sql[0];
            if ($result['banned']==true) {
                return Self::customerResponse(0, null, 'Cannot process the order, Please contact dispensary.', 'FAIL', 'Cannot process the order, Please contact dispensary.', 'banned_customer');
            }
            if ($result['dispban']==true) {
                return Self::customerResponse(0, null, 'Your account has been suspended, Please contact dispensary.', 'FAIL', 'Your account has been suspended, Please contact dispensary.', 'banned_customer');
            }
            if ($data['orderapi'] == 'ticket') {
                $reqData = json_decode(json_encode($data), true);
                $reqData['poscustid'] = $result['poscustid'];
                $verifiedCustData = Self::verifyCustomerDetails($reqData, $result);

                if ($verifiedCustData['resultCode'] == 'SUCCESS') {
                    $cdata = $verifiedCustData['data'];
                    if ($cdata['status'] == "ACTIVE") {
                        if ($cdata['verification_status'] == 'VERIFICATION_PENDING') {
                            if ($cdata['verification_reason'] == 'EXPIRATION') {
                                $response = Self::customerResponse(0, null, $cdata['verification_reason_description'], 'FAIL', $cdata['verification_reason_description'], null);
                                // Terminate Order Operation
                            } else if ($cdata['verification_reason'] == 'NEW') {
                                $response = Self::customerResponse(1, $result['poscustid'], null, 'SUCCESS', null, ['orderstatus' => 'VERIFICATION_PENDING']);
                                // Continue to order with status verification pending
                            } else {
                                $response = Self::customerResponse(1, $result['poscustid'], null, 'SUCCESS', null, ['orderstatus' => 'VERIFICATION_PENDING']);
                                // Continue to order with status verification pending
                            }
                        } else // Verified Customer
                        {
                            $response = Self::customerResponse(1, $result['poscustid'], null, 'SUCCESS', null, ['orderstatus' => 'AWAITING_PROCESSING']);
                            // Continue to order with status Awaiting Process
                        }
                    } 
                    else if ($cdata['status'] == "MERGED" && $cdata['verification_status'] == 'VERIFIED') {
                        $response = Self::customerResponse(1, $result['poscustid'], null, 'SUCCESS', null, ['orderstatus' => 'AWAITING_PROCESSING']);
                        // Continue to order with status Awaiting Process
                    } 
                    else if ($cdata['status'] == "MERGED" && $cdata['verification_status'] !== 'VERIFIED') {
                        $response = Self::customerResponse(1, $result['poscustid'], null, 'SUCCESS', null, ['orderstatus' => 'VERIFICATION_PENDING']);
                        // Continue to order with status verification pending
                    }
                    else if ($cdata['status'] == "DEACTIVATED") {
                        $response = Self::customerResponse(0, $result['poscustid'], 'Customer is Deactivated in POS', 'FAIL', 'CUSTOMER_DEACTIVATED', null);
                        // Terminate Order Operation
                    } else if ($cdata['status'] == "PATIENT_TYPE_UPDATED") {
                        $response = Self::customerResponse(1, $result['poscustid'], null, 'SUCCESS', null, ['orderstatus' => 'VERIFICATION_PENDING']);
                    } else {
                        $response = Self::customerResponse(1, $result['poscustid'], 'Error while validating Customer', 'FAIL', 'ERROR_IN_VALIDATE_CUSTOMER', null);
                        // Terminate Order Operation
                    }
                } else {
                    $response = Self::customerResponse(0, null, $verifiedCustData['error'], 'FAIL', $verifiedCustData['error'], null);
                }
            } else {
                $response = Self::customerResponse(1, $result['poscustid'], null, 'SUCCESS', null, ['orderstatus' => 'VERIFICATION_PENDING']);
            }

            $response['profileData']=[
                'mobile'=>$result['mobile'],
                'email'=>$result['email'],
                'fname'=>$result['fname'],
                'lname'=>$result['lname'],
                'country'=>'US',
                'state'=>$result['state'],
                'dob'=>$result['dob']
            ];
        }
        Util::wlog('createCustomer', $response);
        //file_put_contents('createCustomer.log', json_encode($response), FILE_APPEND);
        return $response;
    }

    public static function createCustomer($requestData, $data)
    {
        /** check auth token */
        $authData = Self::getToken($data['parent_dispid'], $data['cmp']);
        $header = array(
            'Authorization:' . $authData['access_token'],
            'client_id:' . $authData['integClientID'],
            'content-type: application/json',
        );

        // Check customer is already exist in POS.
        // return false = customer not exist.
        // return true = customer is exist.
        $separator = "\n===========================" . date('Y-m-d H:i:s') . "======================" . PHP_EOL;
        Util::wlog('createCustomer', $separator);
        // file_put_contents('createCustomer.log', $separator, FILE_APPEND);
        try {
            $validate = Self::validateCustomer($requestData, $data);
            if (isset($validate['error']) && $validate['error'] == true) {
                $logmsg = json_encode(['type' => 'Error while Validate Customer', 'desc' => $validate['message']], JSON_PRETTY_PRINT);
                Util::wlog('createCustomer', $logmsg);
                //file_put_contents('createCustomer.log', $logmsg, FILE_APPEND);
                return Self::customerResponse(0, 0, 'Error while Validate Customer', 'FAIL', 'Error while Validate Customer', null);
            }
            if (!$validate['exist']) {
                $requestDataJson = json_encode($requestData, JSON_PRETTY_PRINT);
                Util::wlog('createCustomer', $requestDataJson);
                //file_put_contents('createCustomer.log', $requestDataJson, FILE_APPEND);
                $envcache = Util::envCredential($data['cmp']);
                if(empty($envcache->treezurl)){
                    Util::wlog('error_treezenv', 'Treez Url are missing ');
                    throw new Exception("Treez Url are missing ");
                }
                $maxTries = 3;
                $try = 1;
                retrylabel:
                //$response = Util::HandleCurl('POST', $header, json_encode($requestData), Self::$api_url . $authData['integDispId'] . '/customer/detailcustomer');
                $response = Util::HandleCurl('POST', $header, json_encode($requestData), $envcache->treezurl . $authData['integDispId'] . '/customer/detailcustomer');
                Util::wlog('createCustomer', $response);
                //file_put_contents('createCustomer.log', $response, FILE_APPEND);
                $result = json_decode($response, true);

                if (isset($result['fault'])) {
                    if ($try <= $maxTries) {
                        $try++;
                        sleep(1);
                        goto retrylabel;
                    }
                }
                if (isset($result['fault'])) {
                    Util::wlog('createCustomer', 'Spike arrest');
                    //file_put_contents('createCustomer.log', 'Spike arrest', FILE_APPEND);
                    return Self::customerResponse(0, 0, 'Spike arrest', 'FAIL', 'Spike arrest', null);
                }
                if ($response == false) {
                    Util::wlog('createCustomer', 'Spike arrest');
                    //file_put_contents('createCustomer.log', 'Spike arrest', FILE_APPEND);
                    return Self::customerResponse(0, 0, null, 'FAIL', 'No response from APi', null);
                }

                if ($result['resultCode'] == "SUCCESS") {
                    $row = $result['data'];
                    $uploadData = [
                        'poscustid' => $row['customer_id'],
                        'dispensary' => $data['parent_dispid'],
                        'cmp' => $data['cmp'],
                        'custid' => $data['customer_id']
                    ];
                    $uploadedDoc = Self::uploadDocument($uploadData);
                    // Document status will update from node api
                    // if (count($uploadedDoc) > 0) {
                    //     $implodeId = implode(",", $uploadedDoc);
                    //     DB::select("update cmp" . $data['cmp'] . ".documents set isuploaded=true where id in (" . $implodeId . ")");
                    // }

                    // DB::select("insert into cmp" . $data['cmp'] . ".integratedcustomer(custid,poscustid,dispensaryid,createdon,isactive,isdelete) VALUES (" . $data['customer_id'] . "," . $row['customer_id'] . ",('" . $data['dispensary'] . "')::uuid,current_timestamp,true,false)");
                    DB::select("insert into cmp" . $data['cmp'] . ".integratedcustomer(custid,poscustid,dispensaryid,createdon,isactive,isdelete,updatedon) VALUES (" . $data['customer_id'] . "," . $row['customer_id'] . ",('" . $data['dispensary'] . "')::uuid,current_timestamp,true,false,current_timestamp) on conflict(custid,poscustid,dispensaryid) do update set isactive=true,updatedon=current_timestamp");
                    return Self::customerResponse(1, $row['customer_id'], null, 'SUCCESS', null, ['orderstatus' => 'VERIFICATION_PENDING']);
                } else {
                    Util::wlog('createCustomer', $result);
                    //file_put_contents('createCustomer.log', $result, FILE_APPEND);
                    return $result;
                }
            } else {
                // DB::select("insert into cmp" . $data['cmp'] . ".integratedcustomer(custid,poscustid,dispensaryid,createdon,isactive,isdelete) VALUES (" . $data['customer_id'] . "," . $validate['customerid'] . ",('" . $data['dispensary'] . "')::uuid,current_timestamp,true,false)");
                DB::select("insert into cmp" . $data['cmp'] . ".integratedcustomer(custid,poscustid,dispensaryid,createdon,isactive,isdelete,updatedon) VALUES (" . $data['customer_id'] . "," . $validate['customerid'] . ",('" . $data['dispensary'] . "')::uuid,current_timestamp,true,false,current_timestamp) on conflict(custid,poscustid,dispensaryid) do update set isactive=true,updatedon=current_timestamp");
                return Self::customerResponse(1, $validate['customerid'], null, 'SUCCESS', null, ['orderstatus' => 'AWAITING_PROCESSING']);
            }
        } catch (\Throwable $th) {
            return ['status' => 0, 'customerid' => 0, 'error' => $th, 'resultCode' => 'FAIL', 'resultReason' => $th];
            return Self::customerResponse(0, 0, $th, 'FAIL', $th, null);
        }
    }

    public static function uploadDocument($data)
    {
        /** check auth token */
        $authData = Self::getToken($data['dispensary'], $data['cmp']);
        $header = array(
            'Authorization:' . $authData['access_token'],
            'client_id:' . $authData['integClientID'],
            'content-type: application/json',
        );
        $separator = "\n===========================" . date('Y-m-d H:i:s') . "======================" . PHP_EOL;
        Util::wlog('uploadDocument', $separator);
        //file_put_contents('uploadDocument.log', $separator, FILE_APPEND);
        $sql = DB::select("select id,filename,doctype,path from cmp" . $data['cmp'] . ".documents where reference_id=" . $data['custid']);
        /*$sql = DB::select("select d.id,d.filename,d.doctype,d.path from cmp" . $data['cmp'] . ".documents d 
        where not exists (select true from cmp" . $data['cmp'] . ".uploadeddoclog udl where udl.dispensaryid=('".$data['dispensary']."')::uuid and udl.docid=d.id and d.reference_id=udl.custid and udl.isuploaded=true) and d.reference_id=" . $data['custid'] . ";");*/
        $uploadedDoc = [];
        if (count($sql) > 0) {
            foreach ($sql as $a) {
                $path = $a->path;
                $filename = $a->filename;
                $doctype = $a->doctype;
                $id = $a->id;
                $envcache = Util::envCredential($data['cmp']);
                if(empty($envcache->docbucketurl) || empty($envcache->docjoburl)){
                    Util::wlog('error_DocAndImageBucketenv', 'Document or Image Url are missing ');
                    throw new Exception("Document or Image Url are missing ");
                }
                if (!empty($path) && !empty($doctype)) {
                    if (!isset($envcache->docbucketurl)) { //$_ENV['AWS_S3_DOCUMENT_BUCKET_URL']
                        Util::wlog('uploadDocument', 'AWS_S3_DOCUMENT_BUCKET_URL IS MISSING. CANNOT UPLOAD THE DOCUMENT.');
                        return $uploadedDoc;
                    }
                    $fullpath = $envcache->docbucketurl. $path; //$_ENV['AWS_S3_DOCUMENT_BUCKET_URL'] . $path;
                    $requestData = [
                        "cmp" => $data['cmp'],
                        "dispensary" => $data['dispensary'],
                        "img_path" => $fullpath,
                        "custid" => $data['poscustid'],
                        "file_type" => $doctype,
                        "file_name" => $filename,
                        "docid" => $id,
                        "ecomcustid" => $data['custid']
                    ];
                    Util::wlog('uploadDocument', 'Request : ');
                    Util::wlog('uploadDocument', $requestData);
                    //file_put_contents('uploadDocument.log', 'Request : ', FILE_APPEND);
                    //file_put_contents('uploadDocument.log', json_encode($requestData), FILE_APPEND);
                    $response = Util::HandleCurl('POST', $header, json_encode($requestData), $envcache->docjoburl . '/createtask'); //$_ENV['DOC_JOB_URL']
                    $result = json_decode($response, true);
                    Util::wlog('uploadDocument', 'Response : ');
                    Util::wlog('uploadDocument', $result);
                    //file_put_contents('uploadDocument.log', 'Response : ', FILE_APPEND);
                    //file_put_contents('uploadDocument.log', json_encode($result), FILE_APPEND);
                    if ($result['status'] == true) {
                        array_push($uploadedDoc, $id);
                    }
                }
            }
        }
        return $uploadedDoc;
    }

    private static function validateCustomer($requestData, $data)
    {
        $arr = [
            ['param_key' => 'driverlicense', 'param_value' => $requestData['drivers_license'], 'dispensary' => $data['dispensary'], 'cmp' => $data['cmp']],
            ['param_key' => 'phone', 'param_value' => $requestData['phone'], 'dispensary' => $data['dispensary'], 'cmp' => $data['cmp']],
            ['param_key' => 'email', 'param_value' => $requestData['email'], 'dispensary' => $data['dispensary'], 'cmp' => $data['cmp']],
        ];

        $licenceExist = false;
        $phoneExist = false;
        $emailExist = false;
        $customerid = 0;
        if (trim($requestData['drivers_license']) != '') {
            $res = Self::getCustomerByParam(['param_key' => 'driverlicense', 'param_value' => $requestData['drivers_license'], 'dispensary' => $data['parent_dispid'], 'cmp' => $data['cmp']]);
            if ($res['resultCode'] == 'SUCCESS') {
                $data1 = $res['data'];
                $customerid = 0;
                if (count($data1) > 0) {
                    $licenceExist = true;
                    $customerid = $data1['customer_id'];
                }
            } 
            else if ($res['resultCode'] == 'FAIL') {
                $licenceExist = false;
                $customerid = 0;
            }
            else {
                return ['error' => true, 'message' => $res['resultDetail']];
            }
        }

        if ($requestData['phone'] != '' && $licenceExist == false) {
            $res = Self::getCustomerByParam(['param_key' => 'phone', 'param_value' => $requestData['phone'], 'dispensary' => $data['parent_dispid'], 'cmp' => $data['cmp']]);
            if ($res['resultCode'] == 'SUCCESS') {
                $data1 = $res['data'];
                $customerid = 0;
                if (count($data1) > 0) {
                    $phoneExist = true;
                    $customerid = $data1[0]['customer_id'];
                }
            } else {
                return ['error' => true, 'message' => $res['resultDetail']];
            }
        }

        if ($requestData['email'] != '' && $licenceExist == false && $phoneExist == false) {
            $res = Self::getCustomerByParam(['param_key' => 'email', 'param_value' => $requestData['email'], 'dispensary' => $data['parent_dispid'], 'cmp' => $data['cmp']]);
            if ($res['resultCode'] == 'SUCCESS') {
                $data1 = $res['data'];
                $customerid = 0;
                if (count($data1) > 0) {
                    $emailExist = true;
                    $customerid = $data1[0]['customer_id'];
                }
            } else {
                return ['error' => true, 'message' => $res['resultDetail']];
            }
        }
        //file_put_contents('custlog.txt',print_r($licenceExist." || ".$phoneExist." || ".$emailExist."//".$customerid,true));
        if ($licenceExist || $phoneExist || $emailExist) {
            return ['exist' => true, 'customerid' => $customerid];
        } else {
            return ['exist' => false, 'customerid' => $customerid];
        }
    }

    public static function ProcessSellingPrice($tier_price)
    {
        foreach ($tier_price as $k => $v) {
            if ($v->start_value === 1) {
                return floatval($v->price_per_value);
            }
        }
        return 0.00;
    }

    public static function ProcessProductBarCode($bar_code)
    {

        $found_barcode = array();

        foreach ($bar_code as $k => $v) {
            array_push($found_barcode, $v->sku);
        }

        return $found_barcode;
    }

    public static function test($params)
    {

        if ($params['flag'] == 'getToken') {
            return Self::getToken($params['dispensary'], $params['cmp']);
        } else if ($params['flag'] == 'setUpdateFlag') {
            return Self::setUpdateFlag($params['dispensary'], $params['cmp']);
        }
    }

    public static function setUpdateFlag($dispensary, $cmp)
    {
        $params = array('dispensary' => $dispensary, 'cmp' => $cmp);
        $_token = Self::getAuthData($params['dispensary']); // check data in redis
        if (!empty($_token)) {
            $_token['isupdated'] = 1;
            DBUtil::setRedisData($params['dispensary'], $_token);
        }
    }

    public static function getToken($dispensary, $cmp)
    {
        $params = array('dispensary' => $dispensary, 'cmp' => $cmp);

        $_token = Self::getAuthData($params['dispensary']); // check data in redis

        if (empty($_token)) {
            $_token = Self::Authorization($params, null); // get from database
            if ($_token && isset($_token['status'])) {
                return "ERROR";
            }
        }


        if (isset($_token['expires_at'])) {
            $expires_at = new \Moment\Moment($_token['expires_at']);
            $expires_at->setTimezone('UTC');

            $current = new \Moment\Moment();
            $current->setTimezone('UTC');

            if ($current->isAfter($expires_at) || ($_token != null && isset($_token['isupdated']) && $_token['isupdated'] == 1)) { // Check access token is expire ot not
                $_token = Self::Authorization($params, $_token);
                if ($_token && isset($_token['status'])) {
                    return "ERROR";
                }
            }
        } else {
            $_token = Self::Authorization($params, null);
            if ($_token && isset($_token['status'])) {
                return "ERROR";
            }
        }
        return $_token;
    }

    public static function Authorization($params, $_token)
    {

        $response = array('status' => false, 'message' => '');

        if ($_token == null || ($_token != null && isset($_token['isupdated']) && $_token['isupdated'] == 1)) {

            $query = DB::select("select integration from cmp" . $params['cmp'] . ".dispensary where id='" . $params['dispensary'] . "'");

            if (sizeof($query) > 0) {
                $integration = $query[0]->integration;
                $data = json_decode($integration, true);

                if (!isset($data['pos'])) {
                    $response = array('status' => false, 'message' => 'Invalid POS Integration');
                }
                $pos = $data['pos'];

                if (!isset($pos['integClientID'])) {
                    return array('status' => false, 'message' => 'integClientID required!');
                }
                if (!isset($pos['integApiKey'])) {
                    return array('status' => false, 'message' => 'integApiKey required!');
                }
                if (!isset($pos['integDispId'])) {
                    return array('status' => false, 'message' => 'integDispId required!');
                }
                // if (!isset($pos['location'])) {
                //     return array('status' => false, 'message' => 'Location is required!');
                // }
                if (!isset($pos['name'])) {
                    return array('status' => false, 'message' => 'POS is required!');
                }
            }
            $_token = [
                'integClientID' => $pos['integClientID'],
                'integApiKey' => $pos['integApiKey'],
                'integDispId' => $pos['integDispId'],
                'location' => $pos['locationdata'],
                'posName' => $pos['name'],
            ];
        }

        $rawparams = 'client_id=' . $_token['integClientID'] . '&apikey=' . $_token['integApiKey'];

        $header = array(
            'Content-Type: application/x-www-form-urlencoded',
        );
        $envcache = Util::envCredential($params['cmp']);
        if(empty($envcache->treezurl)){
            Util::wlog('error_treezenv', 'Treez Url are missing ');
            throw new Exception("Treez Url are missing ");
        }
        $maxTries = 3;
        $try = 1;
        retrylabel:
        //$response = Util::HandleCurl('POST', $header, $rawparams, Self::$api_url . $_token['integDispId'] . '/config/api/gettokens');
        $response = Util::HandleCurl('POST', $header, $rawparams, $envcache->treezurl . $_token['integDispId'] . '/config/api/gettokens');

        if ($response == false) {
            return array('status' => false, 'message' => 'Response blank from Api');
        }

        $response = json_decode($response, true);

        if (isset($response['fault'])) {
            if ($try <= $maxTries) {
                $try++;
                sleep(1);
                goto retrylabel;
            }
        }

        if (isset($response['fault'])) {
            return array('status' => false, 'message' => 'Spike Violation');
        }

        if ($response) {
            if ($response['resultCode'] == "FAIL") {
                return array('status' => false, 'message' => $response['resultReason']);
            }

            $_token['access_token'] = $response['access_token'];
            $_token['expires_at'] = $response['expires_at'];

            DBUtil::setRedisData($params['dispensary'], $_token);
        }

        $response = DBUtil::getAuthData($params['dispensary']);

        return $response;
    }

    public static function getAuthData($dispid)
    {
        $data = DBUtil::getRedisData($dispid, '');
        return json_decode($data, true);
    }

    public static function setAuthData($dispid, $data)
    {
        // if (!empty($client->get($dispid))) {
        //     $data = DBUtil::getAuthData($dispid);
        // }
        // $data['access_token'] = $data['access_token'];
        // $data['expires_at'] = $data['expires_at'];
        // return DBUtil::setRedisData($dispid, json_encode($data));
    }

    public static function webhook($request)
    {
        //Util::wlog('webhook', $request);
        @$event_type = $request['event_type'];
        @$data = $request['data'];
        $cmp = Util::Decrypt("VUHODTX1P6NZEDGBH1XP", $request['cmp']);
        $dispensaryid = Util::Decrypt("VUHODTX1P6NZEDGBH1XP", $request['dispensaryid']);

        // Old code
        // @$req['integration'] = $request['integration'];
        // @$req['ticket_id'] = $data['ticket_id'];
        // @$req['order_status'] = $data['order_status'];
        // @$req['customer_id'] = $data['customer_id'];

        // New code

        if($event_type=='TICKET_STATUS'){
            $data=['order_status'=>$data['order_status'],'ticket_id'=>$data['ticket_id']];
        }
        else if($event_type=='CUSTOMER'){
            $data=['status'=>$data['status'],'customer_id'=>$data['customer_id'],'banned'=>$data['banned']];
        }
        else if($event_type=='TICKET'){
            $data=['order_status'=>$data['order_status'],'ticket_id'=>$data['ticket_id'],'customer_id'=>$data['customer_id']];
        }

        @$data['integration']=$request['integration'];
        @$data['cmp']=$cmp;
        @$data['dispensaryid']=$dispensaryid;
        
        if($event_type == 'PRODUCT') {
            try {
                DB::select("insert into cmp".$cmp.".manage_sync (dispid, module, sync, last_sync_at) 
                values (('$dispensaryid')::uuid, 'product', true, '".Carbon::now()."') 
                on conflict (dispid) do update set dispid = excluded.dispid, module = excluded.module, sync = excluded.sync, last_sync_at = excluded.last_sync_at");
            }
            catch(Exception $e) {
                Util::wlog('p',$e->getMessage());
            }
        }
        else if($event_type=='TICKET_STATUS' || $event_type=='CUSTOMER') {
            $sql = DBUtil::callProcedure('sp_webhook', Util::sysParams($cmp, $event_type), json_encode($data));
        }
        else if($event_type=='TICKET' && $data['order_status']=='COMPLETED') {
            Self::updateGCBalanceHold($data);
            Self::sendGiftCardMail($data);
            try {
                $res = Birdeye::send($data);
                Util::wlog('birdeye',$res);
            }
            catch(Exception $e) {
                Util::wlog('birdeye',$e->getMessage());
            }
            try{
                Self::updateCustomerRewardsPoints(['cmp'=>$data['cmp'],'customer_id'=>$data['customer_id'],'dispensary'=>$dispensaryid]);
            }catch(Exception $e){
                Util::wlog('rewards points',$e->getMessage());
            }
            try {
                CSPW::cspwCompleteOrderApi('', ["order_no" => json_decode($sql['res'],true)['order_no'], "api_key" => json_decode($sql['res'],true)['api_key']]);
            }
            catch(Exception $e) {
                Util::wlog('cspw',$e->getMessage());
            }
            //for sms...
            try {
                Self::sendOrderSms(['cmp'=>$data['cmp'],'orderid'=>$data['ticket_id']],'order','COMPLETED');
            } catch(Exception $e) {
                Util::wlog('sms '.$data['order_status'],$e->getMessage());
            }
            //for mail...
            try{
                Self::sendOrderMail(['cmp'=>$data['cmp'],'orderid'=>$data['ticket_id']],'order','order_completed');
            } catch(Exception $e){
                Util::wlog('mail order canceled',$e->getMessage());
            }
        }
        else if($event_type=='TICKET' && $data['order_status']=='PACKED_READY') {
            try {
                DB::select("update cmp".$cmp.".orderpayments set treez_payment_status='".pg_escape_string($data['payment_status'])."' where orderid=(select id from cmp".$cmp.".ordermaster where posordernum='".$data['order_number']."' limit 1);");
            } catch(Exception $e) {
                Util::wlog('packed_ready_',$e->getMessage());
            }
        }
        if($event_type=='TICKET_STATUS')
        {
            if(DB::table('cmp'.$data['cmp'].'.ordermaster')->where('posorderid',$data['ticket_id'])->count()==0) {
                return null;
            }
            if($data['order_status']=='PACKED_READY' || $data['order_status']=='CANCELED'){
                
                if($data['order_status']=='CANCELED')
                {
                    try {
                        $alrow = DB::table('cmp'.$data['cmp'].'.ordermaster')
                                ->join('cmp'.$data['cmp'].'.alpinecustomers','alpinecustomers.cust_id','=','ordermaster.customerid')
                                ->join('cmp'.$data['cmp'].'.orderpayments','ordermaster.id','=','orderpayments.orderid')
                                ->where('orderpayments.paytype','AlpineIQ')
                                ->where('ordermaster.posorderid',$data['ticket_id'])
                                ->select('orderpayments.description','orderpayments.amount_paid','alpinecustomers.alpine_contact_id')
                                ->first();
                        if(!empty($alrow)) {
                            AlpineIQ::modifyPoints(['alpine_contact_id'=> $alrow->alpine_contact_id,'amount'=>abs($alrow->description),'cmp' => $data['cmp'],'note' => 'Order Canceled. Points Adjusted']);
                        }
                    }
                    catch(Exception $e) {
                        Util::wlog('alpine_error',$e->getMessage());
                    }
                    try {
                        CSPW::cspwCanceledOrderApi('', ["order_no" => json_decode($sql['res'],true)['order_no'], "api_key" => json_decode($sql['res'],true)['api_key']]);
                    }
                    catch(Exception $e) {
                        Util::wlog('cspw',$e->getMessage());
                    }
                }
                //for sms...
                try {
                    Self::sendOrderSms(['cmp'=>$data['cmp'],'orderid'=>$data['ticket_id']],'order',$data['order_status']);
                } catch(Exception $e) {
                    Util::wlog('sms '.$data['order_status'],$e->getMessage());
                }
                //for mail...
                try{
                    Self::sendOrderMail(['cmp'=>$data['cmp'],'orderid'=>$data['ticket_id']],'order',$data['order_status']);
                } catch(Exception $e){
                    Util::wlog('mail '.$data['order_status'],$e->getMessage());
                }
            }
        }
        return null;
    }

    public static function getAuthToken($req)
    {
        $authData = Self::getToken($req['dispensary'], $req['cmp']);
        return $authData;
        # code...
    }

    public static function callProduct($data)
    {
        //$op = exec('nohup php ' . __DIR__ . '/treez_product_sync.php ' . $data['cmp'] . ' ' . $data['dispensary'] . ' product force ' . $data['syncall'] . ' > /dev/null &');	
        //return 'nohup php artisan sync:products ' . $data['cmp'] . ' ' . $data['dispensary'] . ' product true ' . $data['syncall'] . ' > /dev/null &';	
        $op = \Artisan::call('sync:products ' . $data['cmp'] . ' ' . $data['dispensary'] . ' true ' . $data['syncall']);	
        return ['status' => 1, 'result' => $op, 'errorcode' => null, 'msg' => null];
    }

    public static function callInventory($data)
    {
        //$op = exec('nohup php ' . __DIR__ . '/treez_product_sync.php ' . $data['cmp'] . ' ' . $data['dispensary'] . ' inv force > /dev/null &');	
        $op = \Artisan::call('sync:inventory ' . $data['cmp'] . ' false ' . $data['dispensary']);	
        return ['status' => 1, 'result' => $op, 'errorcode' => null, 'msg' => null];
    }

    public static function stopProcess($data)
    {
        $op = exec('pkill ' . $data['pname']);
        return ['status' => 1, 'result' => $op, 'errorcode' => null, 'msg' => null];
    }

    public static function verifyCustomerDetails($data, $interated_tbl_data)
    {
        try {
            $posCustId = $data['poscustid'];
            // Check flag for customer updated medical details in interatedcustomer table.
            if (isset($interated_tbl_data['isupdated_med_detail']) && $interated_tbl_data['isupdated_med_detail']) {
                $resData = [
                    'poscustid' => $posCustId,
                    'status' => 'PATIENT_TYPE_UPDATED',
                    'verification_status' => 'VERIFICATION_PENDING',
                    'verification_reason' => 'Medical details or `patient type` is updated from customer portal.',
                    'verification_reason_description' => 'Customer has updated Medical details or `patient type` from profile',
                ];
                $response = ['status' => 1, 'data' => $resData, 'error' => null, 'resultCode' => 'SUCCESS'];
                Util::wlog('verifyCustomerDetails', $response);
                return $response;
            }

            /** check auth token */
            $authData = Self::getToken($data['parent_dispid'], $data['cmp']);
            $header = array(
                'Authorization:' . $authData['access_token'],
                'client_id:' . $authData['integClientID'],
                'content-type: application/json',
            );
            $separator = "\n===========================" . date('Y-m-d H:i:s') . "======================"   . PHP_EOL;
            Util::wlog('verifyCustomerDetails', $separator);
            //file_put_contents('verifyCustomerDetails.log', $separator, FILE_APPEND);
            $envcache = Util::envCredential($data['cmp']);
            if(empty($envcache->treezurl)){
                Util::wlog('error_treezenv', 'Treez Url are missing ');
                throw new Exception("Treez Url are missing ");
            }

            //$url = Self::$api_url . $authData['integDispId'] . "/customer/" . $posCustId;
            $url = $envcache->treezurl . $authData['integDispId'] . "/customer/" . $posCustId;
            Util::wlog('verifyCustomerDetails', $url);
            //file_put_contents('verifyCustomerDetails.log', print_r($url, true), FILE_APPEND);
            $maxTries = 3;
            $try = 1;
            retrylabel:
            $curl = Util::HandleCurl('GET', $header, null, $url);
            $result = json_decode($curl, true);
            if (isset($result['fault'])) {
                if ($try <= $maxTries) {
                    $try++;
                    sleep(1);
                    goto retrylabel;
                }
            }
            if (isset($decoded['fault'])) {
                $response = ['status' => 0, 'data' => null, 'error' => 'Spike Violation', 'resultCode' => 'FAIL'];
            }

            if ($curl == false) {
                $response = ['status' => 0, 'data' => null, 'error' => 'Response Blank from Api', 'resultCode' => 'FAIL'];
            }
            $custdata = $result['data'];
            $status = '';
            $verification_status = '';
            $verification_reasons = [];
            $verification_reason = '';
            $verification_reason_description = '';
            if ($result['resultCode'] == 'SUCCESS') {
                $status = $custdata['status'];
                $verification_status = $custdata['verification_status'];
                $verification_reasons = $custdata['verification_reasons'];
                if (count($verification_reasons) > 0) {
                    $verification_reason = $verification_reasons[0]['verification_reason'];
                    $verification_reason_description = $verification_reasons[0]['verification_reason_description'];
                }
                $resData = [
                    'poscustid' => $posCustId,
                    'status' => $status,
                    'verification_status' => $verification_status,
                    'verification_reason' => $verification_reason,
                    'verification_reason_description' => $verification_reason_description,
                ];
                $response = ['status' => 1, 'data' => $resData, 'error' => null, 'resultCode' => 'SUCCESS'];
            } else if ($result['resultCode'] == 'FAIL') {
                $response = ['status' => 0, 'data' => null, 'error' => $result['resultReason'], 'resultCode' => 'FAIL'];
            } else {
                $response = ['status' => 0, 'data' => null, 'error' => 'Result Code found blank', 'resultCode' => 'FAIL'];
            }
            Util::wlog('verifyCustomerDetails', $response);
            //file_put_contents('verifyCustomerDetails.log', print_r($response, true), FILE_APPEND);
            return $response;
        } catch (\Throwable $th) {
            $response = ['status' => 0, 'data' => null, 'error' => $th, 'resultCode' => 'FAIL'];
            Util::wlog('verifyCustomerDetails', $response);
            //file_put_contents('verifyCustomerDetails.log', print_r($response, true), FILE_APPEND);
            return $response;
        }
    }

    public static function customerResponse($status, $customerid, $error, $resultcode, $resultreason, $otherdata = null)
    {
        return ['status' => $status, 'customerid' => $customerid, 'error' => $error, 'resultCode' => $resultcode, 'resultReason' => $resultreason, 'otherData' => $otherdata,'profileData'=>null];
    }

    public static function processInvWebhookData($data)
    {
        if (!isset($data['data'])) {
            return ['status' => 0, 'result' => null, 'errorcode' => 'DATA_MISSING', 'msg' => "Input data is missing"];
        } 
        else if (empty($data['data']) || count($data['data']) == 0) {
            return ['status' => 0, 'result' => null, 'errorcode' => 'DATA_MISSING', 'msg' => "Input data is missing"];
        } else {
            //file_put_contents('gotsp.log', print_r($data, true));
            $sql = DBUtil::callProcedure('sp_inventory', Util::sysParams($data['cmp'], 'crud'), json_encode($data['data']));
            return $sql;
        }
    }

    public static function autoSyncProduct($data)	
    {	
        $dispid='';	
        $where='';	
        $syncall = '';	
        if(isset($data['dispid'])){	
            $dispid=$data['dispid'];	
            $where =" id='".$dispid."'";	
        }	
        else	
        {	
            $where ="lower(name)=lower('".$data['dispname']."')"; 	
        }	
        $currentUtcTime = date('H:i:s');	
        if($currentUtcTime>='11:00:00' && $currentUtcTime<='12:00:00'){	
            $syncall=true;	
        }

        $sql=DB::select("select id from cmp".$data['cmp'].".dispensary where $where and isactive=true LIMIT 1");	
        if(count($sql)>0){	
            $row=$sql[0];	
            //$op = exec('nohup php ' . __DIR__ . '/treez_product_sync.php ' . $data['cmp'] . ' ' . $row->id . ' product force '.$syncall.' > /dev/null &');	
			$op = \Artisan::call('sync:products ' . $data['cmp'] . ' ' . $row->id . ' true ' . $data['syncall'] . ' > /dev/null &');	
            Util::wlog('autoSyncProduct', ['synctime'=>date('Y-m-d h:i:s'),'status'=>'success','syncall'=>$syncall]);	
            return ['status' => 1, 'result' => null, 'errorcode' => null, 'msg' => 'Sync Successfylly'];
        }	
        else	
        {	
			Util::wlog('autoSyncProduct', ['synctime'=>date('Y-m-d h:i:s'),'status'=>'Dispensary name not matched']);	
            return ['status' => 0, 'result' => null, 'errorcode' => '404', 'msg' => 'Dispensary name not matched'];	
        }
    }

    public static function autoSyncInventory($data)
    {   
        $dispid='';
        $where='';
        if(isset($data['dispid'])){
            $dispid=$data['dispid'];
            $where =" id='".$dispid."'";
        }
        else
        {
            $where ="lower(name)=lower('".$data['dispname']."')"; 
        }

        $sql=DB::select("select id from cmp".$data['cmp'].".dispensary where $where and isactive=true LIMIT 1");
        if(count($sql)>0){
            $row=$sql[0];
            //$op = exec('nohup php ' . __DIR__ . '/treez_product_sync.php ' . $data['cmp'] . ' ' . $row->id . ' inv force > /dev/null &');	
			$op = \Artisan::call('sync:inventory ' . $data['cmp'] . ' false ' . $row->id . ' > /dev/null &');	
            Util::wlog('autoSyncInventory', ['synctime'=>date('Y-m-d h:i:s'),'status'=>'success']);
        }
        else
        {
			Util::wlog('autoSyncInventory', ['synctime'=>date('Y-m-d h:i:s'),'status'=>'Dispensary name not matched']);
            return ['status' => 0, 'result' => null, 'errorcode' => '404', 'msg' => 'Dispensary name not matched'];
        }
        
    }

    public static function sendOrderMail($data,$module,$sub_module){
        $qury = DB::select("select count(1) as count from cmp".$data['cmp'].".emailtemplatemapping where module='$module' AND submodule='$sub_module' AND allow_to_send=true");
        if($qury[0]->count==0) {
            return false;
        }
        
        $emailArr= [];
        $emailArr['module']=$module;
        $emailArr['submodule']=$sub_module;
        $clogo = Util::getCompanyDetails($data['cmp']);
        $envcache = Util::envCredential($data['cmp']);
        if(empty($envcache->imgcludeurl)){
            Util::wlog('error_ImageBucketenv', 'Aws Bucket Image Url are missing ');
            throw new Exception("Aws Bucket Image Url are missing ");
        }
        if($sub_module == 'order_placed'){ 
            $sql = DBUtil::callFunction('fn_order', Util::sysParams($data['cmp'], 'getMyOrder'),json_encode(['orderid'=>$data['orderid']]));
            
            $prods = $sql[0];
            $res = json_decode(json_encode($sql[0][0]),true);
            
            $emailArr=['items'=>''];

            foreach($prods as $item){
                $emailArr['items'] .='<tr style="border-collapse:collapse"><td style="padding:5px 10px 5px 0;Margin:0" width="80%" align="left"><p style="Margin:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-size:16px;line-height:24px;color:#333333">'.$item->quantity.' X '.$item->productname.'</p></td><td style="padding:5px 0;Margin:0" width="20%" align="right"><p style="Margin:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-size:16px;line-height:24px;color:#333333">$'.$item->baseprice.'</p></td></tr>';
            }

            $emailArr['cmp']=$data['cmp'];
            $emailArr['discount']=$res['totaldiscount'];
            $emailArr['taxes']=$res['totaltaxamt'];
            $emailArr['subtotal']=$res['subtotal'];
            $emailArr['delivery_fee']=$res['totalextrafees'];
            $emailArr['ordertype_label']=$res['ordertype'];
            $emailArr['order_total']=$res['totalsellingprice'];
            $emailArr['orderno']=$res['orderid'].' | '.$res['posorderid'].' ('.$res['ordertype'].')';
            $emailArr['address']=$res['dispname']."<br/>".trim($res['deliveryaddress']);
            $emailArr['dispensary']=trim($res['dispid']);
            $emailArr['orderid']=trim($data['orderid']);
            $emailArr['ordertype']=trim($res['ordertype']);
            $emailArr['name']=trim($res['dispname']);
            $emailArr['logo']=$envcache->imgcludeurl."cmp".$data['cmp']."/".trim($clogo->img1);
            //$emailArr['logo']='https://shop.my7engines.com/assets/img/7engines_logo_blue.png';
            $emailArr['licenceno']=(($res['displicenceno']!='')?"<b>Licence No. :</b>".trim($res['displicenceno']):'');
            $emailArr['dispaddress']=trim($res['dispaddress']);
            $emailArr['phone']=trim($res['dispphone']);
            $emailArr['email']=trim($res['dispemail']);
            $emailArr['reply_to']=trim($res['dispemail']);
            $emailArr['disp_name']=trim($res['dispname']);
            $emailArr['user']=trim($res['cust_name']);
            $emailArr['cspwvisible']=empty($res['cspw_api_key']) ? 'display:none;' : '';
            $emailArr['otwpath']=env('PUBLIC_URL') . 'index1.php/cspw/otw/' . $res['posorderid'] . '/' . $res['cspw_api_key'];
            $emailArr['arrivedpath']=env('PUBLIC_URL') . 'index1.php/cspw/arrived/' . $res['posorderid'] . '/' . $res['cspw_api_key'];
            $emailArr['email_ad']=$envcache->imgcludeurl."cmp".$data['cmp']."/".$res['dispid']."/".trim($res['email_ad_image']);

        if(!empty($res['cspw_api_key'])) {
            SMSController::sendSMSCurbside($res['cust_mobile'], $emailArr['otwpath'], $emailArr['arrivedpath'], $emailArr['cmp']);
        }

        }else if($sub_module == 'PACKED_READY' || $sub_module == 'CANCELED' || $sub_module == 'COMPLETED'){
            $sql1 = DBUtil::callFunction('fn_order', Util::sysParams($data['cmp'], 'getMyOrderForReadyCancelComplete'),json_encode(['orderid'=>$data['orderid']]));
            $res = json_decode(json_encode($sql1[0][0]),true);

            $emailArr['name']=$res['cust_name'];
            $emailArr['cmp']=$data['cmp']; 
            $emailArr['logo']= $envcache->imgcludeurl."cmp".$data['cmp']."/".trim($clogo->img1); //env('AWS_S3_IMAGE_CLUDE_URL')
            //$emailArr['logo']='https://shop.my7engines.com/assets/img/7engines_logo_blue.png';
            $emailArr['licenceno']=(($res['displicenceno']!='')?"<b>Licence No. :</b>".trim($res['displicenceno']):'');
            $emailArr['dispaddress']=trim($res['dispaddress']);
            $emailArr['order_total']= "$".$res['totalsellingprice'];
            $emailArr['orderno']=$res['orderid'].' | '.$res['posorderid'].' ('.$res['ordertype'].')';
            $emailArr['phone']=trim($res['dispphone']);
            $emailArr['email']=trim($res['dispemail']);
            $emailArr['reply_to']=trim($res['dispemail']);
            $emailArr['cust_email']=trim($res['cust_email']);
            $emailArr['disp_name']=trim($res['dispname']);
            $emailArr['tinyurl']=trim($res['tinyurl']);
            $emailArr['company_name']=trim($res['dispname']);
            $emailArr['user']=$res['cust_name'];
            $emailArr['email_ad']=$envcache->imgcludeurl."cmp".$data['cmp']."/".$res['dispid']."/".trim($res['email_ad_image']);
        }
        
        $mail=TMailing::handleRequest($module, $sub_module, json_decode(json_encode($emailArr)));
        
    }

    public static function updateCustomerDataOnPOS($data)
    {
        try {
            $envcache = Util::envCredential($data['cmp']);
            if(empty($envcache->treezurl)){
                Util::wlog('error_treezenv', 'Treez Url are missing ');
                throw new Exception("Treez Url are missing ");
            }
            $pos_url = $envcache->treezurl; //Self::$api_url;
            $sql = DB::select("select i.custid,i.poscustid,case when (d.isvirtual=true) then d.parentid else d.id end as dispensaryid,c.drivlice,c.licexpdate,c.stmedid,c.medexpdate,COALESCE(c.isadultuse,false) as isadultuse,c.dob,c.fname,c.lname FROM cmp" . $data['cmp'] . ".integratedcustomer i inner join cmp" . $data['cmp'] . ".customer c on i.custid=c.id inner join cmp" . $data['cmp'] . ".dispensary d on i.dispensaryid = d.id where custid=" . $data['customer_id'] . " and i.isactive=true");
            if (count($sql) > 0) {
                $respArr = [];
                foreach ($sql as $rec) {
                    $authData = Self::getToken($rec->dispensaryid, $data['cmp']);
                    $header = array(
                        'Content-Type:  application/json',
                        'authorization: ' . $authData['access_token'],
                        'client_id: ' . $authData['integClientID'],
                    );
                    $customer = Treez::getCustomerById(['dispensary' => $rec->dispensaryid, 'cmp' => $data['cmp'], 'customer_id' => $rec->poscustid]);
                    if(!empty($customer) && $customer['resultCode'] == 'SUCCESS'){
                        $rawparams = (array) $customer['data'];
                        $url = $pos_url . $authData['integDispId'] . "/customer/update/" . $rec->poscustid;
                        $rawparams['customer_id'] = $rec->poscustid;
                        $rawparams['drivers_license'] = trim($rec->drivlice);
                        $rawparams['drivers_license_expiration'] = $rec->licexpdate;
                        $rawparams['state_medical_id'] = $rec->stmedid;
                        $rawparams['permit_expiration'] = $rec->medexpdate;
                        $rawparams['patient_type'] = ($rec->isadultuse) ? 'ADULT' : 'MEDICAL_MMID';
                        $rawparams['birthday'] = $rec->dob;
                        $rawparams['first_name'] = $rec->fname;
                        $rawparams['last_name'] = $rec->lname;
                        Util::wlog('updateCustomerDataOnPOS', json_encode($rawparams));
                        $h_res = Util::HandleCurl('PATCH', $header, json_encode($rawparams), $url);
                        $response = json_decode($h_res, true);
                        if ($response['resultCode'] == 'SUCCESS') {
                            Util::wlog('updateCustomerDataOnPOS', json_encode(['ecomcustid' => $rec->custid,'poscustid' => $rec->poscustid, 'msg' => 'customer updated in treez']));
                        } else {
                            Util::wlog('updateCustomerDataOnPOS', json_encode(['ecomcustid' => $rec->custid,'poscustid' => $rec->poscustid, 'msg' => $response['resultReason']]));
                        }
                    }
                    else {
                        Util::wlog('updateCustomerDataOnPOS', json_encode(['ecomcustid' => $rec->custid,'poscustid' => $rec->poscustid, 'msg' => 'customer not found in treez']));
                    }
                }
            }
        } catch (\Throwable $th) {
            return ['status' => 0, 'customerid' => 0, 'error' => $th, 'resultCode' => 'FAIL', 'resultReason' => $th];
        }
    }

    public static function uploadSingleDocOnTreez($data)
    {
        $authData = Self::getToken($data['dispensary'], $data['cmp']);
        $header = array(
            'Authorization:' . $authData['access_token'],
            'client_id:' . $authData['integClientID'],
            'content-type: application/json',
        );
        $path = $data['path'];
        $filename = $data['filename'];
        $doctype = $data['doctype'];
        $id = $data['id'];
        if (!empty($path) && !empty($doctype)) {
            $envcache = Util::envCredential($data['cmp']);
            if(empty($envcache->docbucketurl) || empty($envcache->docjoburl)){
                Util::wlog('error_DocAndImageBucketenv', 'Document or Image Url are missing ');
                throw new Exception("Document or Image Url are missing ");
            }
            // if (!isset($envcache->docbucketurl)) {
            //     return 'Missing Bucket url';
            // }
            $fullpath = $envcache->docbucketurl. $path; //$_ENV['AWS_S3_DOCUMENT_BUCKET_URL'] . $path;
            $requestData = [
                "cmp" => $data['cmp'],
                "dispensary" => $data['dispensary'],
                "img_path" => $fullpath,
                "custid" => $data['poscustid'],
                "file_type" => $doctype,
                "file_name" => $filename,
                "docid" => $id,
                "ecomcustid" => $data['custid']
            ];
            $response = Util::HandleCurl('POST', $header, json_encode($requestData), $envcache->docjoburl . '/createtask'); //$_ENV['DOC_JOB_URL']
            $result = json_decode($response, true);
        }
        return true;
    }

    public static function createCustomerOnPos($requestData, $data)
    {
        /** check auth token */
        $authData = Self::getToken($data['dispensary'], $data['cmp']);
        $header = array(
            'Authorization:' . $authData['access_token'],
            'client_id:' . $authData['integClientID'],
            'content-type: application/json',
        );
        $separator = "\n===========================" . date('Y-m-d H:i:s') . "======================" . PHP_EOL;
        Util::wlog('createCustomerOnPos', $separator);
        // file_put_contents('createCustomer.log', $separator, FILE_APPEND);
        try {
            $vrdata = [];
            $data['parent_dispid'] = $data['dispensary'];
            $vrdata['email'] = $requestData['email'];
            $vrdata['phone'] = $requestData['phone'];
            $vrdata['drivers_license'] = '';
            $validate = Self::validateCustomer($vrdata, $data);
            if (isset($validate['error']) && $validate['error'] == true) {
                $logmsg = json_encode(['type' => 'Error while Validate Customer', 'desc' => $validate['message']], JSON_PRETTY_PRINT);
                Util::wlog('createCustomerOnPos', $logmsg);
                return ['status' => 0, 'error' => 'Error while Validate Customer'];
            }
            if (!$validate['exist']) {
                $requestDataJson = json_encode($requestData, JSON_PRETTY_PRINT);
                Util::wlog('createCustomerOnPos', $requestDataJson);
                $envcache = Util::envCredential($data['cmp']);
                if(empty($envcache->treezurl)){
                    Util::wlog('error_treezenv', 'Treez Url are missing ');
                    throw new Exception("Treez Url are missing ");
                }
                $maxTries = 3;
                $try = 1;
                retrylabel:
                //$response = Util::HandleCurl('POST', $header, json_encode($requestData), Self::$api_url . $authData['integDispId'] . '/customer/detailcustomer');
                $response = Util::HandleCurl('POST', $header, json_encode($requestData), $envcache->treezurl . $authData['integDispId'] . '/customer/detailcustomer');
                Util::wlog('createCustomerOnPos', $response);
                $result = json_decode($response, true);

                if (isset($result['fault'])) {
                    if ($try <= $maxTries) {
                        $try++;
                        sleep(1);
                        goto retrylabel;
                    }
                }
                if (isset($result['fault'])) {
                    Util::wlog('createCustomerOnPos', 'Spike arrest');
                    return ['status' => 0, 'error' => 'Spike arrest'];
                }
                if ($response == false) {
                    Util::wlog('createCustomerOnPos', 'No response from APi');
                    return ['status' => 0, 'error' => 'No response from APi'];
                }

                if ($result['resultCode'] == "SUCCESS") {
                    //$row = $result['data'];
                    $imageList = $requestData['UploadImages'];
                    foreach ($imageList as $img) {
                        $file = file_get_contents($img['url']);
                        $base64 = base64_encode($file);
                        $header_1 = array(
                            'Authorization:' . $authData['access_token'],
                            'client_id:' . $authData['integClientID'],
                            'content-type: application/json',
                            'Content-Length:' . strlen($file)
                        );
                        $reqData = [
                            "file_name" => 'file-' . $img['type'],
                            "file_type" => $img['type'],
                            "encoded_string" => $base64
                        ];
                        $maxTries_1 = 3;
                        $try_1 = 1; 
                        retrylabel_1:
                        //$response_1 = Util::HandleCurl('POST', $header_1, json_encode($reqData), Self::$api_url . $authData['integDispId'] . '/customer/document/base64/upload');
                        $response_1 = Util::HandleCurl('POST', $header_1, json_encode($reqData), $envcache->treezurl . $authData['integDispId'] . '/customer/document/base64/upload');
                        Util::wlog('createCustomerOnPos', $response_1);
                        $result_1 = json_decode($response_1, true);

                        if (isset($result_1['fault'])) {
                            if ($try_1 <= $maxTries_1) {
                                $try_1++;
                                sleep(1);
                                goto retrylabel_1;
                            }
                        }
                        if (isset($result_1['fault'])) {
                            Util::wlog('createCustomerOnPos', 'Document Upload - Spike arrest');
                            return ['status' => 0, 'error' => 'Document Upload - Spike arrest'];
                        }
                        if ($response_1 == false) {
                            Util::wlog('createCustomerOnPos', 'Document Upload - No response from APi');
                            return ['status' => 0, 'error' => 'Document Upload - No response from APi'];
                        }

                        if ($result_1['resultCode'] == "SUCCESS") {
                            $try_1 = 1;
                            Util::wlog('createCustomerOnPos', 'Document Upload - Document Uploaded');
                        }
                    }

                    return ['status' => 1, 'error' => 'Customer created'];
                } else {
                    Util::wlog('createCustomerOnPos', $result);
                    return ['status' => 0, 'error' => 'Error while creating customer'];
                }
            }
        } catch (\Throwable $th) {
            return ['status' => 0, 'error' => $th];
        }
    }

    public static function orderUpdate($data, $authData,$ticketid,$updreq=[],$orderid,$charge_respo,$paymentdata=null) {
        try {
            $envcache = Util::envCredential($data['data']['cmp']);
            if(empty($envcache->treezurl)){
                Util::wlog('error_treezenv', 'Treez Url are missing ');
                throw new Exception("Treez Url are missing ");
            }
            Util::wlog('paymentlog',$ticketid, __LINE__);
            $maxTries = 3;
            $try = 1;
            $pos_url = $envcache->treezurl; //Self::$api_url;
            $cmp = 'cmp'.$data['data']['cmp'];
            $url = $pos_url . $authData['integDispId'] . "/ticket/update/" . $ticketid;
            $updreq['payments'] = $updreq['ecom_payments'];
            $rawparams = json_encode($updreq);
            $header = array(
                'Content-Type:  application/json',
                'authorization: ' . $authData['access_token'],
                'client_id: ' . $authData['integClientID'],
            );
            retrylabel:
            $response = Util::HandleCurl('PUT', $header, $rawparams, $url);
            $res = $response;
            $decoded = json_decode($response, true);
            if (isset($decoded['fault'])) {
                if ($try <= $maxTries) {
                    $try++;
                    sleep(1);
                    goto retrylabel;
                }
            }
            if($decoded['resultCode']=='SUCCESS') {
                $paystatus = '';
                $paymentdata['payments'] = $updreq['ecom_payments'];
                if(!empty($paymentdata)){
                    $paystatus = $paymentdata['payment_status'];
                    $paymentdata = json_encode($paymentdata);
                } else {
                    $paystatus = $updreq['payment_status'];
                }
                $data = ['orderid'=>$orderid,'paytype'=>$paystatus,'paydetails'=>$paymentdata];
                // DB::table($cmp.'.ordermaster')->where('id',$orderid)->update(['paytype'=>$paystatus,'paydetails'=>$paymentdata]);
                DBUtil::callProcedure('sp_orders', Util::sysParams($data->cmp, 'updateOrder'), json_encode($data));
                $res = '{"resultCode":"SUCCESS","resultReason":"Order updated","resultDetail":null}';
            }

            if (isset($decoded['fault'])) {
                $res = '{"resultCode":"FAIL","resultReason":Spike arrest,"resultDetail":null}';
            }

            if ($response == false) {
                $res = '{"resultCode":"FAIL","resultReason":null,"resultDetail":null}';
            }
            return $res;
        } catch(Exception $e) {
            Util::wlog('treez_php_orderUpdate',$e->getMessage(), __LINE__);
            $res = '{"resultCode":"FAIL","resultReason":"'.$e->getMessage().'","resultDetail":null}';
            return $res;
        }
    }

    public static function sendGiftCardMail($data){
        // if(DB::table("cmp".$data['cmp'].".emailtemplatemapping")->where(['module' => 'order', 'submodule' => 'gift_card'])->whereRaw('allow_to_send=true')->count() === 0) {
        //     return false;
        // }
        $sql = DBUtil::callFunction('fn_giftproduct', Util::sysParams($data['cmp'], 'getMyGiftCard'),json_encode($data));
        $prods = $sql[0];
        if(count($prods) > 0) {
            $res = json_decode(json_encode($sql[0][0]),true);
    
            if(empty($res['cardno'])) {
                return;
            }
    
            $emailArr['cmp']=$data['cmp'];
            $emailArr['cardno']=$res['cardno'];
            $emailArr['custname']=$res['custname'];
            $emailArr['amount']=$res['amount'];
    
            $mail=TMailing::handleRequest('order', 'gift_card', json_decode(json_encode($emailArr)));
        }
    }

    public static function checkOrUpdateGiftcard($data, $maderesponse = null, $check = true) {
        if($check) {
            // checks for gift card usage
            if(isset($data['data']['giftcards']) && !empty($data['data']['giftcards'])) {
                return true;
            } else {
                return false;
            }
        } else {
            // returns gift card payment array object
            $gctotal = 0;
            foreach($data['data']['giftcards'] as $key=>$value){
                $gctotal += $value->balance; // added round becoz generating expo. value
            }
            if($gctotal >= $maderesponse['total']) {
                return [
                    'payment_source'=>'ECOMMERCE',
                    'payment_method'=>'CASH',
                    'amount_paid'=>$maderesponse['total'],
                ];
            } else {
                return [
                    'payment_source'=>'ECOMMERCE',
                    'payment_method'=>'CASH',
                    'amount_paid'=> $gctotal,
                ];
            }
        }
    }

    public static function updateGCBalanceHold($data){
        try {
            DBUtil::callProcedure('sp_giftproduct', Util::sysParams($data['cmp'], 'updateGCBalanceHold'), json_encode($data));
        }
        catch(Exception $e) {
            Util::wlog('treez_php_updateGCBalanceHold_',$e->getMessage(), __LINE__);
        }   
    }

    public static function checkOrGetRewards($data, $check = true) {
        if($check) {
            // checks for gift card usage
            if(isset($data['data']['reward_points_amt']) && ($data['data']['reward_points_amt'])>0) {
                return true;
            } else {
                return false;
            }
        } else {
            return [
                    'payment_source'=>'ECOMMERCE',
                    'payment_method'=>'CHECK',
                    'amount_paid'=>$data['data']['reward_points_amt']
            ];
        }
    }

    public static function strongholdpayment($data, $maderesponse, $final_amount) {
        try{
            Util::wlog('paymentlog','In Payment', __LINE__);
            $charge_payload = [
                'amount'                => floor($final_amount*100),
                'customer_id'           => $data['data']['sh_custid'],
                'payment_source_id'     => $data['data']['paymentsourceid'],
                'payment_type'          => 'bank_debit',
                'treez_order_id'        => $maderesponse['order_number'],
                'terminal_id'           => $data['data']['terminalid'],
                'cmp'                   => $data['data']['cmp'],
                'dispensary'            => $data['data']['dispensary']
            ];
            Util::wlog('paymentlog',$charge_payload, __LINE__);
            $charge_respo = Strongholdpay::create_charge($charge_payload);
            Util::wlog('paymentlog',$charge_respo, __LINE__);
            if($charge_respo['status']==0) { 
                // Payment Failed
                Util::wlog('paymentlog','In Paylink method', __LINE__);

                $paylink_order_arr = [
                    "total_amount"     => floor($maderesponse['total']*100),
                    "tax_amount"       => floor($maderesponse['tax_total']*100),
                    "sub_amount"       => floor($maderesponse['sub_total']*100),
                    "convenience_fee"  => 0,
                    "order"            => []
                ];        

                $paylink_order_arr['order'] = array_map(function($element){
                    return [
                        "name"          => $element['product_size_name'],
                        "quantity"      => $element['quantity'],
                        "total_amount"  => floor($element['price_total']*100),
                        "price"         => floor($element['price_sell']*100),
                        "description"   => null,
                        "image_url"     => null
                    ];
                },
                $maderesponse['items']);

                $envcache = Util::envCredential($data['data']['cmp']);
                if(empty($envcache->shpredirecturl)){
                    Util::wlog('error_hpurlenv', 'StrongHold Redirect Url is missing ');
                    throw new Exception("StrongHold Redirect Url is missing ");
                }

                $paylink_payload = [
                        'type'          => 'checkout',
                        'customer_id'   => $data['data']['sh_custid'],
                        'charge_id'     => null,
                        'order'         => $paylink_order_arr,
                        'cmp'           => $data['data']['cmp'],
                        'dispensary'    => $data['data']['dispensary'],
                        'charge'        => [
                                                "type"              => "bank_debit",
                                                "amount"            => floor($maderesponse['total']*100),
                                                "currency"          => "usd",
                                                "customer_id"       => $data['data']['sh_custid'],
                                                "payment_source_id" => $data['data']['paymentsourceid'],
                                                "source_id"         => null,
                                                "external_id"       => $maderesponse['order_number'],
                                                "terminal_id"       => $data['data']['terminalid']
                                            ], 
                        'callbacks'     =>  [
                                                "success_url"       => $envcache->shpredirecturl, //env('SHP_PAYLINK_SUCCESS_URL'),
                                                "exit_url"          => $envcache->shpredirecturl, //env('SHP_PAYLINK_FAIL_URL')
                                            ],
                    ];
                    
                Util::wlog('paymentlog',$paylink_payload, __LINE__);
                $paylink_respo = Strongholdpay::create_paylink($paylink_payload);
                Util::wlog('paymentlog',$paylink_respo, __LINE__);

                if($paylink_respo['status']==1){ 
                    $payment_link = $paylink_respo['result']['url'];
                    $ticket_note = ', Payment Failed';
                    $ticket_note .= ', Payment Link = '.$payment_link;
                    return ['status'=>false,'code'=>99,'ticket_note'=>$ticket_note,'api_res'=>$paylink_respo];
                }
                else 
                {
                    $ticket_note = ', Payment Failed. Paylink has not generated due to '.$charge_respo['error'];
                    return ['status'=>false,'code'=>99,'ticket_note'=>$ticket_note,'api_res'=>$charge_respo];
                }
            }
            else {
                return ['status'=>true,'code'=>200, 'api_res'=> $charge_respo['result']];
            }
        }
        catch(\Exception $e){
            throw new Exception($e->getMessage()); 
        }
    }

    public static function hypurpayment($data, $final_amount) {
        try
        {
            $pay_response = Hypur::pay([
                'cmp'            => $data['data']['cmp'], 
                'dispensary'     => $data['data']['dispensary'], 
                'paccode'        => $data['data']['paccode'], 
                'amount'         => $final_amount,
                'custid'         => $data['data']['ecom_custid'],
                'hypurcode'      => $data['data']['hypurcode']
            ]);
            if($pay_response['status']==1) {
                return ['status'=>true,'code'=>200, 'api_res'=> $pay_response];
            }
            else {
                return ['status'=>false,'code'=>99,'api_res'=>$pay_response];
            }
        }
        catch(Exception $e) {
            throw new Exception($e->getMessage());
        }
    }

    public static function updateTicket($authData, $data, $maderesponse, $treez_payment_obj, $ticket_note) {
        try {
            $envcache = Util::envCredential($data['data']['cmp']);
            if(empty($envcache->treezurl)){
                Util::wlog('error_treezenv', 'Treez Url are missing ');
                throw new Exception("Treez Url are missing ");
            }
            $maxTries = 3;
            $try      = 1;
            $pos_url  = $envcache->treezurl; //Self::$api_url;
            $cmp      = 'cmp'.$data['data']['cmp'];
            $ticketid = $maderesponse['ticket_id'];
            $url      = $pos_url . $authData['integDispId'] . "/ticket/update/" . $ticketid;

            $header = array(
                'Content-Type:  application/json',
                'authorization: ' . $authData['access_token'],
                'client_id: ' . $authData['integClientID'],
            );
            $request    = [
                             'type'                   => $maderesponse['type'],
                             'order_source'           => 'ECOMMERCE',
                             'order_status'           => $maderesponse['order_status'],
                             'payment_status'         => 'UNPAID',
                             'ticket_note'            => $ticket_note,
                             'payments'               => $treez_payment_obj['payments'],
                             'payment_authorization'  => $treez_payment_obj['payment_authorization']
                          ];
            $request    = json_encode($request);
            Util::wlog('updateticket',$request);
            retrylabel:
            $response   = Util::HandleCurl('PUT', $header, $request, $url);
            $decoded    = json_decode($response, true);
            Util::wlog('updateticket',$decoded);
            if (isset($decoded['fault'])) {
                if ($try <= $maxTries) {
                    $try++;
                    sleep(1);
                    goto retrylabel;
                }
            }
            if(isset($decoded['resultCode']) && $decoded['resultCode']=='SUCCESS') {
                return ['status'=>true,'code'=>200,'api_res'=>$decoded];
            }
            if(isset($decoded['resultCode']) && $decoded['resultCode']=='FAIL') {
                return ['status'=>false,'code'=>101,'api_res'=>$decoded];
            }
            if (isset($decoded['fault'])) {
                return ['status'=>false,'code'=>101,'api_res'=>$decoded];
            }
            if ($response == false) {
                return ['status'=>false,'code'=>101,'api_res'=>$decoded];
            }
            return ['status'=>true,'code'=>200,'api_res'=>$decoded];
        }   
        catch(Exception $e)  {
            return ['status'=>false,'code'=>101,'api_res'=>$e->getMessage()];
        }
    } 

    public static function makePaymentObject($payment_res, $gateway, $orderid) {  
            if($gateway == 'Stronghold') {
                $payment_method = 'ACH';
                $payment_status = 'AUTHORIZED';
                $payment_res['amount'] = ($payment_res['amount']/100);
                $payment_res['fee'] = ($payment_res['fee']/100);

            }   
            else if ($gateway == 'Hypur') {
                $payment_method = 'HYPUR_CUSTOM';
                $payment_status = 'PAID';
            } 
            else {
                @$payment_method = $payment_res['payment_method'];
                @$payment_status = $payment_res['payment_status'];
            }
            @$arr['orderid']            = $orderid;     
            @$arr['paytype']            = $gateway;     
            @$arr['paymethod']          = $payment_method; 
            @$arr['payment_method']     = $payment_method; 
            @$arr['payment_date']       = Carbon::now(); 
            @$arr['payment_id']         = $payment_res['id'];
            @$arr['fee']                = $payment_res['fee'];
            @$arr['type']               = $payment_res['bank_debit'];
            @$arr['amount_paid']        = $payment_res['amount'];
            @$arr['amount']             = $payment_res['amount'];
            @$arr['status']             = $payment_res['status'];
            @$arr['currency']           = $payment_res['currency'];
            @$arr['created_at']         = $payment_res['created_at'];
            @$arr['customer_id']        = $payment_res['customer_id'];
            @$arr['description']        = $payment_res['description'];
            @$arr['external_id']        = $payment_res['external_id'];
            @$arr['authorized_at']      = $payment_res['authorized_at'];
            @$arr['convenience_fee']    = $payment_res['convenience_fee'];
            @$arr['payment_source']     = $payment_res['payment_source_id'];
            @$arr['payment_status']     = $payment_status;
            return $arr;
    }

    public static function updateCustomerRewardsPoints($data)
    {
        try {
            $sql = DB::select("select i.poscustid FROM cmp" . $data['cmp'] . ".integratedcustomer i inner join cmp" . $data['cmp'] . ".customer c on i.custid=c.id where c.id=" . $data['customer_id'] . " and i.dispensaryid = '".$data['dispensary']."' and i.isactive=true");
            if (count($sql) > 0) {
                $respArr = [];
                foreach ($sql as $rec) {
                    $authData = Self::getToken($data['dispensary'], $data['cmp']);
                    $header = array(
                        'Content-Type:  application/json',
                        'authorization: ' . $authData['access_token'],
                        'client_id: ' . $authData['integClientID'],
                    );
                    $envcache = Util::envCredential($data['cmp']);
                    if(empty($envcache->treezurl)){
                        Util::wlog('error_treezenv', 'Treez Url are missing ');
                        throw new Exception("Treez Url are missing ");
                    }
                    $pos_url = $envcache->treezurl; //Self::$api_url;
                    //$url = Self::$api_url . $authData['integDispId'] . "/customer/" . $rec->poscustid;
                    $url = $envcache->treezurl . $authData['integDispId'] . "/customer/" . $rec->poscustid;
                    $h_res = Util::HandleCurl('GET', $header, null, $url);
                    $response = json_decode($h_res, true); 
                
                    $params = [];
                    $params['rewardspoints'] = $response['data']['rewards_balance'];
                    $params['cmp'] = $data['cmp'];
                    $params['custid'] = $data['customer_id'];
                    
                    $sqlproc = DBUtil::callProcedure('sp_customer', Util::sysParams($data['cmp'], 'updatecustomerrewards'), json_encode($params));
                    $res = json_decode($sqlproc['res']);
                    
                    if ($response['resultCode'] == 'SUCCESS') {
                        $respArr[] = ['poscustid' => $rec->poscustid, 'dispensaryid' => $rec->dispensaryid, 'msg' => 'Rewards Points updated successfully'];
                    } else {
                        $respArr[] = ['poscustid' => $rec->poscustid, 'dispensaryid' => $data['dispensary'], 'msg' => $response['resultReason']];
                    }
                }
            }
        } catch (\Throwable $th) {
            return ['status' => 0, 'customerid' => 0, 'error' => $th, 'resultCode' => 'FAIL', 'resultReason' => $th];
        }
    }

    public static function sendOrderSms($data,$module,$sub_module){ 
        $qury = DB::select("select count(1) as count from cmp".$data['cmp'].".smssettings where module='$module' AND sub_module='$sub_module' AND allow_to_send=true");
        if($qury[0]->count==0) {
            return false;
        }
        $sql = DBUtil::callFunction('fn_order', Util::sysParams($data['cmp'], 'getMyOrderForSMS'),json_encode(['orderid'=>$data['orderid']]));
        
        if(count($sql[0])>0)
        {   
            $res = json_decode(json_encode($sql[0][0]),true);
            $smsArr = [];
            $smsArr['name']=$res['cust_name'];
            $smsArr['order_total']="$".$res['totalsellingprice'];
            $smsArr['orderno']=$res['orderid'].' | '.$res['posorderid'].' ('.$res['ordertype'].')';
            $smsArr['phone']=trim($res['dispphone']);
            $smsArr['module']=$module;
            $smsArr['submodule']=$sub_module;
            $smsArr['tinyurl']=$res['tinyurl'];
            $smsArr['disp_name']=$res['dispname'];
            @$smsArr['daytype']=$data['daytype'];
            $cust_phone = $res['cust_mobile'];
            
            if(empty($cust_phone)) throw new Exception("Mobile not found for $sub_module notification");
            $sql1 = DBUtil::callFunction('fn_getsmstemplate',Util::sysParams($data['cmp'], ''), json_encode($smsArr)); 
            if(count($sql1[0])>0)
            {
                $retData  = $sql1[0][0]; 
                $text = $retData->template;
                $expdt = json_decode($retData->expdata);
                foreach ($expdt as $key => $value) {
                    $text = str_replace("{" . $key . "}", $value, $text);
                }
                $resp = SMSController::sendSMSOTP($cust_phone, $text,$data['cmp'], $sub_module);
                
            }
            else {
               throw new Exception("Template not found for $sub_module notification"); 
            }
        }
        else {
            throw new Exception("Order details not found for $sub_module notification"); 
        }
    }

    public static function sendOrderMailandSms($data){
        if($data['ticket_id'] && ($data['order_status']=='PACKED_READY' || $data['order_status']=='CANCELED' || $data['order_status']=='COMPLETED')){
            try {
                //if(DB::table('cmp'.$data['cmp'].'.ordermaster')->where('posorderid',$data['ticket_id'])->count()>0) {
                    if($data['order_status']!='COMPLETED'){
                        Self::sendOrderSms(['cmp'=>$data['cmp'],'orderid'=>$data['ticket_id']],'order',$data['order_status']);
                    }
                    Self::sendOrderMail(['cmp'=>$data['cmp'],'orderid'=>$data['ticket_id']],'order',$data['order_status']);
                //}
            } catch(Exception $e) {
                Util::wlog('smsormail'.$data['order_status'],$e->getMessage());
            }
        }
    }

    public static function callDefaultImages($data)
    {
        $dispid = $data['dispensary'];
        if($data["syncall"] == 'false'){
            $dispid = '';
        }
        $op = \Artisan::call('sync:defaultImages ' . $data['cmp'] . ' ' . $dispid ); //. ' ' . $data['dispensary']
        sleep(5);
        //Clear product cache
        \Artisan::call("prepare:productlist ".$data['cmp'] ." ".$dispid	); //." ".$data['dispensary']	
        return ['status' => 1, 'result' => $op, 'errorcode' => null, 'msg' => null];
    }
}
