<?php

namespace App\Model;

use App\Model\BaseModel;
use App\Core\Service\Logger;
use App\Service\Messaging;
use App\Model\MasterModel;
use App\Library\Utilities;
use App\Core\Library\Crypto;
use App\Config\Main;
use Exception;

class MasterDataSetModel extends BaseModel
{
    private $model;
    private $library;
    private $Messaging;

    public function  __construct()
    {
        parent::__construct();
        $this->model = new MasterModel();
        $this->library = new Utilities();
        $this->Messaging = new Messaging();
    }

    //   PRE INSERT/UPDATE PROCESS   (START)
    public function preInsertUpdateGetData($master, $input)
    {
        try {
            switch ($master) {
                case 'users_master':
                    return $this->getClientUserData($input);
                case 'customer_master':
                    if (count($input['addressForm']) == 0) {
                        return ["status" => false,'error' => 'Please add atleast one address'];
                    }
                    return ["status" => true, "dbData" => $input];;
                case 'location_pincode':
                    return $this->getPincodeData($input);
                case 'order_status':
                    return $this->getOrderStatusData($input);
                case 'coupon_master':
                    return $this->getCouponData($input);
                case 'users_group_master':
                    return $this->getClientUserGroupData($input);
                case 'item_master':
                    return $this->getItemMasterData($input);
                case 'item_package_master':
                    return $this->getItemPackageMasterData($input);
                case 'stockout_inventory':
                    return $this->getStockOutInventoryData($input);
                case 'purchase_master':
                    return $this->beforeInsertUpdatePurchase($input);
                case 'purchasereturn_master':
                    return $this->beforeInsertUpdatePurchaseReturn($input);
                case 'itemcategory_master':
                    return $this->validateDuplicateTax($input);
                case 'item_stock':
                    return $this->validateDuplicateBranch($input);
                case 'order_courier':
                    return $this->getOrderCourierData($input);
                case 'leads':
                    return $this->checkCustomer($input);
                default:
                    return ["status" => true, "dbData" => $input];
            }
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    public function checkCustomer($data)
    {
        try {
            $dbData = $data;
            if (empty($data['customer_id'])) {
                $sql = "SELECT id FROM " . $data['dbname'] . "." . $this->tables['customer_master'] . " WHERE mobile_number=:phone AND country_code=:code";
                $custrs = $this->fetchSingleData($sql, [':phone' => $data['contact_no'], ':code' => $data['contact_code']]);
                if (empty($custrs['status'])) {
                    throw new \Exception($custrs['error']);
                }
                if (!empty($custrs['data'])) {
                    $dbData['customer_id'] = $custrs['data']['id'];
                    return ["status" => true, "dbData" => $dbData];
                }
                $customer = [
                    'customer_name' => $data['client_name'],
                    'mobile_number' => $data['contact_no'],
                    'country_code'  => $data['contact_code'],
                    'email_id'      => $data['email'],
                    'alt_mobile1'   => !empty($data['alt_contact_no']) ? $data['alt_contact_no'] : NULL,
                    'branch_id'     => $data['branch'],
                    'lead_source'   => $data['lead_source'],
                    'customer_type' => $data['customer_type']
                ];
                $customer_address = [
                    'address'       => $data['address'],
                    'address_pincode'       => $data['pincode'],
                    'address_state_id'      => $data['state'],
                    'address_city_id'       => $data['city'],
                    'is_default'    => 1
                ];
                $custrs = $this->insert($data['dbname'] . '.' . $this->tables['customer_master'], $customer);
                if (empty($custrs['status'])) {
                    throw new \Exception($custrs['error']);
                }
                $customer_address['customer_id'] = $custrs['insert_id'];
                $custaddrs = $this->insert($data['dbname'] . '.' . $this->tables['customer_address_master'], $customer_address);
                if (empty($custaddrs['status'])) {
                    throw new \Exception($custaddrs['error']);
                }
                $dbData['customer_id'] = $custrs['insert_id'];
                return ["status" => true, "dbData" => $dbData];
            }
            return ["status" => true, "dbData" => $dbData];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    public function getOrderCourierData($data)
    {
        try {
            $dbData = [];
            $dbData['order_id'] = $data['order_id'];
            $dbData['courier_api_type'] = $data['courier_api_type'];
            $dbData['courier_weight'] = isset($data['courier_weight']) ? $data['courier_weight'] : NULL;
            $dbData['courier_product_name'] = isset($data['courier_product_name']) ? $data['courier_product_name'] : NULL;
            $dbData['courier_height'] = isset($data['courier_height']) ? $data['courier_height'] : NULL;
            $dbData['courier_length'] = isset($data['courier_length']) ? $data['courier_length'] : NULL;
            $dbData['courier_breath'] = isset($data['courier_breath']) ? $data['courier_breath'] : NULL;
            $dbData['courier_payment_mode'] = isset($data['courier_payment_mode']) ? $data['courier_payment_mode'] : NULL;
            $dbData['courier_ewaybill_no'] = isset($data['courier_ewaybill_no']) ? $data['courier_ewaybill_no'] : NULL;
            $dbData['courier_transdistance'] = isset($data['courier_transdistance']) ? $data['courier_transdistance'] : NULL;
            $dbData['courier_transporter_id'] = isset($data['courier_transporter_id']) ? $data['courier_transporter_id'] : NULL;
            $dbData['courier_transporter_name'] = isset($data['courier_transporter_name']) ? $data['courier_transporter_name'] : NULL;
            $dbData['courier_type_of_delivery'] = isset($data['courier_type_of_delivery']) ? $data['courier_type_of_delivery'] : NULL;
            $dbData['courier_type_of_service'] = isset($data['courier_type_of_service']) ? $data['courier_type_of_service'] : NULL;
            $dbData['courier_unit_of_measure'] = isset($data['courier_unit_of_measure']) ? $data['courier_unit_of_measure'] : NULL;
            $dbData['pickup_date'] = isset($data['pickup_date']) ? date('Y-m-d', strtotime($data['pickup_date'])) : NULL;
            $dbData['origin_area'] = isset($data['origin_area']) ? $data['origin_area'] : NULL;
            $dbData['customer_code'] = isset($data['customer_code']) ? $data['customer_code'] : NULL;
            $dbData['product_type'] = isset($data['product_type']) ? $data['product_type'] : NULL;
            $dbData['pickup_hour'] = isset($data['pickup_hour']) ? $data['pickup_hour'] : NULL;
            $dbData['pickup_minutes'] = isset($data['pickup_minutes']) ? $data['pickup_minutes'] : NULL;
            $dbData['courier_service_type'] = isset($data['courier_service_type']) ? $data['courier_service_type'] : NULL;
            $dbData['courier_airway_bill_number'] = isset($data['courier_airway_bill_number']) ? $data['courier_airway_bill_number'] : NULL;
            $dbData['courier_mainfest_id'] = isset($data['courier_mainfest_id']) ? $data['courier_mainfest_id'] : NULL;
            $dbData['courier_voulmetric_weight'] = isset($data['courier_voulmetric_weight']) ? $data['courier_voulmetric_weight'] : 0.00;
            $dbData['courier_packing_type'] = isset($data['courier_packing_type']) ? $data['courier_packing_type'] : 0.00;
            return ["status" => true, "dbData" => $dbData];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function validateDuplicateBranch($data)
    {
        try {
            $branch = $data['stockForm'];
            $branchIdIdCounts = [];
            $duplicates = [];

            foreach ($branch as $item) {
                $branchId = $item['branch_id'];
                if (isset($branchIdIdCounts[$branchId])) {
                    $branchIdIdCounts[$branchId]++;
                    $duplicates[$branchId] = true;
                } else {
                    $branchIdIdCounts[$branchId] = 1;
                }
            }
            if (!empty($duplicates)) {
                return ["status" => false, "error" => "Duplicate branch id(s) found: " . implode(', ', array_keys($duplicates))];
            }
            return ["status" => true, "dbData" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function validateDuplicateTax($data)
    {
        try {
            $tax = $data['taxForm'];
            $taxIdCounts = [];
            $duplicates = [];

            foreach ($tax as $item) {
                $taxId = $item['tax_id'];
                if (isset($taxIdCounts[$taxId])) {
                    $taxIdCounts[$taxId]++;
                    $duplicates[$taxId] = true;
                } else {
                    $taxIdCounts[$taxId] = 1;
                }
            }
            if (!empty($duplicates)) {
                return ["status" => false, "error" => "Duplicate tax id(s) found: " . implode(', ', array_keys($duplicates))];
            }
            return ["status" => true, "dbData" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function beforeInsertUpdatePurchaseReturn($data)
    {
        try {
            $dbPrefix = $data['dbname'];
            $id = $data['id'];
            $resp = $this->model->validatePurchaseItemQty($data['purchase_id'], $data['dbname'], $data['id']);
            if (!$resp['status'])
                throw new Exception($resp['error']);
            $purchaseQty = array_column($resp['data'], 'qty', 'item_id');
            $itemIds = array_keys($purchaseQty);
            foreach ($data['itemForm'] as $key => $val) {
                $item_id = $val['item_id'];
                if (!in_array($item_id, $itemIds)) {
                    throw new Exception("Item does not exist in purchase list " . $val['item_desc']);
                }
                $itemQty = round($val['qty'], 2) + round($val['free_qty'], 2);
                if ($itemQty > $purchaseQty[$item_id]) {
                    throw new Exception("Item Quantity cannot not exced ($purchaseQty[$item_id]) for item desc " . $val['item_desc']);
                }
            }
            $data['total_no_item'] = count($data['itemForm']);
            $data['no_gst'] = $data['no_gst'] ? 1 : 0;
            ($id > 0) ? $this->model->stockIn($id, $dbPrefix, 0, 'PR') : '';
            return ["status" => true, "dbData" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function beforeInsertUpdatePurchase($data)
    {
        try {
            //Validate on update as other user has updated this earlier or not
            // if($this->my_model->validatePurchaseOnUpdate(array('purchase_update_time'=>$data['purchase_update_time']),$data['id'])==FALSE && $data['id']>0){
            //  	echo json_encode(array("statusCode" => "400",'error'=>'Please refresh the page as someone updated the same purchase'));
            // 	 die;
            //  }
            // function validatePurchaseOnUpdate($data, $id){
            //     $validatePurchase = $this->db->select('id')->where(array('id' => $id, 'purchase_update_time' => $data['purchase_update_time']))->get($this->purchase_master_table)->row_array();
            //     if ($validatePurchase['id'] < 1) {
            //         return false;
            //     }
            //     return true;}
            $dbPrefix = $data['dbname'];
            $id = $data['id'];
            $invoice_no = $data['invoice_number'];
            $vendor_id = $data['vendor_id'];
            $data['total_no_item'] = count($data['itemForm']);
            $data['no_gst'] = $data['no_gst'] ? 1 : 0;
            //Validate Invoice Number as it should be unique
            $where = "invoice_number = $invoice_no AND vendor_id = $vendor_id";
            if ($data['id'] > 0) {
                $where .= " AND id != $id";
            }
            $duplicateInvoice = $this->getNumRows("SELECT id FROM `$dbPrefix`.`purchase_master` WHERE $where");
            if (!$duplicateInvoice['status'])
                throw new \Exception($duplicateInvoice['error']);
            if ($duplicateInvoice['count'] > 0) {
                return ["status" => false, "error" => 'Invoice number already exist'];
            }
            ($id > 0) ? $this->model->stockIn($id, $dbPrefix, 1, 'PU') : '';
            return ["status" => true, "dbData" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getClientUserData($dbData)
    {
        try {
            $userLogin = $dbData['user_login'];
            $login_sql = "SELECT * FROM `sanordo_db`.`client_users_master` WHERE user_login = '$userLogin'";
            if (!empty($dbData['user_id'])) {
                $login_sql .= " AND comp_user_id != " . $dbData['user_id'];
            }

            $checkLogin = $this->fetchSingleData($login_sql);
            if (!$checkLogin['status']) {
                throw new \Exception($checkLogin['error']);
            }
            if ($checkLogin['data']) {
                throw new \Exception('This login ID not available');
            }
            if (!empty($dbData['user_email'])) {
                $email = $dbData['user_email'];
                $checkEmail = $this->fetchSingleData("SELECT * FROM `sanordo_db`.`client_users_master` WHERE user_email = '$email'");
                if (!$checkEmail['status']) {
                    throw new \Exception($checkEmail['error']);
                }
                if ($checkEmail['data']) {
                    throw new \Exception('This email already exist');
                }
            }
            if (!empty($dbData['user_phone'])) {
                $phone = $dbData['user_phone'];
                $checkPhone = $this->fetchSingleData("SELECT * FROM `sanordo_db`.`client_users_master` WHERE user_phone = '$phone'");
                if (!$checkPhone['status']) {
                    throw new \Exception($checkPhone['error']);
                }
                if ($checkPhone['data']) {
                    throw new \Exception('This mobile no. already exist');
                }
            }
            if ($dbData['master_type'] == 0 && count($dbData['branchForm']) == 0) {
                throw new \Exception('This user isn\'t master, So please add atleast one branch');
            }
            if ($dbData['action'] == 'update') {
                if (!empty($dbData['sys_gen_password'])) {
                    $dbData['sys_gen_password'] = password_hash($dbData['sys_gen_password'], PASSWORD_BCRYPT);
                    $dbData['user_pass'] = $dbData['sys_gen_password'];
                }
            } else if (!empty($dbData['sys_gen_password'])) {
                $dbData['sys_gen_password'] = password_hash($dbData['sys_gen_password'], PASSWORD_BCRYPT);
            }

            $manager_id = isset($dbData['manager_id']) && $dbData['manager_id'] !== '' ? $dbData['manager_id'] : null;
            $dbData['manager_id'] = $manager_id;
            if (empty($dbData['orderby_change_rights'])) {
                $dbData['orderby_change_rights'] = 0;
            }
            if (empty($dbData['master_type'])) {
                $dbData['master_type'] = 0;
            }
            if ($dbData['master_type'] == 1 && $dbData['orderby_change_rights'] != 1) {
                throw new \Exception('Order book by change rights must be yes if master Rights yes');
            }
            return ["status" => true, "dbData" => $dbData];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getPincodeData($dbData)
    {
        try {
            if (empty($dbData['min_delivery_days'])) {
                $dbData['min_delivery_days'] = 0;
            }
            if (empty($dbData['max_delivery_days'])) {
                $dbData['max_delivery_days'] = 0;
            }
            return ["status" => true, "dbData" => $dbData];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getOrderStatusData($dbData)
    {
        try {
            if (!empty($dbData['hit_api_to_client']) && $dbData['hit_api_to_client'] !== '') {
                if (empty($dbData['api_url'])) {
                    throw new \Exception('WhatsApp URLs (Comma-separated) required');
                }
            }
            (empty($dbData['order_editable'])) ? $dbData['order_editable'] = 0 : '';
            (empty($dbData['mark_as_default_complete'])) ? $dbData['mark_as_default_complete'] = 0 : '';
            (empty($dbData['stock_in_out'])) ? $dbData['stock_in_out'] = 0 : '';
            (empty($dbData['status_type'])) ? $dbData['status_type'] = 0 : '';
            (empty($dbData['hit_api_to_client'])) ? $dbData['hit_api_to_client'] = 0 : '';
            (empty($dbData['status_sequence'])) ? $dbData['status_sequence'] = 0 : '';
            (empty($dbData['show_payment_link'])) ? $dbData['show_payment_link'] = 0 : '';
            if ($dbData['stock_in_out'] == 1 && $dbData['mark_as_default_complete'] != 2) {
                throw new \Exception('If you marked this as StockIn then it is necessary to mark as completed !!');
            }
            if ($dbData['status_type'] == 21 && $dbData['mark_as_default_complete'] != 2) {
                throw new \Exception('If status is invoice return than it should be mark as completed !!');
            }
            if ($dbData['stock_in_out'] == 2) {
                //Check other Stock out is checked because stock out can be placed at one stage ony
                if ($dbData['action'] == 'insert') {
                    $checkData = $this->model->getMasterDataByID($dbData['dbname'], 'order_status', '2', 'stock_in_out');
                } else if ($dbData['action'] == 'update') {
                    $id = $dbData['id'];
                    $checkData = $this->model->getMasterDataByID($dbData['dbname'], 'order_status', '2', 'stock_in_out', '*', "id != $id");
                }
                if (isset($checkData['data']['id']) && $checkData['data']['id'] > 0) {
                    throw new \Exception('Sorry, Only one status can have Stock Out right!!');
                }
            }
            return ["status" => true, "dbData" => $dbData];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getCouponData($dbData)
    {
        try {
            if ($dbData['coupon_type'] == 1 && $dbData['discount'] > 100) {
                throw new \Exception('Discount cannot be greater than 100%');
            }
            $dbData['coupon_title'] = strtoupper($dbData['coupon_title']);
            $dbData['valid_from'] = date("Y-m-d", strtotime($dbData['valid_from']));
            $dbData['valid_to'] = date("Y-m-d", strtotime($dbData['valid_to']));
            $dbData['ip_address'] = $_SERVER['REMOTE_ADDR'];
            if ($dbData['action'] == 'insert') {
                if ($dbData['coupon_status_type'] == 1) {
                    $validateCouponSingle = $this->model->validateCouponCodes($dbData['dbname'], array(), array(
                        'coupon_name' => $dbData['coupon_title']
                    ));
                    if (count($validateCouponSingle) > 0) {
                        throw new \Exception('Coupon Code already exist');
                    }
                }
            } else if ($dbData['action'] == 'update') {
                $select = "*,date_format(date(valid_from),'%Y-%m-%d') as valid_from,date_format(date(valid_to),'%Y-%m-%d') as valid_to";
                $id = $dbData['id'];
                $couponDbMasterArray2 = $this->model->getMasterDataByID($dbData['dbname'], 'coupon_master', $id, 'id', $select);
                $couponDbMasterArray = $couponDbMasterArray2['data'];
                $dbData['CouponsData'] = $couponDbMasterArray;
                if ($couponDbMasterArray['coupon_status_type'] == 2 && $dbData['coupon_status_type'] == 1) { //Transfer from bulk order to single coupon
                    if ($this->model->getTotalCouponCount($dbData['dbname'], "coupon_master_id = $id AND is_used = 1", array('status' => FALSE)) > 0) {
                        throw new \Exception('Sorry you cannot chnage as one or more coupons are used !!');
                    }
                } else if ($couponDbMasterArray['coupon_status_type'] == 2 && $dbData['coupon_status_type'] == 2) {
                    $usedCount = $this->model->getTotalCouponCount($dbData['dbname'], "coupon_master_id = $id AND is_used = 1", array('status' => FALSE));
                    if ($couponDbMasterArray['coupon_title'] != $dbData['coupon_title'] && $usedCount > 0) { // If want to change series
                        throw new \Exception('Sorry you cannot chnage coupon series as one or more coupons are used !!');
                    } else if ($dbData['coupon_count'] < $couponDbMasterArray['coupon_count'] && $usedCount > $dbData['coupon_count']) { // Want to reduce more coupon from this series
                        throw new \Exception("You cannot reduce the number of coupons as more that $usedCount coupons are already used");
                    }
                } else if ($couponDbMasterArray['coupon_status_type'] == 1 && $dbData['coupon_status_type'] == 1) { // Only Coupon Change Single Coupon type
                    $validateCouponSingle = $this->model->validateCouponCodes($dbData['dbname'], "coupon_master_id != $id", array('coupon_name' => $dbData['coupon_title']));
                    if (count($validateCouponSingle) > 0) {
                        throw new \Exception('Coupon Code already exist');
                    }
                }
            }
            return ["status" => true, "dbData" => $dbData];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getClientUserGroupData($dbData)
    {
        try {
            (empty($dbData['hide_phone'])) ? $dbData['hide_phone'] = 0 : '';
            (empty($dbData['assign_lead'])) ? $dbData['assign_lead'] = 0 : '';
            (empty($dbData['assign_order'])) ? $dbData['assign_order'] = 0 : '';
            (empty($dbData['show_all'])) ? $dbData['show_all'] = 0 : '';
            (empty($dbData['self_update'])) ? $dbData['self_update'] = 0 : '';
            (empty($dbData['lead_update'])) ? $dbData['lead_update'] = 0 : '';
            (empty($dbData['update_address_after_shopify'])) ? $dbData['update_address_after_shopify'] = 0 : '';
            (empty($dbData['bulk_order_status'])) ? $dbData['bulk_order_status'] = 0 : '';
            (empty($dbData['allow_to_paid_order'])) ? $dbData['allow_to_paid_order'] = 0 : '';
            (empty($dbData['bulk_move_to_shopify'])) ? $dbData['bulk_move_to_shopify'] = 0 : '';
            (empty($dbData['order_status_id'])) ? $dbData['order_status_id'] = 0 : '';
            (empty($dbData['import_permission'])) ? $dbData['import_permission'] = 0 : '';
            (empty($dbData['allow_ip'])) ? $dbData['allow_ip'] = 0 : '';
            if (!empty($dbData['order_status_id'])) {
                $dbData['order_status_id'] = implode(',', $dbData['order_status_id']);
            } else {
                $dbData['order_status_id'] = '';
            }
            if (!empty($dbData['import_permission'])) {
                $dbData['import_permission'] = implode(',', $dbData['import_permission']);
            } else {
                $dbData['import_permission'] = '';
            }
            return ["status" => true, "dbData" => $dbData];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getItemMasterData($dbData)
    {
        try {
            $dbData['item_name'] = trim(ucfirst($dbData['item_name']));
            $dbData['item_code'] = $dbData['item_code'] ? trim(strtoupper($dbData['item_code'])) : $dbData['item_code'];
            $dbData['including_tax'] = $dbData['including_tax'] ? 1 : 0;
            // CHECK DUPLICATE CUSTOMER TYPE
            $customer_type = $dbData['rateForm'];
            $customerIdCounts = [];
            $duplicates = [];

            foreach ($customer_type as $item) {
                $customerId = $item['customer_type'];
                if (isset($customerIdCounts[$customerId])) {
                    $customerIdCounts[$customerId]++;
                    $duplicates[$customerId] = true;
                } else {
                    $customerIdCounts[$customerId] = 1;
                }
            }
            if (!empty($duplicates)) {
                return ["status" => false, "error" => "Duplicate customer type(s) found: " . implode(', ', array_keys($duplicates))];
            }

            return ["status" => true, "dbData" => $dbData];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getItemPackageMasterData($dbData)
    {
        try {
            $cost = array();
            if (count($dbData['itemForm']) == 0)
                throw new \Exception('Item is required');

            // CHECK DUPLICATE ITEM
            $items = $dbData['itemForm'];
            $itemIdCounts = [];
            $duplicates = [];

            foreach ($items as $item) {
                $itemId = $item['item_id'];
                if (isset($itemIdCounts[$itemId])) {
                    $itemIdCounts[$itemId]++;
                    $duplicates[$itemId] = true;
                } else {
                    $itemIdCounts[$itemId] = 1;
                }
            }
            if (!empty($duplicates)) {
                return ["status" => false, "error" => "Duplicate item id(s) found: " . implode(', ', array_keys($duplicates))];
            }

            for ($i = 0; $i < count($dbData['itemForm']); $i++) {
                if (empty($dbData['itemForm'][$i]['item_id']) || empty($dbData['itemForm'][$i]['quantity']) || empty($dbData['itemForm'][$i]['rate'])) {
                    throw new \Exception('Item, Quantity or Rate is required');
                } else {
                    array_push($cost, $dbData['itemForm'][$i]['rate']);
                }
            }
            $dbData['package_name'] = trim(ucfirst(strtolower($dbData['package_name'])));
            $dbData['remarks'] = $dbData['remarks'] ? trim($dbData['remarks']) : $dbData['remarks'];
            $dbData['item_count'] = count($dbData['itemForm']);
            $dbData['package_cost'] = array_sum($cost);
            return ["status" => true, "dbData" => $dbData];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getStockOutInventoryData($dbData)
    {
        try {
            if (count($dbData['stockOutForm']) == 0) {
                throw new \Exception('Item is required');
            }
            $itemCounts = [];
            $duplicates = [];
            foreach ($dbData['stockOutForm'] as $val) {
                if (empty($val['item_id'])) {
                    throw new \Exception('Item can\'t be empty');
                }
                $itemId = $val['item_id'];
                if (isset($itemCounts[$itemId])) {
                    $itemCounts[$itemId]++;
                    if ($itemCounts[$itemId] === 2) {
                        $duplicates[] = $itemId;
                    }
                } else {
                    $itemCounts[$itemId] = 1;
                }
            }
            if (!empty($duplicates)) {
                throw new \Exception('Duplicate items are not allowed');
            }
            $dbData['item_count'] = count($dbData['stockOutForm']);
            if ($dbData['action'] == 'update') {
                $this->model->stockOut($dbData['inv_id'], $dbData['dbname'], 1, 'IV');
                $this->model->stockIn($dbData['inv_id'], $dbData['dbname'], 1, 'IV');
            }
            return ["status" => true, "dbData" => $dbData];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }
    //   PRE INSERT/UPDATE PROCESS   (END)

    //   POST INSERT / UPDATE PROCESS   (START)
    public function postInsertUpdateProcess($master, $input)
    {
        try {
            switch ($master) {
                case 'coupon_master':
                    if ($input['action'] == 'insert') {
                        return $this->addCouponsData($input);
                    } else if ($input['action'] == 'update') {
                        return $this->updateTymAddCoupons($input);
                    }
                case 'customer_master':
                    return $this->insertCustomerAddress($input);
                case 'itemcategory_master':
                    return $this->insertCategoryTax($input);
                case 'item_master':
                    return $this->insertItemRate($input);
                case 'item_package_master':
                    return $this->insertPackageItem($input);
                case 'stockout_inventory':
                    return $this->insertStockOutInvItem($input);
                case 'order_status':
                    // 1 Default status 2 mark as completed
                    if ($input['mark_as_default_complete'] == 1) {
                        $dbname = $input['dbname'];
                        $inserted_id = $input['insert_id'];
                        return $this->model->updateDefaultAndCompleteStatus("`$dbname`.`order_status`", "id != $inserted_id AND mark_as_default_complete = 1");
                    }
                    return ["status" => true, "dbData" => $input];
                case 'users_master':
                    return $this->userBranchNDProfileRights($input);
                case 'leads':
                    return $this->insertLeadItemAndTax($input);
                case 'lead_flp_log':
                    return $this->updateLeadFlpMail($input);
                case 'purchase_master':
                    return $this->insertPurchaseItmTax($input);
                case 'purchasereturn_master':
                    return $this->insertPurchaseReturnItmTax($input);
                default:
                    return ["status" => true, "dbData" => $input];
                    break;
            }
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function insertPurchaseReturnItmTax($data)
    {
        try {
            $data['no_gst'] = $data['no_gst'] ? 1 : 0;
            if ((count($data['itemForm']) == 0))
                return ['status' => false, 'error' => 'Item required'];
            // if ((count($data['taxForm']) == 0) && $data['no_gst'] == 0)
            //     return ['status' => false, 'error' => 'Tax required'];
            $dbname = $data['dbname'];
            foreach ($data['itemForm'] as $val) {
                $itemDataMap[] = array(
                    'prtn_id'     => $data['insert_id'],
                    'cr_usr'          => $data['user_id'],
                    'item_id'         => $val['item_id'],
                    'item_desc'       => $val['item_desc'],
                    'hsn_sac_code'    => $val['hsn_sac_code'],
                    'rate'            => $val['rate'],
                    'final_rate'      => $val['final_rate'],
                    'discount'        => $val['discount'],
                    'discount_amount' => $val['discount_amount'],
                    'qty'             => $val['qty'],
                    'free_qty'        => $val['free_qty'],
                    'unit'            => $val['unit'],
                    'amount'          => $val['amount'],
                    'tax_percentage'  => $val['tax_percentage'],
                    'tax_amount'      => $val['tax_amount'],
                    'total_amount'    => $val['total_amount']
                );
            }

            if ($data['taxForm']) {
                foreach ($data['taxForm'] as $val) {
                    $taxDataMap[] = array(
                        'prtn_id'    => $data['insert_id'],
                        'item_id'        => $val['gridTax_item_id'],
                        'item_name'      => $val['gridTax_item_name'],
                        'tax_id'         => $val['gridTax_tax_id'],
                        'tax_name'       => $val['gridTax_tax_name'],
                        'tax_percentage' => $val['gridTax_tax_percentage'],
                        'taxable_amount' => $val['gridTax_taxable_amount'],
                        'tax_amount'     => $val['gridTax_tax_amount']
                    );
                }
            }
            if ($data['action'] == 'update') {
                $this->model->delete("`$dbname`.`purchasereturn_itemlist`", ['prtn_id' => $data['insert_id']]);
                $this->model->delete("`$dbname`.`purchasereturn_taxlist`", ['prtn_id' => $data['insert_id']]);
            }
            $itemResp = $this->model->batchInsert("`$dbname`.`purchasereturn_itemlist`", $itemDataMap);
            if (!$itemResp['status']) {
                throw new \Exception($itemResp['error']);
            }
            if ($data['no_gst'] == 0 && $data['taxForm']) {
                $taxResp = $this->model->batchInsert("`$dbname`.`purchasereturn_taxlist`", $taxDataMap);
                if (!$taxResp['status']) {
                    throw new \Exception($taxResp['error']);
                }
            }

            $this->model->stockIn($data['insert_id'], $dbname, 1, 'PR');
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function insertPurchaseItmTax($data)
    {
        try {
            $data['no_gst'] = $data['no_gst'] ? 1 : 0;
            if ((count($data['itemForm']) == 0))
                return ['status' => false, 'error' => 'Item required'];
            // if ((count($data['taxForm']) == 0) && $data['no_gst'] == 0)
            //     return ['status' => false, 'error' => 'Tax required'];
            $dbname = $data['dbname'];
            foreach ($data['itemForm'] as $val) {
                $itemDataMap[] = array(
                    'purchase_id'     => $data['insert_id'],
                    'cr_usr'          => $data['user_id'],
                    'item_id'         => $val['item_id'],
                    'item_desc'       => $val['item_desc'],
                    'hsn_sac_code'    => $val['hsn_sac_code'],
                    'rate'            => $val['rate'],
                    'discount'        => $val['discount'],
                    'qty'             => $val['qty'],
                    'free_qty'        => $val['free_qty'],
                    'unit'            => $val['unit'],
                    'tax_percentage'  => $val['tax_percentage'],
                    'final_rate'      => $val['final_rate'],
                    'discount_amount' => $val['discount_amount'],
                    'amount'          => $val['amount'],
                    'tax_amount'      => $val['tax_amount'],
                    'total_amount'    => $val['total_amount']
                );
            }

            if ($data['taxForm']) {
                foreach ($data['taxForm'] as $val) {
                    $taxDataMap[] = array(
                        'purchase_id'    => $data['insert_id'],
                        'item_id'        => $val['gridTax_item_id'],
                        'item_name'      => $val['gridTax_item_name'],
                        'tax_id'         => $val['gridTax_tax_id'],
                        'tax_name'       => $val['gridTax_tax_name'],
                        'tax_percentage' => $val['gridTax_tax_percentage'],
                        'taxable_amount' => $val['gridTax_taxable_amount'],
                        'tax_amount'     => $val['gridTax_tax_amount']
                    );
                }
            }
            if ($data['action'] == 'update') {
                $this->model->delete("`$dbname`.`purchase_itemlist`", ['purchase_id' => $data['insert_id']]);
                $this->model->delete("`$dbname`.`purchase_taxlist`", ['purchase_id' => $data['insert_id']]);
            }
            $itemResp = $this->model->batchInsert("`$dbname`.`purchase_itemlist`", $itemDataMap);
            if (!$itemResp['status']) {
                throw new \Exception($itemResp['error']);
            }
            if ($data['no_gst'] == 0 && $data['taxForm']) {
                $taxResp = $this->model->batchInsert("`$dbname`.`purchase_taxlist`", $taxDataMap);
                if (!$taxResp['status']) {
                    throw new \Exception($taxResp['error']);
                }
            }
            $this->model->stockIn($data['insert_id'], $dbname, 0, 'PU');
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }
    private function updateLeadFlpMail($data)
    {
        try {
            $dbname = $data['dbname'];
            $lead_id = $data['flp_lead_id'];
            if ($data['cmnt_with_email'] == 'YES') {
                $lead_status_data = $this->model->getMasterDataByID($dbname, 'lead_status', $data['lead_flp_status'], 'id');
                if ($lead_status_data['status']) {
                    if (!empty($lead_status_data['data']['email_template_id'])) {
                        $template_data = $this->model->getMasterDataByID($dbname, 'order_message_template', $lead_status_data['data']['email_template_id'], 'id');
                        if ($template_data['status']) {
                            $lead_data = $this->model->getLeadData($dbname, "t1.id = $lead_id ");
                            if ($lead_data['status']) {
                                if (!empty($lead_data['data'][0]['email'])) {
                                    $dataArray = $lead_data['data'][0];
                                    $email_to = explode(',', $dataArray['email']);
                                    $multiple_email = [];
                                    for ($x = 1; $x < count($email_to); $x++) {
                                        $multiple_email[] =  $email_to[$x];
                                    }
                                    if (!empty($multiple_email)) {
                                        $email_cc = implode(",", $multiple_email);
                                    } else {
                                        $email_cc = '';
                                    }
                                    $dbtemplate['temp_type'] = $template_data['data']['temp_type'];
                                    $dbtemplate['subject'] = $template_data['data']['subject'];
                                    if ($template_data['data']['email_type'] == 'TEXT') {
                                        $dbtemplate['template_body'] = $template_data['data']['template_body'];
                                    } else {
                                        $dbtemplate['template_body'] = view('mailer/email_form', ['body' => $template_data['data']['template_body']]);
                                        $dataEmailArr['embeddedImage']   = $this->compData($data['comp_id']);
                                    }
                                    $finalTemplate    = $this->Messaging->setEmailSMSTemplate(array_keys($this->template_vars), array($dbtemplate), $dataArray);
                                    $dataEmailArr['template_name'] = $template_data['data']['template_name'];
                                    $dataEmailArr['type']     = 'Email';
                                    $dataEmailArr['ref_type']     = 'LEAD - Comment & Mail';
                                    $dataEmailArr['ref_id']       = $lead_id;
                                    $dataEmailArr['subject']  = $finalTemplate['email_subject'];
                                    $dataEmailArr['body']     = $finalTemplate['email_body'];
                                    $dataEmailArr['to']      = $email_to[0];
                                    $dataEmailArr['user_id']      = $data['user_id'];
                                    $dataEmailArr['cc']        = !empty($email_cc) ? $email_cc : '';
                                    $dataEmailArr['attachments'] = [];
                                    $insert_data = $this->replaceEmailSmsFields($dataEmailArr);
                                    $logResp = $this->model->insert("`$dbname`.`email_sms_log`", $insert_data);
                                    if ($logResp['status']) {
                                        $resp = $this->model->update("`$dbname`.`leads`", ['lead_status' => $data['lead_flp_status']], ['id' => $data['flp_lead_id']]);
                                        // if ($resp['status']) {
                                        //     return ['status' => true];
                                        // } else {
                                        //     throw new \Exception($resp['error']);
                                        // }
                                    } else {
                                        throw new \Exception($logResp['message']);
                                    }
                                } else {
                                    throw new \Exception('Email Not Found');
                                }
                            } else {
                                throw new \Exception($lead_data['error']);
                            }
                        } else {
                            throw new \Exception($template_data['error']);
                        }
                    } else {
                        throw new \Exception('Please Assign Template');
                    }
                } else {
                    throw new \Exception($lead_status_data['error']);
                }
            } else {
                $resp = $this->model->update("`$dbname`.`leads`", ['lead_status' => $data['lead_flp_status']], ['id' => $lead_id]);
            }
            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    function replaceEmailSmsFields($data)
    {
        try {
            $ins_data['template_name'] = $data['template_name'];
            $ins_data['type'] = $data['type'];
            $ins_data['ref_id'] = $data['ref_id'];
            $ins_data['ref_type'] = $data['ref_type'];
            $ins_data['data'] = json_encode($data);
            $ins_data['to'] = $data['to'];
            $ins_data['cc'] = isset($data['cc']) ? $data['cc'] : NULL;
            $ins_data['email_subject'] = isset($data['subject']) ? $data['subject'] : NULL;
            $ins_data['body'] = $data['body'];
            $ins_data['attachment'] = !empty($data['attachments']) ? json_encode($data['attachments']) : NULL;
            $ins_data['cr_usr'] = $data['user_id'];
            $ins_data['created_at'] = date('Y-m-d H:i:s');
            return $ins_data;
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    function compData($comp_id)
    {
        $sql = "SELECT * FROM `sanordo_db`.`admin_client_master` WHERE id = $comp_id";
        $resp = $this->fetchSingleData($sql);
        $img = $_ENV['SERVER_PATH'] . '/' . $resp['data']['logo_img'];
        return $img;
        if (file_exists($check_dir)) {
            $images = scandir($check_dir);
            for ($j = 0; $j < count($images); $j++) {
                if ($images[$j] == '.' || $images[$j] == '..') {
                    continue;
                } else {
                    $comp_logo = $check_dir . '/' . $images[$j];
                    return $comp_logo;
                }
            }
        } else {
            return $comp_logo = $_ENV['app.IMAGE_PATH'] . '/assets/img/MeraEstate-Logo.jpg';
        }
    }

    private function insertLeadItemAndTax($data)
    {
        try {
            $item_arr = [];
            if (!empty($data['item_list'])) {
                foreach ($data['item_list'] as $key => $item) {
                    $one_item = array(
                        'lead_id' => $data['insert_id'],
                        'category_id' => !empty($item['category_id']) ? $item['category_id'] : NULL,
                        'item_id' => !empty($item['item_id']) ? $item['item_id'] : NULL,
                        'item_name' => !empty($item['item_name']) ? $item['item_name'] : NULL,
                        'item_package_id' => !empty($item['item_package_id']) ? $item['item_package_id'] : NULL,
                        'hsn_code' => !empty($item['hsn_code']) ? $item['hsn_code'] : NULL,
                        'rate' => !empty($item['rate']) ? $item['rate'] : 0.00,
                        'including_tax' => !empty($item['including_tax']) ? $item['including_tax'] : 0,
                        'mrp' => !empty($item['mrp']) ? $item['mrp'] : 0.00,
                        'qty' => !empty($item['qty']) ? $item['qty'] : 0.00,
                        'discount' => !empty($item['discount']) ? $item['discount'] : NULL,
                        'discount_amount' => !empty($item['discount_amount']) ? $item['discount_amount'] : NULL,
                        'discount_type' => !empty($item['discount_type']) ? $item['discount_type'] : NULL,
                        'amount' => !empty($item['amount']) ? $item['amount'] : 0.00,
                        'tax_percentage' => !empty($item['tax_percentage']) ? $item['tax_percentage'] : 0.00,
                        'tax_amount' => !empty($item['tax_amount']) ? $item['tax_amount'] : 0.00,
                        'total_amount' => !empty($item['total_amount']) ? $item['total_amount'] : NULL
                    );
                    $one_item['item_detail'] = json_encode([
                        "item_code" => $item['item_code'],
                        "category_id" => $item['category_id'],
                        "group_id" => $item['group_id'],
                        "unit" => $item['unit'],
                        "rate" => $one_item['rate'],
                        "qty" => $one_item['qty'],
                        "discount" => $one_item['discount'],
                        "discount_type" => $one_item['discount_type'],
                        "total_rate" => $item['total_rate'],
                        "including_tax" => $one_item['including_tax'],
                        "image" => $item['image'],
                        "variant_id" => $item['variant_id']
                    ]);
                    $item_arr[] = $one_item;
                }

                $dbname = $data['dbname'];
                if ($data['action'] == 'update') {
                    $this->model->delete("`$dbname`.`lead_item_list`", ['lead_id' => $data['insert_id']]);
                }
                $insResp = $this->model->batchInsert("`$dbname`.`lead_item_list`", $item_arr);
                if (!$insResp['status']) {
                    throw new \Exception($insResp['error']);
                }
            }

            $tax_arr = [];
            if (!empty($data['item_tax_list'])) {
                foreach ($data['item_tax_list'] as $key => $item_taxes) {
                    foreach ($item_taxes as $item_id => $item) {
                        $tax_arr[] = array(
                            'lead_id' => $data['insert_id'],
                            'item_id' => !empty($item['item_id']) ? $item['item_id'] : NULL,
                            'item_name' => !empty($item['item_name']) ? $item['item_name'] : NULL,
                            'tax_name' => !empty($item['tax_name']) ? $item['tax_name'] : NULL,
                            'tax_id' => !empty($item['tax_id']) ? $item['tax_id'] : NULL,
                            'tax_percentage' => !empty($item['tax_percentage']) ? $item['tax_percentage'] : 0.00,
                            'taxable_amount' => !empty($item['taxable_amount']) ? $item['taxable_amount'] : NULL,
                            'tax_amount' => !empty($item['tax_amount']) ? $item['tax_amount'] : 0.00
                        );
                    }
                }
                $dbname = $data['dbname'];
                if ($data['action'] == 'update') {
                    $this->model->delete("`$dbname`.`lead_tax_list`", ['lead_id' => $data['insert_id']]);
                }
                $instax = $this->model->batchInsert("`$dbname`.`lead_tax_list`", $tax_arr);
                if (!$instax['status']) {
                    throw new \Exception($instax['error']);
                }
            }
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }
    //   UPDATE / ADD PERMISSIONS ---  COMMON FOR USER AND GROUP
    public function extractMenusRights($menus, $Id, $type)
    {
        try {
            $extractedData = [];
            foreach ($menus as $menu) {
                $menuData = [
                    'page_id' => $menu['menu_id'],
                    'view_right' => $menu['view_right'],
                    'add_right' => $menu['add_right'],
                    'edit_right' => $menu['edit_right'],
                    'delete_right' => $menu['delete_right'],
                    'excel_right' => $menu['excel_right'],
                ];
                if ($type == 'USER') {
                    $menuData['user_id'] = $Id;
                }
                if ($type == 'GROUP') {
                    $menuData['profile_id'] = $Id;
                }
                $extractedData[] = $menuData;

                if (isset($menu['child_menus']) && is_array($menu['child_menus'])) {
                    $childMenus = $menu['child_menus'];
                    $childData = $this->extractMenusRights($childMenus, $Id, $type);
                    $extractedData = array_merge($extractedData, $childData);
                }
            }
            return $extractedData;
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    public function updateUserProfileRights($dbname, $cond, $extractedData)
    {
        try {
            $this->model->delete($dbname, $cond);
            $insert = $this->model->batchInsert($dbname, $extractedData);
            if (!$insert['status'])
                throw new \Exception($insert['error']);
            return ['status' => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    //   INSERT USER BRANCH RIGHTS --  ADD MORE
    public function insertUserBranchRights($data)
    {
        try {
            for ($i = 0; $i < count($data['branchForm']); $i++) {
                if (empty($data['branchForm'][$i]['branch_id'])) {
                    throw new \Exception('Branch is required');
                } else {
                    $userBranchMap[] = array(
                        'user_id' => $data['insert_id'],
                        'branch_id' => $data['branchForm'][$i]['branch_id'],
                        'make_default' => $data['branchForm'][$i]['make_default'] ? $data['branchForm'][$i]['make_default'] : 0,
                        'cr_usr' => $data['user_id']
                    );
                }
            }
            $dbname = $data['clientDB'];
            if ($data['action'] == 'update') {
                $resp =  $this->model->delete("`$dbname`.`branch_user_rights`", ['user_id' => $data['insert_id']]);
                if (!$resp['status'])
                    throw new \Exception($resp['error']);
            }
            $insResp = $this->model->batchInsert("`$dbname`.`branch_user_rights`", $userBranchMap);
            if (!$insResp['status'])
                throw new \Exception($insResp['error']);
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    // INSERT USER BRANCHS
    public function userBranchNDProfileRights($data)
    {
        try {
            $db = $data['dbname'];
            if (count($data['branchForm']) > 0) {
                $resp = $this->insertUserBranchRights($data);
                if (!$resp['status']) {
                    throw new \Exception($resp['error']);
                }
            }
            if ($data['master_type'] != 1) {
                $profile = $data['profile'];
                $sql = "SELECT *,page_id as menu_id FROM `$db`.`users_profile_rights` WHERE profile_id = $profile";
                $result = $this->model->fetchAllData($sql);
                $dbname = `$db` . `users_master_rights`;
                $cond = ['user_id' => $data['insert_id']];
                if ($result['data']) {
                    $data['rights'] = $result['data'];
                    $menus = $this->extractMenusRights($result['data'], $data['insert_id'], 'USER');
                    $resp = $this->updateUserProfileRights($dbname, $cond, $menus);
                    if (!$resp['status']) {
                        throw new \Exception($resp['error']);
                    }
                }
            }
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    // INSERT STOCKOUT INENTORY ITEM
    public function insertStockOutInvItem($data)
    {
        try {
            foreach ($data['stockOutForm'] as $val) {
                $stockOutitemDataMap[] = array(
                    'inv_id' => $data['insert_id'],
                    'item_id' => $val['item_id'],
                    'qty' => $val['qty'],
                    'rto_qty' => $val['rto_qty'],
                    'cr_usr' => $data['user_id']
                );
            }
            $dbname = $data['dbname'];
            if ($data['action'] == 'update') {
                $this->model->delete("`$dbname`.`stockout_inventory_item`", ['inv_id' => $data['insert_id']]);
            }
            $insResp = $this->model->batchInsert("`$dbname`.`stockout_inventory_item`", $stockOutitemDataMap);
            if (!$insResp['status']) {
                throw new \Exception($insResp['error']);
            }
            $this->model->stockOut($data['insert_id'], $dbname, 0, 'IV');
            $this->model->stockIn($data['insert_id'], $dbname, 0, 'IV');

            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    // INSERT PACKAGE ITEMS  --  ADD MORE
    public function insertPackageItem($data)
    {
        try {
            if (count($data['itemForm']) == 0) {
                throw new \Exception('Please, add some items');
            }
            for ($i = 0; $i < count($data['itemForm']); $i++) {
                $itemDataMap[] = array(
                    'package_id' => $data['insert_id'],
                    'item_id' => $data['itemForm'][$i]['item_id'],
                    'rate' => $data['itemForm'][$i]['rate'],
                    'quantity' => $data['itemForm'][$i]['quantity'],
                    'cr_usr' => $data['user_id']
                );
            }
            $dbname = $data['dbname'];
            if ($data['action'] == 'update') {
                $this->model->delete("`$dbname`.`item_package_item_mapping`", ['package_id' => $data['insert_id']]);
            }
            $insResp = $this->model->batchInsert("`$dbname`.`item_package_item_mapping`", $itemDataMap);
            if (!$insResp['status'])
                throw new \Exception($insResp['error']);

            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    //  INSERT ITEM RATE 
    public function insertItemRate($data)
    {
        try {
            if (count($data['rateForm']) > 0) {
                for ($i = 0; $i < count($data['rateForm']); $i++) {
                    if (empty($data['rateForm'][$i]['item_rate'])) {
                        throw new \Exception('Rate is required');
                    } else {
                        $rateDataMap[] = array(
                            'item_id' => $data['insert_id'],
                            'customer_type' => $data['rateForm'][$i]['customer_type'],
                            'item_rate' => $data['rateForm'][$i]['item_rate'],
                            'item_total_rate' => $data['rateForm'][$i]['item_total_rate'] ? $data['rateForm'][$i]['item_total_rate'] : 0,
                            'cr_usr' => $data['user_id']
                        );
                    }
                }
                $dbname = $data['dbname'];
                if ($data['action'] == 'update') {
                    $this->model->delete("`$dbname`.`item_rate_master`", ['item_id' => $data['insert_id']]);
                }
                $insResp = $this->model->batchInsert("`$dbname`.`item_rate_master`", $rateDataMap);
                if (!$insResp['status'])
                    throw new \Exception($insResp['error']);
            }
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    //   INSERT ITEM CATEGORY TAX  --  ADD MORE
    public function insertCategoryTax($data)
    {
        try {
            if (count($data['taxForm']) == 0) {
                throw new \Exception('Please, add some tax');
            }
            for ($i = 0; $i < count($data['taxForm']); $i++) {
                if (empty($data['taxForm'][$i]['tax_id']) || empty($data['taxForm'][$i]['tax_percentage'])) {
                    throw new \Exception('Tax and value is required');
                } else {
                    $taxDataMap[] = array(
                        'cat_id' => $data['insert_id'],
                        'tax_id' => $data['taxForm'][$i]['tax_id'],
                        'tax_percentage' => $data['taxForm'][$i]['tax_percentage'],
                        'cr_usr' => $data['user_id']
                    );
                }
            }
            $dbname = $data['dbname'];
            if ($data['action'] == 'update') {
                $this->model->delete("`$dbname`.`itemcategorytax_master`", ['cat_id' => $data['insert_id']]);
            }
            $insResp = $this->model->batchInsert("`$dbname`.`itemcategorytax_master`", $taxDataMap);
            if (!$insResp['status'])
                throw new \Exception($insResp['error']);
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    //   INSERT CUSTOMER ADDRESS ---  ADD MORE
    public function insertCustomerAddress($data)
    {
        try {
            if (count($data['addressForm']) > 0) {
                for ($i = 0; $i < count($data['addressForm']); $i++) {
                    if (empty($data['addressForm'][$i]['address_pincode']) || empty($data['addressForm'][$i]['address_state_id']) || empty($data['addressForm'][$i]['address_city_id'])) {
                        throw new \Exception('Pincode, State or City required');
                    } else {
                        $customerAddMap[] = array(
                            'customer_id' => $data['insert_id'],
                            'address_title' => $data['addressForm'][$i]['address_title'],
                            'address_pincode' => $data['addressForm'][$i]['address_pincode'],
                            'address_state_id' => $data['addressForm'][$i]['address_state_id'],
                            'address_city_id' => $data['addressForm'][$i]['address_city_id'],
                            'address_mobile' => $data['addressForm'][$i]['address_mobile'],
                            'address' => $data['addressForm'][$i]['address'],
                            'gst' => $data['addressForm'][$i]['gst'],
                        );
                    }
                }
                $dbname = $data['dbname'];
                if ($data['action'] == 'update') {
                    $this->model->delete("`$dbname`.`customer_address_master`", ['customer_id' => $data['insert_id']]);
                }
                $resp = $this->model->batchInsert("`$dbname`.`customer_address_master`", $customerAddMap);
                if (!$resp['status'])
                    throw new \Exception($resp['error']);
            } else {
                throw new \Exception('Please add atleast one address');
            }
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    //   INSERT BULK COUPONS RECORD INSERT TYM 
    private function addCouponsData($dbData)
    {
        try {
            if ($dbData['coupon_status_type'] == 1) {
                //Individual Order
                $dataCouponMap[] = array('coupon_name' => $dbData['coupon_title'], 'coupon_master_id' => $dbData['insert_id']);
            } else {
                // Bulk Order
                $couponArray = $this->generateUniqueCoupons($dbData['dbname'], $dbData['coupon_count'], 10, $dbData['coupon_title'], array());
                foreach ($couponArray as $key => $value) {
                    $dataCouponMap[] = array('coupon_name' => $value, 'coupon_master_id' => $dbData['insert_id']);
                }
            }
            if (count($dataCouponMap) > 0)
                $dbname = $dbData['dbname'];
            $resp = $this->model->batchInsert("`$dbname`.`coupon_list`", $dataCouponMap);
            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    //   INSERT BULK COUPONS RECORD UPDATE TYM
    private function updateTymAddCoupons($dbData)
    {
        try {
            $id = $dbData['insert_id'];
            $dbname = $dbData['dbname'];
            $couponDbMasterArray = $dbData['CouponsData'];
            if ($couponDbMasterArray['coupon_status_type'] == 1 && $dbData['coupon_status_type'] == 1) { // Few changes on individual coupon type      CHECK
                $dataCouponMap = array('coupon_name' => $dbData['coupon_title']);
                $resp = $this->model->update("`$dbname`.`coupon_list`", $dataCouponMap, array('coupon_master_id' => $id));
            } else if ($couponDbMasterArray['coupon_status_type'] == 2 && $dbData['coupon_status_type'] == 1) { //Transfer from bulk coupon to single coupon     CHECK
                $resp = $this->model->deleteCouponList($dbname, "coupon_master_id = $id", array());
                $dataCouponMap[] = array('coupon_name' => $dbData['coupon_title'], 'coupon_master_id' => $id);
                $resp = $this->model->batchInsert("`$dbname`.`coupon_list`", $dataCouponMap);
            } else if ($couponDbMasterArray['coupon_status_type'] == 1 && $dbData['coupon_status_type'] == 2) { //Transfer from Single to Bulk Order       CHECK
                $resp = $this->model->deleteCouponList($dbname, "coupon_master_id = $id", array());
                $couponArray = $this->generateUniqueCoupons($dbname, $dbData['coupon_count'], 10, $dbData['coupon_title'], array());
                foreach ($couponArray as $key => $value) {
                    $dataCouponMap[] = array('coupon_name' => $value, 'coupon_master_id' => $id);
                }
                if (count($dataCouponMap) > 0)
                    $resp = $this->model->batchInsert("`$dbname`.`coupon_list`", $dataCouponMap);
            } else if ($couponDbMasterArray['coupon_status_type'] == 2 && $dbData['coupon_status_type'] == 2) { // Bulk Coupons
                if ($couponDbMasterArray['coupon_title'] != $dbData['coupon_title']) {
                    // Want  change coupon series     CHECK
                    if ($dbData['coupon_count'] > $couponDbMasterArray['coupon_count'] || $dbData['coupon_count'] < $couponDbMasterArray['coupon_count']) {
                        $resp = $this->model->deleteCouponList($dbname, "coupon_master_id = $id", array());
                        $couponArray = $this->generateUniqueCoupons($dbname, $dbData['coupon_count'], 10, $dbData['coupon_title'], array());
                        foreach ($couponArray as $key => $value) {
                            $dataCouponMap[] = array('coupon_name' => $value, 'coupon_master_id' => $id);
                        }
                        if (count($dataCouponMap) > 0)
                            $resp = $this->model->batchInsert("`$dbname`.`coupon_list`", $dataCouponMap);
                    }
                } else if ($couponDbMasterArray['coupon_title'] == $dbData['coupon_title']) {
                    $resp = ['status' => true];
                    // If title is same
                    if ($dbData['coupon_count'] > $couponDbMasterArray['coupon_count']) {
                        // Want to add more coupons in the list   CHECK
                        $insertCoupnCount = $dbData['coupon_count'] - $couponDbMasterArray['coupon_count'];
                        $couponArray = $this->generateUniqueCoupons($dbname, $insertCoupnCount, 10, $dbData['coupon_title'], array());
                        foreach ($couponArray as $key => $value) {
                            $dataCouponMap[] = array('coupon_name' => $value, 'coupon_master_id' => $id);
                        }
                        if (count($dataCouponMap) > 0)
                            $resp =  $this->model->batchInsert("`$dbname`.`coupon_list`", $dataCouponMap);
                    } else if ($dbData['coupon_count'] < $couponDbMasterArray['coupon_count']) {
                        //Want to Delete coupons from the list   CHECK
                        $deleteCoupnCount = $couponDbMasterArray['coupon_count'] - $dbData['coupon_count'];
                        $resp = $this->model->deleteCouponList($dbname, "coupon_master_id = $id AND is_used = 0", array(), $deleteCoupnCount);
                    }
                    $this->model->getTotalCouponCount($dbname, "coupon_master_id = $id", array('status' => true, 'coupon_master_id' => $id));
                }
            }

            return $resp;
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    //   BULK COUPON GENERATE  ---  COUPON MASTER 
    public function generateUniqueCoupons($dbname, $count = 1, $lenght = 10, $prefix = '', $preCouponArray = array(), $preIndex = array(), $newDbArray = array())
    {
        if (strlen($prefix) >= 5)
            $lenght = 5;
        else
            $lenght = $lenght - strlen($prefix);

        if ($count == 0) {
            $couponArray = $preCouponArray;
            return $couponArray;
        }

        $couponArray = $couponIndexArray = $lastCouponArray = array();

        if (count($preCouponArray) > 0) { // For recursive function
            $couponArray = $preCouponArray;
            for ($i = 0; $i < $count; $i++) {
                $coupon = strtoupper($prefix) . substr(strtoupper($this->library->random_string('alnum', $lenght)), 0, $lenght);
                if (in_array($coupon, $couponArray)) {
                    $i--;
                    continue;
                }
                $indexNewVal = $preIndex[$newDbArray[$i]];

                $couponArray[$indexNewVal] = $coupon;
                $couponIndexArray[$coupon] = $indexNewVal;
                $lastCouponArray[] = $coupon;
            }
        } else { // for fresh call
            for ($i = 0; $i < $count; $i++) {
                $coupon = strtoupper($prefix) . substr(strtoupper($this->library->random_string('alnum', $lenght)), 0, $lenght);
                if (in_array($coupon, $couponArray)) {
                    $i--;
                    continue;
                }
                $couponArray[] = $coupon;
                $couponIndexArray[$coupon] = $i;
            }
        }
        $dbCouponMatchArray = array();
        if (count($lastCouponArray) > 0) {
            $dbCouponMatchArray = $this->model->validateCouponCodes($dbname, '', $lastCouponArray);
        } else if (count($couponArray) > 0) {
            $dbCouponMatchArray = $this->model->validateCouponCodes($dbname, '', $couponArray);
        }
        if (count($dbCouponMatchArray) > 0) {
            foreach ($dbCouponMatchArray as $key => $value) {
                $dbPassArray[] = $value['coupon_name'];
            }
            $couponArray = $this->generateUniqueCoupons($dbname, count($dbPassArray), $lenght, $prefix, $couponArray, $couponIndexArray, $dbPassArray);
        }
        return $couponArray;
    }
    //   POST INSERT / UPDATE PROCESS   (END)

    //   PRE DELETE PROCESS   (START)
    public function preDeleteProcess($master, $input)
    {
        try {
            switch ($master) {
                case 'coupon_master':
                    return $this->deleteCoupons($input);
                case 'customer_master':
                    //   DELETE CUSTOMER ADDRESS
                    return $this->deleteAddMore($input, 'customer_address_master', 'customer_id');
                case 'itemcategory_master':
                    //   DELETE ITEM CATEGORY TAX
                    return $this->deleteAddMore($input, 'itemcategorytax_master', 'cat_id');
                case 'item_master':
                    //   DELETE ITEM RATE
                    $resp = $this->deleteAddMore($input, 'item_rate_master', 'item_id');
                    if (!$resp['status']) {
                        throw new \Exception($resp['error']);
                    }
                    return $this->model->getMasterDataByID($input['dbname'], $master, $input['delete_id'], 'item_id');
                case 'item_package_master':
                    //   DELETE PACKAGE ITEM
                    return $this->deleteAddMore($input, 'item_package_item_mapping', 'package_id');
                case 'stockout_inventory':
                    return $this->deleteStockOutInventory($input);
                case 'users_master':
                    //   DELETE USER BRANCH
                    return $this->deleteAddMore($input, 'branch_user_rights', 'user_id');
                    // case 'client_users_master':
                    //     //   DELETE LEAD ITEM , PACKAGE
                    //     $this->deleteAddMore($input, 'lead_item', 'lead_id');
                    //     return $this->deleteAddMore($input, 'lead_item_package', 'lead_id');
                case 'lead_source':
                    return $this->model->getMasterDataByID($input['dbname'], $master, $input['delete_id'], 'id');
                case 'purchasereturn_master':
                    $this->model->stockIn($input['delete_id'], $input['dbname'], 0, 'PR');
                    $this->deleteAddMore($input, 'purchasereturn_itemlist', 'prtn_id');
                    return $this->deleteAddMore($input, 'purchasereturn_taxlist', 'prtn_id');
                case 'purchase_master':
                    $this->model->stockIn($input['delete_id'], $input['dbname'], 1, 'PU');
                    $this->deleteAddMore($input, 'purchase_itemlist', 'purchase_id');
                    return $this->deleteAddMore($input, 'purchase_taxlist', 'purchase_id');
                case 'leads':
                    $this->deleteAddMore($input, 'lead_flp_log', 'flp_lead_id');
                    $this->deleteAddMore($input, 'lead_tax_list', 'lead_id');
                    return $this->deleteAddMore($input, 'lead_item_list', 'lead_id');
                case 'order_attachments':
                    return $this->model->getMasterDataByID($input['dbname'], $master, $input['delete_id'], 'id');
                default:
                    return ["status" => true, "data" => $input];
                    break;
            }
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    //   DELETE COUPONS  --- COUPON MASTER 
    private function deleteCoupons($data)
    {
        try {
            $dbname = $data['dbname'];
            $delete_id = $data['delete_id'];
            if ($this->model->getTotalCouponCount($dbname, "coupon_master_id = $delete_id AND is_used = 1", array('status' => false)) > 0) {
                throw new \Exception('You cannot delete the used coupons');
            }
            $resp = $this->model->delete("`$dbname`.`coupon_list`", ['coupon_master_id' => $delete_id]);
            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            return ["status" => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    //   DELETE ADD MORE FIELDS  -----  COMMON
    private function deleteAddMore($data, $table, $primaryKey)
    {
        try {
            $dbname = $data['dbname'];
            $delete_id = $data['delete_id'];
            $resp = $this->model->delete("$dbname.$table", ["$primaryKey" => $delete_id]);

            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            return ["status" => true, 'data' => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }
    //   DELETE STOCKOUT INVENTORY ITEMS
    private function deleteStockOutInventory($data)
    {
        try {
            $dbname = $data['dbname'];
            $delete_id = $data['delete_id'];
            $this->model->stockOut($delete_id, $dbname, 1, 'IV');
            $this->model->stockIn($delete_id, $dbname, 1, 'IV');
            $resp = $this->model->delete("$dbname.stockout_inventory_item", ['inv_id' => $delete_id]);

            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            return ["status" => true, 'data' => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }
    //   PRE DELETE PROCESS   (END)

    //   POST DELETE PROCESS   (START)
    public function postDeleteProcess($master, $input)
    {
        try {

            switch ($master) {
                case 'item_master':
                    return $this->deleteImg($input, $master, 'item_id');
                case 'lead_source':
                    return $this->deleteImg($input, $master, 'id');
                case 'order_attachments':
                    $input['img_path'] = $input['path'];
                    return $this->deleteImg($input, $master, 'id');
                default:
                    return ["status" => true, "data" => $input];
            }
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    public function deleteImg($data)
    {
        try {
            if ($data['img_path']) {
                $previousFilePath = $_ENV['SERVER_PATH'] . '/' . $data['img_path'];
                if (file_exists($previousFilePath)) {
                    if (!unlink($previousFilePath)) {
                        return array('status' => false, 'error' => 'Failed to delete previous file.');
                    }
                }
            }
            return ['status' => true];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    //   POST DELETE PROCESS   (END)

    //   POST DATABYID PROCESS   (START)

    public function postDataByIdProcess($master, $dbname, $data, $edit_id)
    {
        try {
            switch ($master) {
                case 'customer_master':
                    return $this->getCustomerAddress($data, $dbname, $edit_id);
                case 'itemcategory_master':
                    return $this->getItemCategoryTax($data, $dbname, $edit_id);
                case 'item_master':
                    return $this->getItemRate($data, $dbname, $edit_id);
                case 'item_package_master':
                    return $this->getPackageItem($data, $dbname, $edit_id);
                case 'stockout_inventory':
                    return $this->getStockOutInventory($data, $dbname, $edit_id);
                case 'users_group_master':
                    return $this->getClientGroup($data);
                case 'leads':
                    return $this->getLeadItemAndTax($data, $dbname, $edit_id);
                case 'order_logic':
                    return $this->getActionOrderStatus($data, $dbname, $edit_id);
                case 'purchase_master':
                    return $this->getPurchaseItmTax($data, $dbname, $edit_id);
                case 'purchasereturn_master':
                    return $this->getPurchaseReturnItmTax($data, $dbname, $edit_id);
                case 'courier':
                    return $this->getCourierWebhookURL($data, $dbname, $edit_id);
                case 'branch_master':
                    return $this->getParseBranchData($data, $dbname, $edit_id);
                case 'order_message_template':
                    return $this->getParseTemplateData($data, $dbname, $edit_id);
                default:
                    return ["status" => true, "data" => $data];
                    break;
            }
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }
    
    private function getParseTemplateData($data, $dbname, $edit_id) {
        try {
            if(strtolower($data['temp_type']) == 'whatsapp') {
                if(!empty($data['is_whatsapp_business_template']) && !empty($data['template_body'])) {
                    $data['template_body'] = stripslashes($data['template_body']);
                }
            }
            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getParseBranchData($data, $dbname, $edit_id) {
        try {
            $data['sms_api_headers'] = !empty($data['sms_api_headers']) ? stripslashes($data['sms_api_headers']) : "";
            $data['sms_api_data'] = !empty($data['sms_api_data']) ? stripslashes($data['sms_api_data']) : "";
            $data['sms_api_data'] = trim($data['sms_api_data']);
            $data['sms_url'] = !empty($data['sms_url']) ? stripslashes($data['sms_url']) : "";

            $data['whatsapp_api_headers'] = !empty($data['whatsapp_api_headers']) ? stripslashes($data['whatsapp_api_headers']) : "";
            $data['whatsapp_api_data'] = !empty($data['whatsapp_api_data']) ? stripslashes($data['whatsapp_api_data']) : "";
            $data['whatsapp_api_data'] = trim($data['whatsapp_api_data']);
            $data['whatsapp_url'] = !empty($data['whatsapp_url']) ? stripslashes($data['whatsapp_url']) : "";

            $data['dial_api_url'] = !empty($data['dial_api_url']) ? stripslashes($data['dial_api_url']) : "";
            $data['click_2_call_header_json'] = !empty($data['click_2_call_header_json']) ? stripslashes($data['click_2_call_header_json']) : "";
            $data['dial_api_json'] = !empty($data['dial_api_json']) ? stripslashes($data['dial_api_json']) : "";

            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getCourierWebhookURL($data, $dbname, $edit_id)
    {
        try {
            $urlarr = Main::WebhookURLs();
            $url = '';
            if (!empty($urlarr[$data['courier_api']])) {
                $url = $urlarr[$data['courier_api']];
                if (!empty($data['access_token'])) {
                    $url = $url . '?token=' . $data['access_token'];
                }
                $data['webhook_url'] = $url;
            }
            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getPurchaseReturnItmTax($data, $dbname, $edit_id)
    {
        try {
            $itemsQuery = "SELECT * FROM `$dbname`.`purchasereturn_itemlist` WHERE prtn_id = $edit_id";
            $itemresp = $this->model->fetchAllData($itemsQuery);
            if (!$itemresp['status']) {
                throw new \Exception($itemresp['error']);
            }
            $data['itemData'] = $itemresp['data'];

            $taxQuery = "SELECT * FROM `$dbname`.`purchasereturn_taxlist` WHERE prtn_id = $edit_id";
            $taxresp = $this->model->fetchAllData($taxQuery);
            if (!$taxresp['status']) {
                throw new \Exception($taxresp['error']);
            }
            $data['taxData'] = $taxresp['data'];

            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getPurchaseItmTax($data, $dbname, $edit_id)
    {
        try {
            $itemsQuery = "SELECT t1.*, t2.item_name FROM `$dbname`.`purchase_itemlist` t1 LEFT JOIN `$dbname`.`item_master` t2 ON(t2.item_id=t1.item_id) WHERE purchase_id = $edit_id ";
            $itemresp = $this->model->fetchAllData($itemsQuery);
            if (!$itemresp['status']) {
                throw new \Exception($itemresp['error']);
            }
            $data['itemData'] = $itemresp['data'];

            $taxQuery = "SELECT * FROM `$dbname`.`purchase_taxlist` WHERE purchase_id = $edit_id";
            $taxresp = $this->model->fetchAllData($taxQuery);
            if (!$taxresp['status']) {
                throw new \Exception($taxresp['error']);
            }
            $data['taxData'] = $taxresp['data'];

            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getActionOrderStatus($data, $dbname, $edit_id)
    {
        try {
            $itemsQuery = "SELECT logic_id,order_status_id,status_action_id FROM `$dbname`.`order_logic` WHERE order_status_id = $edit_id";
            $actionStatus = $this->model->fetchAllData($itemsQuery);
            if (!$actionStatus['status']) {
                throw new \Exception($actionStatus['error']);
            }
            $data['actionOrderStatus'] = $actionStatus['data'];

            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    private function getLeadItemAndTax($data, $dbname, $edit_id)
    {
        try {
            $itemsQuery = "SELECT * FROM $dbname.lead_item_list WHERE lead_id=:id";
            $itemsresp = $this->model->fetchAllData($itemsQuery, [":id" => $edit_id]);
            if (!$itemsresp['status']) {
                throw new \Exception($itemsresp['error']);
            }

            if ($itemsresp['data']) {
                foreach ($itemsresp['data'] as $key => $val) {
                    $detail = json_decode($val['item_detail']);
                    $itemsresp['data'][$key]['total_rate'] = $detail->total_rate;
                    $itemsresp['data'][$key]['item_code'] = $detail->item_code;
                    $itemsresp['data'][$key]['group_id'] = $detail->group_id;
                    $itemsresp['data'][$key]['unit'] = $detail->unit;
                    $itemsresp['data'][$key]['variant_id'] = $detail->variant_id;
                    $itemsresp['data'][$key]['id'] = $val['item_id'];
                    $itemsresp['data'][$key]['text'] = $val['item_name'];
                }
            }
            $data['items'] = $itemsresp['data'];

            $taxQuery = "SELECT * FROM `$dbname`.`lead_tax_list` WHERE lead_id = $edit_id";
            $taxresp = $this->model->fetchAllData($taxQuery);
            if (!$taxresp['status']) {
                throw new \Exception($taxresp['error']);
            }
            $data['item_tax'] = $taxresp['data'];

            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }
    // EDIT TIME CUSTOMER ADRESS 
    private function getCustomerAddress($data, $dbname, $edit_id)
    {
        try {
            $select = "SELECT t.*,s.state_name,c.city_name FROM `$dbname`.`customer_address_master` t
                LEFT JOIN `sanordo_db`.`admin_state_master` s ON t.address_state_id = s.state_id
                LEFT JOIN `$dbname`.`location_city` c ON t.address_city_id=c.id WHERE customer_id = $edit_id";
            $resp = $this->model->fetchAllData($select);
            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            $data['customerAddress'] = $resp['data'];
            // if ($this->user_data->hide_phone == 1) {  UNCOMMENT WHEN HIDE PHONE FIELD ADD ON DB
            //     $dataList['data']['mobile_number'] = substr_replace($dataList['data']['mobile_number'], 'XXXXXX', 2, 6);
            //     if ($dataList['data']['alt_mobile1'] != '')
            //         $dataList['data']['alt_mobile1'] = substr_replace($dataList['data']['alt_mobile1'], 'XXXXXX', 2, 6);
            //     if ($dataList['data']['alt_mobile2'] != '')
            //         $dataList['data']['alt_mobile2'] = substr_replace($dataList['data']['alt_mobile2'], 'XXXXXX', 2, 6);
            //     if ($dataList['data']['alt_mobile3'] != '')
            //         $dataList['data']['alt_mobile3'] = substr_replace($dataList['data']['alt_mobile3'], 'XXXXXX', 2, 6);
            //     if ($dataList['data']['email_id'] != '')
            //         $dataList['data']['email_id'] = $this->showEmail($dataList['data']['email_id']);
            // }


            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    // EDIT TIME ITEM CATEGORY TAX 
    private function getItemCategoryTax($data, $dbname, $edit_id)
    {
        try {
            $select = "SELECT itemTax.tax_id,itemTax.tax_percentage FROM `$dbname`.`itemcategorytax_master` itemTax
                LEFT JOIN `$dbname`.`itemcategory_master` itemCat ON itemTax.cat_id = itemCat.itemcat_id 
                WHERE itemcat_id = $edit_id";

            $resp = $this->model->fetchAllData($select);
            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            $data['taxData'] = $resp['data'];

            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    // EDIT TIME ITEM RATE 
    private function getItemRate($data, $dbname, $edit_id)
    {
        try {
            $select = "SELECT iR.customer_type,iR.item_rate,iR.item_total_rate FROM `$dbname`.`item_rate_master` iR
                LEFT JOIN `$dbname`.`item_master` item ON iR.item_id = item.item_id 
                WHERE iR.item_id = $edit_id";

            $resp = $this->model->fetchAllData($select);
            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            $data['rateData'] = $resp['data'];

            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    // EDIT TIME PACKAGE ITEM 
    private function getPackageItem($data, $dbname, $edit_id)
    {
        try {
            $select = "SELECT iP.item_id,iP.quantity,iP.rate,item.item_name FROM `$dbname`.`item_package_item_mapping` iP
                LEFT JOIN `$dbname`.`item_package_master` pack ON iP.package_id = pack.id 
                LEFT JOIN `$dbname`.`item_master` item ON iP.item_id = item.item_id 
                WHERE iP.package_id = $edit_id";

            $resp = $this->model->fetchAllData($select);
            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            $data['itemData'] = $resp['data'];

            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    // EDIT TIME STOCKOUT INVENTORY 
    private function getStockOutInventory($data, $dbname, $edit_id)
    {
        try {
            $select = "SELECT t1.item_id,t1.qty,t1.rto_qty,t2.item_name FROM `$dbname`.`stockout_inventory_item` t1 LEFT JOIN `$dbname`.`item_master` t2 ON(t2.item_id=t1.item_id) WHERE t1.inv_id = $edit_id";

            $resp = $this->model->fetchAllData($select);
            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            $data['stockOutData'] = $resp['data'];

            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    // EDIT GROUP
    private function getClientGroup($data)
    {
        try {
            if ($data) {
                $data['order_status_id'] = explode(',', $data['order_status_id']);
                if ($data['import_permission']) {
                    $data['import_permission'] = explode(',', $data['import_permission']);
                }
            }

            return ["status" => true, "data" => $data];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }
    //   POST DATABYID PROCESS   (END)

    //  INSERT ORDER LOGIC DATA
    public function insertOrderLogicData($data)
    {
        try {
            if ($data['order_status_id'] && $data['status_action_id']) {
                foreach ($data['status_action_id'] as $val) {
                    $DataMap[] = array(
                        'order_status_id' => $data['order_status_id'],
                        'status_action_id' => $val,
                        'cr_usr' => $data['user_id'],
                        'created_at' => date('Y-m-d H:i:s')
                    );
                }
                $dbname = $data['dbname'];
                $delResp = $this->model->delete("`$dbname`.`order_logic`", ['order_status_id' => $data['order_status_id']]);
                if (!$delResp['status']) {
                    throw new \Exception($delResp['error']);
                }
                $insResp = $this->model->batchInsert("`$dbname`.`order_logic`", $DataMap);
                if (!$insResp['status'])
                    throw new \Exception($insResp['error']);

                return ['status' => true, 'data' => $insResp['inserted_rows']];
            } else {
                throw new \Exception('Order status or action order status is require');
            }
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }

    // CHANGE PASSWORD
    public function changePassword($data)
    {
        try {
            $user_id = $data['user_id'];
            $dbPrefix = $data['dbname'];
            $resp = $this->fetchSingleData("SELECT * FROM sanordo_db.client_users_master WHERE comp_user_id = $user_id");
            if (!$resp['status']) {
                throw new \Exception($resp['error']);
            }
            $cur_pass = Crypto::decrytData($data['current_password']);
            if (!password_verify($cur_pass, $resp['data']['user_pass'])) {
                throw new \Exception('Current password is wrong');
            }
            $new_pass = Crypto::decrytData($data['new_password']);
            $con_pass = Crypto::decrytData($data['confirm_password']);
            if ($new_pass != $con_pass) {
                throw new \Exception('New password not match with confirm password');
            }
            $en_pass = password_hash($new_pass, PASSWORD_BCRYPT);
            $updMain = $this->update('sanordo_db.client_users_master', ['user_pass' => $en_pass], ['comp_user_id' => $user_id]);
            if (!$updMain['status']) {
                throw new \Exception($updMain['error']);
            }
            $updClient = $this->update("`$dbPrefix`.`users_master`", ['user_pass' => $en_pass], ['user_id' => $user_id]);
            if (!$updClient['status']) {
                throw new \Exception($updClient['error']);
            }
            return ['status' => true, 'data' => $updClient['affected_rows']];
        } catch (\Exception $e) {
            Logger::error($e->getMessage(), ['File' => $e->getFile(), 'Line' => $e->getLine()]);
            return ["status" => false, "error" => $e->getMessage()];
        }
    }
}
