<?php
defined('BASEPATH') OR exit('No direct script access allowed');
require APPPATH . '../vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xls;

class Customer extends CI_Controller
{
  public $columnNames = [
    "assignee"      => ["table" => "admin",      "alias" => "ai",  "column" => "name",         "key2" => "adminID","select" => ""],
    "stages"        => ["table" => "categories", "alias" => "css", "column" => "categoryName", "key2" => "category_id","select" => "css.cat_color as stage_color"],
    "gst_state"     => ["table" => "states",     "alias" => "st",  "column" => "state_name",   "key2" => "state_id","select" => ""],
    "lead_priority" => ["table" => "categories", "alias" => "cat", "column" => "categoryName", "key2" => "category_id","select" => ""],
    "lead_source"   => ["table" => "categories", "alias" => "cl",  "column" => "categoryName", "key2" => "category_id","select" => "cl.cat_color as source_color"],
    "enquiry_for"   => ["table" => "categories", "alias" => "cle", "column" => "categoryName", "key2" => "category_id","select" => "cle.cat_color as enquiry_color"],
  ];

  public $customCol = [
    "company_id"  => ["table" => "info_settings", "alias" => "i",  "column" => "companyName", "key2" => "infoID","select" => ""],
    "created_by"  => ["table" => "admin","alias" => "ad", "column" => "name","key2" => "adminID","select" => ""],
    "modified_by" => ["table" => "admin","alias" => "am", "column" => "name","key2" => "adminID","select" => ""],
  ];
  protected $Model;
  public $menuID;
  public function __construct()
  {
    parent::__construct();
    $this->load->helper(['url','security']);
    $this->load->model('core/CommonModelNew');
    $this->Model = $this->CommonModelNew;
    $this->load->library("ValidateData");
    $this->load->library('core/FilterEngine', [], 'filterengine');
    $this->load->library('core/FilterBuilder', [], 'filterbuilder');
    $this->load->library('core/History', [], 'history');
    $this->load->library('Filters',['customCol' => $this->customCol,'columnNames'=>$this->columnNames], 'filters');
    //$this->output->set_content_type('application/json', 'utf-8');
  }

  public function list($file='')
  {
    $this->response->decodeRequest();
    if($file != "download"){
        $this->access->checkTokenKey();
    }
    $payload = json_decode($this->input->raw_input_stream, true);
    if (!is_array($payload)) $payload = $this->input->post() ?: [];

    $menuId = (int)($payload['menuId'] ?? 0);
    if ($menuId <= 0) {
        $this->response->output(['flag'=>'F','msg'=>'menuId is required','statusCode'=>422], 200);
        return;
    }

    // Logged-in user
    $userId = $this->input->get_request_header('SadminID', true);
    if (!$userId) $userId = $payload['SadminID'] ?? $this->input->post('SadminID');

    // Menu meta + PK
    $menuMeta = $this->Model->getMenuMeta($menuId);
    if (!$menuMeta) {
        $this->response->output(['flag'=>'F','msg'=>'Invalid menu','statusCode'=>422], 200);
        return;
    }
    $pk = $menuMeta['pk'];

    // Columns from user settings (fallbacks preserved)
    $columns = $this->Model->getUserSelectedColumns($menuId, (string)$userId, $pk);

    if (empty($columns)) {
        if (isset($payload['columns']) && is_array($payload['columns']) && !empty($payload['columns'])) {
            $columns = $payload['columns'];
            if ($pk && !in_array($pk, $columns, true)) array_unshift($columns, $pk);
        } else {
            $columns = [$pk, 'name', 'email', 'status', 'created_date'];
        }
    }

    $filters  = isset($payload['filters']) && is_array($payload['filters']) ? $payload['filters'] : [];
    // Collect overrides from payload
    $overrides = [];

    overrideFromPayload($overrides, $payload, 'stages', [
    'empty_token' => 'nostatus',
    'cast_ints'   => true,
    ]);

    // type, status, company_id behave the same way (reusable!)
    overrideFromPayload($overrides, $payload, 'type');
    overrideFromPayload($overrides, $payload, 'status');
    overrideFromPayload($overrides, $payload, 'company_id', ['cast_ints' => true]);
    
    // Apply forced filters
    $filters = $this->filterbuilder->applyOverrideFilters($filters, $overrides);
    $freeTxt  = isset($payload['freeTextSearch']) ? trim((string)$payload['freeTextSearch']) : '';
    if (isset($payload['order'], $payload['orderBy'])) {
        // ensure sort is an array
        if(!isset($payload['sort']) || !is_array($payload['sort'])) {
            $payload['sort'] = [];
        }
        $payload['sort']['by']  = (string) $payload['orderBy'];
        $dir = strtoupper((string) $payload['order']);
        $payload['sort']['dir'] = ($dir === 'ASC') ? 'ASC' : 'DESC';
    }
    // Use it (with your default)
    $sort = $payload['sort'] ?? ['by' => 'created_date', 'dir' => 'DESC'];

    //$sort     = isset($payload['sort']) && is_array($payload['sort']) ? $payload['sort'] : ['by'=>'created_date','dir'=>'DESC'];

    $curPageIdx = isset($payload['curpage'])
        ? max(0, (int)$payload['curpage'])                                  // 0,1,2...
        : (isset($payload['page']) ? max(0, (int)$payload['page'] - 1) : 0); // compat for old 1-based 'page'

     $conf = $this->config->item("pagination");
    $pagLimit = $conf['per_page'];
    $limit  = min(200, max(1, (int)($payload['limit'] ?? $pagLimit ?? 20)));
    $offset = $curPageIdx * $limit;
   
    $plan  = $this->filterengine->buildPlan($menuId, $columns, $filters, $freeTxt, $sort, $this->columnNames, $this->customCol);
    $total = $this->Model->countByPlan($plan, $plan['pk']);
    $debugSql = $this->Model->compilePlanSQL($plan);
    if($file == "download"){
        $rows  = $this->Model->listByPlan($plan, null,null);
        $this->download($columns,$rows,$payload);exit;
    }else{
        $rows  = $this->Model->listByPlan($plan, $limit, $offset);
    }

        

        //print $debugSql;exit;

    $totalPages = ($limit > 0) ? (int)ceil($total / $limit) : 1;
    $hasMore    = ($curPageIdx + 1) < $totalPages;

    $start = ($total === 0) ? 0 : $offset;                      // zero-based start index
    $end   = ($total === 0) ? 0 : min($offset + $limit, $total); // zero-based exclusive end

    $status = [];
    $status['data'] = $rows;
    $status['paginginfo'] = [
        "curPage"      => $curPageIdx,                              // 0-based current page
        "prevPage"     => ($curPageIdx > 0) ? ($curPageIdx - 1) : 0,
        "pageLimit"    => $limit,
        "nextpage"     => $hasMore ? ($curPageIdx + 1) : 0,         // 0 when no next page
        "totalRecords" => $total,
        "start"        => $start,                                   // 0-based
        "end"          => $end                                      // 0-based exclusive
    ];

    // Keep your flags/messages; if you prefer 200 even on last page, set statusCode=200 here.
    if ($total <= $end) {
        $status['msg'] = 'No more records';
        $status['statusCode'] = 400;   // <-- if frontend expects this in JSON; else set 200
        $status['flag'] = 'S';
        $status['loadstate'] = false;
    } else {
        $status['msg'] = 'OK';
        $status['statusCode'] = 200;
        $status['flag'] = 'S';
        $status['loadstate'] = true;
    }

    $this->response->output($status, 200);
  }

    public function customerMaster($customer_id = "")
    {
        $this->access->checkTokenKey();
        $this->response->decodeRequest();
        $method = $this->input->method(TRUE);
        $this->menuID = $this->input->post('menuId');
        if($this->menuID == ""){
            $this->menuID = $this->input->get('menuId');
        }
        $adminID = $this->input->post('SadminID');
        $company_id = $this->input->post('company_id');
        if ($method == "POST" || $method == "PUT") {
            $customerDetails = array();
            $updateDate = date("Y/m/d H:i:s");
            $countryCodeNumber = $this->input->post('countryCode');
            $customerDetails['customer_id'] = $this->validatedata->validate('customer_id', 'Customer ID', false, '', array());
            $customerDetails['salutation'] = $this->validatedata->validate('salutation', 'Salutation', false, '', array());
            $customerDetails['name'] = $this->validatedata->validate('name', 'Name', true, '', array());
            $customerDetails['birth_date'] = $this->validatedata->validate('birth_date', 'Birth Date', false, '', array());
            $customerDetails['record_type'] = $this->validatedata->validate('record_type', 'record Type', true, '', array());
            $customerDetails['status'] = $this->validatedata->validate('status', 'status', false, '', array());
            $customerDetails['address'] = $this->validatedata->validate('address','addresss',false,'',array());
            $customerDetails['customer_image'] = $this->validatedata->validate('customer_image','Customer Image',false,'',array());
            $customerDetails['billing_name'] = $this->validatedata->validate('billing_name', 'Billing Address', false, '', array());
            $customerDetails['billing_address'] = $this->validatedata->validate('billing_address', 'Company Name', false, '', array());
            $customerDetails['branch_id	'] = $this->validatedata->validate('branch_id	', 'Branch Id	', false, '', array());
            $customerDetails['gst_no'] = $this->validatedata->validate('gst_no', ' Gst No', false, '', array());
            $customerDetails['adhar_number'] = $this->validatedata->validate('adhar_number', ' adhar Number', false, '', array());
            $customerDetails['pan_number'] = $this->validatedata->validate('pan_number', ' Pan Number', false, '', array());
            $customerDetails['website'] = $this->validatedata->validate('website', 'Website', false, '', array());
            $customerDetails['type'] = $this->validatedata->validate('type', 'Type', false, '', array());
            $customerDetails['stages'] = $this->validatedata->validate('stages', 'lead stages', false, '', array());
            $customerDetails['country'] = $this->validatedata->validate('country', 'Country', false, '', array());
            $customerDetails['state'] = $this->validatedata->validate('state', 'State', false, '', array());
            $customerDetails['city'] = $this->validatedata->validate('city', 'City', false, '', array());
            $customerDetails['latitude'] = $this->validatedata->validate('latitude', 'latitude', false, '', array());
            $customerDetails['longitude'] = $this->validatedata->validate('longitude', 'longitude', false, '', array());
            $customerDetails['zipcode'] = $this->validatedata->validate('zipcode', 'zipcode', false, '', array());
            $customerDetails['office_land_line'] = $this->validatedata->validate('office_land_line', 'office_land_line', false, '', array());
            $customerDetails['lead_source'] = $this->validatedata->validate('lead_source', 'lead source', false, '', array());
            $customerDetails['mailing_address'] = $this->validatedata->validate('mailing_address', 'Mailing Address', false, '', array());
            $customerDetails['additional_contacts'] = $this->input->post('additional_contacts');
            $customerDetails['email'] = $this->validatedata->validate('email', 'Email', false, '', array());
            $customerDetails['mobile_no'] = $this->validatedata->validate('mobile_no', 'Mobile', false, '', array());
            $customerDetails['wa_number'] = $this->validatedata->validate('wa_number', 'Whats App Number', false, '', array());
            $customerDetails['preferred_communication'] = $this->validatedata->validate('preferred_communication', 'Preferred comminication', false, '', array());
            $customerDetails['gst_state'] = $this->validatedata->validate('gst_state', 'GST State', false, '', array());
            $customerDetails['lead_priority'] = $this->validatedata->validate('lead_priority', 'lead_priority', false, '', array());
            $customerDetails['assignee'] = $this->validatedata->validate('assignee', 'Assignee', false, '', array());
            $customerDetails['customer_portal_access'] = $this->validatedata->validate('customer_portal_access', 'Customer Portal Access', false, '', array());
            $customerDetails['remark'] = $this->validatedata->validate('remark', 'remark', false, '', array());
            $customerDetails['enquiry_for'] = $this->validatedata->validate('enquiry_for', 'Enquiry For', false, '', array());
            //$customerDetails = $this->populateContact($customerDetails);
            $menuDetails = $this->datatables->getMenuDetails($this->menuID);
            $fieldData = ($customerDetails['type'] =="lead") ? $this->datatables->mapDynamicFeilds("leads",$this->input->post()) : $this->datatables->mapDynamicFeilds("customer",$this->input->post());
            if (isset($customerDetails['birth_date']) && !empty($customerDetails['birth_date']) && $customerDetails['birth_date'] != "0000-00-00") {
                $customerDetails['birth_date'] = str_replace("/", "-", $customerDetails['birth_date']);
                $customerDetails['birth_date'] = date("Y-m-d", strtotime($customerDetails['birth_date']));
            }else{
                $customerDetails['birth_date'] = null;
            }

            if(!isset($customerDetails['pan_number']) && empty($customerDetails['pan_number'])){
                $customerDetails['pan_number'] = null;
            }

            if(!isset($customerDetails['branch_id']) && empty($customerDetails['branch_id'])){
                $customerDetails['branch_id'] = null;	
            }
            if ($method == "PUT") {
                $this->db->trans_start();
                if(isset($customerDetails['email']) && !empty($customerDetails['email'])){
                    $where= array("email"=>$customerDetails['email']);
                    $customerEmail = $this->CommonModel->getMasterDetails('customer','',$where);
                    if(!empty($customerEmail)){
                        $this->db->trans_rollback();
                        $status['msg'] = $this->systemmsg->getErrorCode(278);
                        $status['statusCode'] = 278;
                        $status['data'] = array();
                        $status['flag'] = 'F';
                        $this->response->output($status, 200);
                    }
                }
                $customerDetails['company_id'] = $this->company_id;
                $iticode = $customerDetails['customer_id'];
                $customerDetails['status'] = "active";
                $customerDetails['created_by'] = $this->input->post('SadminID');
                $customerDetails['created_date'] = $updateDate;
                $iscreated = $this->CommonModel->saveMasterDetails('customer', $customerDetails);
                if (!$iscreated) {
                    $status['msg'] = $this->systemmsg->getErrorCode(998);
                    $status['statusCode'] = 998;
                    $status['data'] = array();
                    $status['flag'] = 'F';
                    $this->response->output($status, 200);
                } else {
                    $customer_id = $this->db->insert_id();
                    $this->history->addCreate('lead', $customer_id,$customer_id,'lead',$customerDetails['created_by']);
                    $this->filterbuilder->upsertDynamicData();
                    $status['triggerNotification'] = 'N';
                    if(!$this->config->item('development')){
                        $postData = [
                            'action'      => 'add',
                            'tableName'   => 'customer',
                            'primaryKey'  => 'customer_id',
                            'primary_id'  => $customer_id,
                            'oldData'     => json_encode([]),
                            'menuID'      => $this->menuID,
                            'company_id'  => $this->company_id
                        ];
                        $status['triggerNotification'] = 'Y';
                        $status['notificationData'] = json_encode($postData);
                    }
                    if($customerDetails['customer_portal_access'] == 'yes'){
                        if (empty($customerDetails['email'])) {
                            $status['msg'] = str_replace("{fieldName}", 'Email', $this->systemmsg->getErrorCode(218));
                            $status['statusCode'] = 218;
                            $status['data'] = array();
                            $status['flag'] = 'F';
                            $this->response->output($status, 200);
                        }
                        if (empty($customerDetails['mobile_no'])) {
                            $status['msg'] = str_replace("{fieldName}", 'Mobile No', $this->systemmsg->getErrorCode(218));
                            $status['statusCode'] = 218;
                            $status['data'] = array();
                            $status['flag'] = 'F';
                            $this->response->output($status, 200);
                        }
                        $baseURL = $this->generatePasswordRequest($customerDetails,$customer_id);
                        $status['baseURL'] = $baseURL;
                    }
                    $this->db->trans_commit();
                    $status['lastID'] = $customer_id;

                    $status['msg'] = $this->systemmsg->getSucessCode(400);
                    $status['statusCode'] = 400;
                    $status['data'] = array();
                    $status['flag'] = 'S';
                    $this->response->output($status, 200);
                }
            } elseif ($method == "POST") {
                $where = array('customer_id' => $customer_id);
                if (!isset($customer_id) || empty($customer_id)) {
                    $status['msg'] = $this->systemmsg->getErrorCode(998);
                    $status['statusCode'] = 998;
                    $status['data'] = array();
                    $status['flag'] = 'F';
                    $this->response->output($status, 200);
                }
                $customerDetails['modified_by'] = $this->input->post('SadminID');
                $customerDetails['modified_date'] = $updateDate;
                $oldData = $this->CommonModel->getMasterDetails('customer', '', $where);
                if($oldData[0]->stages != $customerDetails['stages']){
                    $customerDetails['last_activity_date'] = date("Y/m/d H:i:s");
                }
                $iscreated = $this->CommonModel->updateMasterDetails('customer', $customerDetails, $where);

                if (!$iscreated) {
                    $status['msg'] = $this->systemmsg->getErrorCode(998);
                    $status['statusCode'] = 998;
                    $status['data'] = array();
                    $status['flag'] = 'F';
                    $this->response->output($status, 200);
                } else {
                    $newData = $this->CommonModel->getMasterDetails('customer', '', $where);
                    $this->history->compareAndAdd($customerDetails['type'], $customer_id,$oldData[0],$newData[0],$customerDetails['type'],$customer_id,$customerDetails['modified_by']);

                    $whereD['customer_id'] = $customer_id;
                    $this->filterbuilder->upsertDynamicData($customer_id);
                    $status['triggerNotification'] = 'N';
                    if(!$this->config->item('development')){
                        $postData = [
                            'action'      => 'update',
                            'tableName'   => 'customer',
                            'primaryKey'  => 'customer_id',
                            'primary_id'  => $customer_id,
                            'oldData'     => json_encode($oldData),
                            'menuID'      => $this->menuID,
                            'company_id'  => $this->company_id
                        ];
                        $status['triggerNotification'] = 'Y';
                        $status['notificationData'] = json_encode($postData);
                    }
                    $status['lastID'] = $customer_id;
                    $status['msg'] = $this->systemmsg->getSucessCode(400);
                    $status['statusCode'] = 400;
                    $status['data'] = array();
                    $status['flag'] = 'S';
                    $this->response->output($status, 200);
                }
            } elseif ($method == "dele") {
                $customerDetails = array();
                $where = array('sID' => $sID);
                if (!isset($sID) || empty($sID)) {
                    $status['msg'] = $this->systemmsg->getErrorCode(996);
                    $status['statusCode'] = 996;
                    $status['data'] = array();
                    $status['flag'] = 'F';
                    $this->response->output($status, 200);
                }
                $iscreated = $this->CommonModel->deleteMasterDetails('customer', $where);
                if (!$iscreated) {
                    $status['msg'] = $this->systemmsg->getErrorCode(996);
                    $status['statusCode'] = 996;
                    $status['data'] = array();
                    $status['flag'] = 'F';
                    $this->response->output($status, 200);
                } else {
                    $status['triggerNotification'] = 'N';
                    if(!$this->config->item('development')){
                        $oldData = $this->CommonModel->getMasterDetails('customer', '', $where) ;
                        $postData = [
                            'action'      => 'delete',
                            'tableName'   => 'customer',
                            'primaryKey'  => 'customer_id',
                            'primary_id'  => $customer_id,
                            'oldData'     => json_encode($oldData),
                            'menuID'      => $this->menuID,
                            'company_id'  => $this->company_id
                        ];
                        $status['triggerNotification'] = 'Y';
                        $status['notificationData'] = json_encode($postData);
                    }
                    $status['msg'] = $this->systemmsg->getSucessCode(400);
                    $status['statusCode'] = 400;
                    $status['data'] = array();
                    $status['flag'] = 'S';
                    $this->response->output($status, 200);
                }
            }
        } else {
            if($customer_id ==""){
                $status['msg'] = $this->systemmsg->getSucessCode(400);
                $status['statusCode'] = 400;
                $status['data'] =array();
                $status['flag'] = 'S';
                $this->response->output($status,200);
            }
            //$rec = $this->filterbuilder->fetchRecordWithDynamic($this->menuID, $customer_id);
            $record = $this->filterbuilder->fetchRecordFlat($this->menuID, (int)$customer_id, 'labels', true);
            $status['data'][0] = $record;
            $status['msg'] = "";
            $status['statusCode'] = 200;
            //$status['data'] = array();
            $status['flag'] = 'S';
            $this->response->output($status, 200);
        }
    }
    public function populateContact($customerDetails){
		if (isset($customerDetails['additional_contacts']) && !empty($customerDetails['additional_contacts'])) {
			$additional_contacts = json_decode($customerDetails['additional_contacts'],true);
			// breakPoint([$additional_contacts]);exit;
			$is_primary_count = 0;
			foreach ($additional_contacts as $key => $contact) {
				$empty_count = 0 ;
				foreach ($contact as $contact_key => $contact_value) {
					if ( ($contact_key !='is_primary') && (!isset($contact_value) || empty($contact_value))) {
						$empty_count++;
					}
					if (($contact_key == 'is_primary') && ($contact_value == false || !isset($contact_value))) {
						$is_primary_count++;
					}
				}
				if ($empty_count == count($contact)) {
					unset($additional_contacts[$key]);
				}
				if (count($additional_contacts) == 1) {
					$contact['is_primary'] = true;
				}
				// if ($contact['is_primary']) {
				// 	if((isset($contact['country_code']) && !empty($contact['country_code'])) && (isset($contact['mobile_no']) && !empty($contact['mobile_no']))){
				// 		$contact['country_code'] = str_replace("+","",$contact['country_code']);
				// 		$formattedNumber = $contact['country_code']. '' . $contact['mobile_no'];
				// 		$customerDetails['mobile_no'] = $formattedNumber;
				// 	}else{
				// 		if(isset($contact['mobile_no']) && !empty($contact['mobile_no'])){
				// 			$customerDetails['mobile_no'] = $contact['mobile_no'];
				// 		}
				// 	}
				// 	if((isset($contact['wa_country_code']) && !empty($contact['wa_country_code'])) && (isset($contact['Whatsapp_no']) && !empty($contact['Whatsapp_no']))){
				// 		$contact['wa_country_code'] = str_replace("+","",$contact['wa_country_code']);
				// 		$formattedNumber = $contact['wa_country_code']. '' . $contact['Whatsapp_no'];
				// 		$customerDetails['wa_number'] = $formattedNumber;
				// 	}else{
				// 		if(isset($contact['wa_number']) && !empty($contact['wa_number'])){
				// 			$customerDetails['wa_number'] = $contact['wa_number'];
				// 		}
				// 	}
				// 	// if((isset($contact['country_code']) && !empty($contact['country_code'])) && (isset($contact['mobile_no']) && !empty($contact['mobile_no']))){
				// 	// 	$contact['country_code'] = str_replace("+","",$contact['country_code']);
				// 	// 	$formattedNumber = $contact['country_code']. '' . $contact['mobile_no'];
				// 	// 	$customerDetails['mobile_no'] = $formattedNumber;
				// 	// }else{
				// 	// 	if(isset($contact['mobile_no']) && !empty($contact['mobile_no'])){
				// 	// 		$customerDetails['mobile_no'] = $contact['mobile_no'];
				// 	// 	}
				// 	// }
				// 	if(isset($contact['email']) && !empty($contact['email'])){
				// 		$customerDetails['email'] = $contact['email'];
				// 	}
				// 	if(isset($contact['contact_type']) && !empty($contact['contact_type'])){
				// 		$customerDetails['contact_type'] = $contact['contact_type'];
				// 	}
				// }
			}
			
			if (count($additional_contacts) == $is_primary_count) {
				$additional_contacts['contact_1']['is_primary'] = true;
				if((isset($additional_contacts['contact_1']['country_code']) && !empty($additional_contacts['contact_1']['country_code'])) && (isset($additional_contacts['contact_1']['mobile_no']) && !empty($additional_contacts['contact_1']['mobile_no']))){
					$formattedNumber = str_replace("+","",$contact['country_code']). '' . $contact['mobile_no'];
					$customerDetails['mobile_no'] = $formattedNumber;
				}else{
					$customerDetails['mobile_no'] = $additional_contacts['contact_1']['mobile_no'];
				}
				if((isset($additional_contacts['contact_1']['wa_country_code']) && !empty($additional_contacts['contact_1']['wa_country_code'])) && (isset($additional_contacts['contact_1']['Whatsapp_no']) && !empty($additional_contacts['contact_1']['Whatsapp_no']))){
					$formattedNumber = str_replace("+","",$contact['wa_country_code']). '' . $contact['Whatsapp_no'];
					$customerDetails['wa_number'] = $formattedNumber;
				}else{
					$customerDetails['wa_number'] = $additional_contacts['contact_1']['wa_number'];
				}
				if(isset($additional_contacts['contact_1']['contact_type']) && !empty($additional_contacts['contact_1']['contact_type'])){
					$customerDetails['contact_type'] = $additional_contacts['contact_1']['contact_type'];
				}
			}
			$customerDetails['additional_contacts'] = json_encode($additional_contacts);
		}else{
			$additional_contacts['contact_1'] = [];
			if (isset($customerDetails['wa_number']) && !empty($customerDetails['wa_number'])) {
				$additional_contacts['contact_1']['Whatsapp_no'] = $customerDetails['wa_number'];
			}
			if (isset($customerDetails['mobile_no']) && !empty($customerDetails['mobile_no'])) {
				$additional_contacts['contact_1']['mobile_no'] = $customerDetails['mobile_no'];
			}
			if (isset($customerDetails['email']) && !empty($customerDetails['email'])) {
				$additional_contacts['contact_1']['email'] = $customerDetails['email'];
			}
			if (!empty($additional_contacts['contact_1'])) {
				$additional_contacts['contact_1']['contact_person_name'] = $customerDetails['name'];
				$additional_contacts['contact_1']['contact_type'] = null;
				$additional_contacts['contact_1']['country_code'] = '+91';
				$additional_contacts['contact_1']['wa_country_code'] = '+91';
				$additional_contacts['contact_1']['is_primary'] = true;
				$customerDetails['additional_contacts'] = json_encode($additional_contacts);
			}else{
				$customerDetails['additional_contacts'] = '{}';
			}
		}
		return $customerDetails;
	}

    public function getcustomerNotesDetails()
	{
		$this->access->checkTokenKey();
		$this->response->decodeRequest();
		$isAll = $this->input->post('getAll');
		$customer = $this->input->post('customer_id');
		$record_type = $this->input->post('record_type');
		$wherec = $join = array();

		if (!isset($orderBy) || empty($orderBy)) {
			$orderBy = "note_id";
			$order = "DESC";
		}

		$other = array("orderBy"=>$orderBy,"order"=>$order);

		if(isset($customer) && !empty($customer)){			
			$customer = trim($customer);
			$wherec["record_id ="] = "'".$customer."'";
		}

		if(isset($record_type) && !empty($record_type)){			
			$wherec["record_type ="] = "'".$record_type."'";
		}

		$adminID = $this->input->post('SadminID');
		if ($isAll == "Y") {
			$join = array();
			$customerNotesDetails = $this->CommonModel->GetMasterListDetails($selectC='*','notes',$wherec,'','','', $other);	
		}else{
			$selectC = "*";
			$customerNotesDetails = $this->CommonModel->GetMasterListDetails($selectC, 'notes', $wherec, '', '', '', $other);
		}
		$status['data'] = $customerNotesDetails;
		if ($customerNotesDetails) {
			$status['msg'] = "sucess";
			$status['statusCode'] = 400;
			$status['flag'] = 'S';
			$this->response->output($status, 200);
		} else {
			$status['msg'] = $this->systemmsg->getErrorCode(227);
			$status['statusCode'] = 227;
			$status['flag'] = 'F';
			$this->response->output($status, 200);
		}
	}

	public function customerNote($note_id = "")
	{

		$this->access->checkTokenKey();
		$this->response->decodeRequest();
		$method = $this->input->method(TRUE);

		// print_r($method);exit;
		if ($method == "POST" || $method == "PUT") {
			$customerNote = array();
			$updateDate = date("Y/m/d H:i:s");
			$customerNote['record_id'] = $this->validatedata->validate('customer_id', 'Customer ID', false, '', array());
			$customerNote['note_desc'] = $this->validatedata->validate('note_desc', 'Customer Note', false, '', array());
			$customerNote['title'] = $this->validatedata->validate('title', 'Title', false, '', array());
			$customerNote['reminder_date'] = $this->validatedata->validate('reminder_date', 'Reminder Date', false, '', array());
            $customerNote['record_type'] = $this->validatedata->validate('record_type', 'Record Type', false, '', array());
			$reminder_time = $this->validatedata->validate('reminder_time', 'Reminder Time', false, '', array());
			if($this->input->post('record_type') == 'followup'){
				$customerNote['follow_up_date'] = $this->validatedata->validate('follow_up_date', 'Follow Up Date', true, '', array());
			}
			if(isset($customerNote['follow_up_date']) && !empty($customerNote['follow_up_date']) && $customerNote['follow_up_date'] != "0000-00-00") {
				$customerNote['follow_up_date'] = str_replace("/", "-", $customerNote['follow_up_date']);
				$customerNote['follow_up_date'] = date("Y-m-d", strtotime($customerNote['follow_up_date']));
			} else {
				$customerNote['follow_up_date'] = null;
			}
            $customerDetails = $this->CommonModel->getMasterDetails('customer', '', array("customer_id"=>$customerNote['record_id']));
            if ($method == "PUT") {
				
				$customerNote['created_by'] = $this->input->post('SadminID');
				$customerNote['created_date'] = $updateDate;
				$iscreated = $this->CommonModel->saveMasterDetails('notes', $customerNote);
				$lastNoteID = $this->db->insert_id();
				if (!$iscreated) {
					$status['msg'] = $this->systemmsg->getErrorCode(998);
					$status['statusCode'] = 998;
					$status['data'] = array();
					$status['flag'] = 'F';
					$this->response->output($status, 200);
				} else {
                    
                    $this->history->addCreate('note',$lastNoteID,$customerNote['record_id'],$customerDetails[0]->type,$customerNote['created_by']);
                    $this->updateEarlistFollowUpDate($customerNote['record_id']);
					$status['msg'] = $this->systemmsg->getSucessCode(400);
					$status['statusCode'] = 400;
					$status['data'] = array();
					$status['lastID'] = $lastNoteID;
					$status['flag'] = 'S';
					$this->response->output($status, 200);
				}
			} elseif ($method == "POST") {
				$where = array('note_id' => $note_id);
				if (!isset($note_id) || empty($note_id)) {
					$status['msg'] = $this->systemmsg->getErrorCode(998);
					$status['statusCode'] = 998;
					$status['data'] = array();
					$status['flag'] = 'F';
					$this->response->output($status, 200);
				}
                $oldData = $this->CommonModel->getMasterDetails('notes', '', $where);
				$customerNote['modified_by'] = $this->input->post('SadminID');
				$customerNote['modified_date'] = $updateDate;
				$iscreated = $this->CommonModel->updateMasterDetails('notes', $customerNote, $where);
                if (!$iscreated) {
					$status['msg'] = $this->systemmsg->getErrorCode(998);
					$status['statusCode'] = 998;
					$status['data'] = array();
					$status['flag'] = 'F';
					$this->response->output($status, 200);
				} else {
                    
                    $newData = $this->CommonModel->getMasterDetails('notes', '', $where);
                    $this->history->addEntry('note',$note_id,'note',$oldData[0]->title, $newData[0]->title,"Note Updated",$customerDetails[0]->type,$customerNote['record_id'],$customerNote['modified_by']);
                    $this->updateEarlistFollowUpDate($customerNote['record_id']);
					$status['msg'] = $this->systemmsg->getSucessCode(400);
					$status['statusCode'] = 400;
					$status['data'] = array();
					$status['flag'] = 'S';
					$this->response->output($status, 200);
				}
			} elseif ($method == "dele") {
				$customerNote = array();
				$where = array('sID' => $sID);
				if (!isset($sID) || empty($sID)) {
					$status['msg'] = $this->systemmsg->getErrorCode(996);
					$status['statusCode'] = 996;
					$status['data'] = array();
					$status['flag'] = 'F';
					$this->response->output($status, 200);
				}

				$iscreated = $this->CommonModel->deleteMasterDetails('notes', $where);
				if (!$iscreated) {
					$status['msg'] = $this->systemmsg->getErrorCode(996);
					$status['statusCode'] = 996;
					$status['data'] = array();
					$status['flag'] = 'F';
					$this->response->output($status, 200);
				} else {
					$status['msg'] = $this->systemmsg->getSucessCode(400);
					$status['statusCode'] = 400;
					$status['data'] = array();
					$status['flag'] = 'S';
				}
					$this->response->output($status, 200);
			}
		} else {

			$where = array("note_id" => $note_id);
			$customerDetails = $this->CommonModel->getMasterDetails('notes', '', $where);

			if (isset($customerDetails) && !empty($customerDetails)) {

				$status['data'] = $customerDetails;
				$status['statusCode'] = 200;
				$status['flag'] = 'S';
				$this->response->output($status, 200);
			} else {

				$status['msg'] = $this->systemmsg->getErrorCode(227);
				$status['statusCode'] = 227;
				$status['data'] = array();
				$status['flag'] = 'F';
				$this->response->output($status, 200);
			}
		}
	}

	public function noteDelete(){
		$this->access->checkTokenKey();
		$this->response->decodeRequest();
		$action = $this->input->post("action");
		$noteID= $this->input->post("id");
		$wherec["note_id"] = $noteID;
		// $where = array("note_id" => $note_id);
		$noteDetails = $this->CommonModel->getMasterDetails('notes', '', $wherec);
        // print_r($noteDetails);
        // print $this->db->last_query();
		$changestatus = $this->CommonModel->deleteMasterDetails('notes',$wherec);
		if($changestatus){
			$this->updateEarlistFollowUpDate($noteDetails[0]->record_id);
			$status['data'] = array();
			$status['statusCode'] = 200;
			$status['flag'] = 'S';
			$this->response->output($status, 200);
		} else {
			$status['data'] = array();
			$status['msg'] = $this->systemmsg->getErrorCode(996);
			$status['statusCode'] = 996;
			$status['flag'] = 'F';
			$this->response->output($status, 200);
		}
	}
    	public function updateEarlistFollowUpDate($customer_id = ''){
		$wherec = [] ;
		if (isset($customer_id) && !empty($customer_id)) {
			$wherec["t.customer_id ="] = "'".$customer_id."'";			
		}
		$customerDetails = $this->CommonModel->GetMasterListDetails($selectC="t.customer_id",'customer',$wherec,'','',[],[]);	
		foreach ($customerDetails as $key => $value) {
			$wherec = array();
			$whereN["t.record_id"] = ' = "' . $value->customer_id . '"';
			$whereN["t.record_type"] = ' = "followup" ';
			$whereN["t.follow_up_date"] = ' > '.date('Y-m-d');
			$customerNote = $this->CommonModel->GetMasterListDetails('follow_up_date', 'notes', $whereN,'1', '', [], ['order'=>'ASC' ,'orderBy'=>"follow_up_date"]);
			$where['customer_id'] = $value->customer_id;
			if(isset($customerNote) && !empty($customerNote)){
				$customerDetails1['follow_up_date'] = (isset($customerNote[0]->follow_up_date) && !empty($customerNote[0]->follow_up_date)) ? $customerNote[0]->follow_up_date : null;
			}else{
				$customerDetails1['follow_up_date'] = null;
			}
			$iscreated = $this->CommonModel->updateMasterDetails('customer', $customerDetails1, $where);
			if (!$iscreated) {
				$emailError['message'] = str_replace("{{error}}", 'Error while inserting Followup Date', $this->systemmsg->getErrorCode(340));
				$emailError['code'] = 340;
				$this->errorlogs->checkDBError($emailError, 'Campaign Error', dirname(__FILE__), __LINE__, __METHOD__);
			}
		}
	}

    public function download($columns,$rows,$payload)
    {
        $staticJoined = $payload['staticJoined'];
		$columnMapping = isset($payload['columnMapping']) ? json_decode($payload['columnMapping'],true) : [] ;
        $dateFormat = null ;
		if(isset($postData['SadminID']) && !empty($postData['SadminID'])){
			$defaultComp = $this->CommonModel->getMasterDetails('admin', 'default_company', array('adminID'=>$postData['SadminID']));
			if(isset($defaultComp[0]->default_company) && !empty($defaultComp[0]->default_company)){
				$defaultCompsettings = $this->CommonModel->getMasterDetails('info_settings', 'date_format', array('infoID'=>$defaultComp[0]->default_company));
				if(isset($defaultCompsettings[0]->date_format) && !empty($defaultCompsettings[0]->date_format)){
					$dateFormat = $defaultCompsettings[0]->date_format;
				}
			}
		}
       $headers = [];
        foreach ($columns as $value) {
            if (isset($columnMapping[$value])) {
                $headers[] = $columnMapping[$value];
            } else {
                $headers[] = capitalize_words(str_replace("_", " ", $value));
            }
        }
        if($payload['reportType'] == "pdf"){
            $this->printpdf($headers,$columns,$rows);
            exit;
        }		
        gc_enable();                         // Enable garbage collector
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet()->setTitle('Sheet1');
        $sheet->fromArray($headers, null, 'A1');
        //print_r($columns);exit;
        // ============ DATA ROWS ============
        $row = 2;
        foreach ($rows as $item) {

            $rowData = [];
            foreach ($columns as $col) {
                // Handle special cases here if needed
                if(array_key_exists($col, $item)){
                    $rowData[] = $item[$col];
                } //else {
                //     $rowData[] = ""; // fallback if field missing
                // }
            }
            $sheet->fromArray($rowData, null, 'A' . $row);
            $row++;
        }

        // ============ AUTO SIZE ============
        foreach (range('A', $sheet->getHighestColumn()) as $col) {
            $sheet->getColumnDimension($col)->setAutoSize(true);
        }

        // ============ OUTPUT ============
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment; filename="user_data_report.xlsx"');

        if (ob_get_length()) ob_end_clean();
        $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);

        // Memory optimization
        $writer->setPreCalculateFormulas(false);

        $writer->save('php://output');

        // Free memory
        $spreadsheet->disconnectWorksheets();
        unset($spreadsheet);
        gc_collect_cycles();
    }
    function printpdf($headers,$columns,$rows){
        
        $this->load->library('MPDFCI');
        $this->mpdfci->SetHTMLFooter('<div style="text-align:center">{PAGENO} of {nbpg}</div>');
        $this->mpdfci->showWatermarkImage = false;

        $css = 'table{border-collapse:collapse;width:100%;table-layout:fixed;}
                th,td{border:1px solid #ddd;padding:6px;font-size:12px;word-wrap:break-word;vertical-align:top;}
                h3{margin:0 0 8px 0;}';
        $this->mpdfci->WriteHTML($css, \Mpdf\HTMLParserMode::HEADER_CSS);

        $this->mpdfci->WriteHTML('<h3>Report</h3>', \Mpdf\HTMLParserMode::HTML_BODY);

        // THEAD in the exact order of $labels
        $thead = '<thead><tr>';
        foreach ($headers as $label) {
            $thead .= '<th>'.htmlspecialchars((string)$label, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8').'</th>';
        }
        $thead .= '</tr></thead>';
        $this->mpdfci->WriteHTML('<table class="report">'.$thead.'<tbody>', \Mpdf\HTMLParserMode::HTML_BODY);

        // --- Stream rows in batches (memory-safe) ---
        $batchSize = 150; $buf = ''; $i = 0;

        foreach ($rows as $row) {
            $rowData=[];
            foreach ($columns as $col) {
                // Handle special cases here if needed
                //if (isset($row[$col])) {
                if(array_key_exists($col, $row)){
                    $rowData[$col] = $row[$col];
                }
                // else {
                //     $rowData[] = ""; // fallback if field missing
                // }
            }

            $cells = '';
            foreach ($rowData as $idx => $val) {
               // $key = $labelToKey[$idx]; // preserves label order
                if ($val instanceof \DateTimeInterface) {
                    $val = $val->format('Y-m-d H:i');
                } elseif (is_array($val) || is_object($val)) {
                    $val = json_encode($val, JSON_UNESCAPED_UNICODE);
                }
                
                $clean = strip_tags((string)$val);

                // Normalize line breaks
                $clean = str_replace(["\r\n", "\r"], "\n", $clean);

                // Convert newlines to <br> for mPDF
                $clean = nl2br(htmlspecialchars($clean, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'));

                $cells .= '<td>'.$clean.'</td>';

                //$cells .= '<td>'.htmlspecialchars((string)$val, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8').'</td>';
            }
            $buf .= '<tr>'.$cells.'</tr>';

            if ((++$i % $batchSize) === 0) {
                $this->mpdfci->WriteHTML($buf, \Mpdf\HTMLParserMode::HTML_BODY);
                $buf = '';
            }
        }
        if ($buf !== '') {
            $this->mpdfci->WriteHTML($buf, \Mpdf\HTMLParserMode::HTML_BODY);
        }
        $this->mpdfci->WriteHTML('</tbody></table>', \Mpdf\HTMLParserMode::HTML_BODY);
        if (ob_get_length()) { @ob_end_clean(); }
        return $this->mpdfci->Output('report.pdf', \Mpdf\Output\Destination::INLINE);
    }
}