<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Contacts extends CI_Controller
{
  public $columnNames = [
    "assignee"=> ["table" => "admin","alias" => "ai",  "column" => "name","key2" => "adminID","select" => ""],
  ];

  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('Filters',['customCol' => $this->customCol,'columnNames'=>$this->columnNames], 'filters');
  }

  public function list()
  {
    $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'

    $limit  = min(200, max(1, (int)($payload['limit'] ?? 20)));
    $offset = $curPageIdx * $limit;
   
    $plan  = $this->filterengine->buildPlan($menuId, $columns, $filters, $freeTxt, $sort, $this->columnNames, $this->customCol);
    $total = $this->Model->countByPlan($plan, $plan['pk']);
    $rows  = $this->Model->listByPlan($plan, $limit, $offset);

        $debugSql = $this->Model->compilePlanSQL($plan);

        //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 create($contact_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['contact_id'] = $this->validatedata->validate('contact_id', 'Contact ID', false, '', array());
            $customerDetails['name'] = $this->validatedata->validate('salutation', 'Salutation', false, '', array());
            $customerDetails['name'] = $this->validatedata->validate('name', 'Name', true, '', array());
            $customerDetails['email'] = $this->validatedata->validate('email', 'Email', false, '', array());
            $customerDetails['mobile'] = $this->validatedata->validate('mobile', 'Mobile', false, '', array());
            $customerDetails['wa_number'] = $this->validatedata->validate('wa_number', 'Whats App Number', false, '', array());
            $customerDetails['designation'] = $this->validatedata->validate('designation', 'Designation', false, '', array());
            $customerDetails['department'] = $this->validatedata->validate('department', 'Department', false, '', array());
            $customerDetails['contact_type'] = $this->validatedata->validate('contact_type', 'Contact Type', false, '', array());
            $customerDetails['contact_type_other'] = $this->validatedata->validate('contact_type_other', 'Contact Other', false, '', array());
            $customerDetails['status'] = $this->validatedata->validate('status', 'Contact Status', false, '', array());
            //$customerDetails = $this->populateContact($customerDetails);
            //$menuDetails = $this->datatables->getMenuDetails($this->menuID);
            
            if ($method == "PUT") {
                $this->db->trans_start();
                if(isset($customerDetails['email']) && !empty($customerDetails['email'])){
                    $where= array("email"=>$customerDetails['email']);
                    $customerEmail = $this->CommonModel->getMasterDetails('contacts','',$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['contact_id'];
                $customerDetails['status'] = "active";
                $customerDetails['created_by'] = $this->input->post('SadminID');
                $customerDetails['created_date'] = $updateDate;
                $iscreated = $this->CommonModel->saveMasterDetails('contacts', $customerDetails);
                if (!$iscreated) {
                    $status['msg'] = $this->systemmsg->getErrorCode(998);
                    $status['statusCode'] = 998;
                    $status['data'] = array();
                    $status['flag'] = 'F';
                    $this->response->output($status, 200);
                } else {
                    $contact_id = $this->db->insert_id();
                    //$this->history->addCreate('lead', $contact_id,$contact_id,'lead',$customerDetails['created_by']);
                    $this->db->trans_commit();
                    $status['lastID'] = $contact_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('contact_id' => $contact_id);
                if (!isset($contact_id) || empty($contact_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;
                $iscreated = $this->CommonModel->updateMasterDetails('contacts', $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('contacts', '', $where);
                    // $this->history->compareAndAdd('contact', $contact_id,$oldData[0],$newData[0],$customerDetails['type'],$contact_id,$customerDetails['modified_by']);
                    $whereD['contact_id'] = $contact_id;
                    $status['lastID'] = $contact_id;
                    $status['msg'] = $this->systemmsg->getSucessCode(400);
                    $status['statusCode'] = 400;
                    $status['data'] = array();
                    $status['flag'] = 'S';
                    $this->response->output($status, 200);
                }
            } 
        } else {
            if($contact_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, $contact_id);
            //$record = $this->filterbuilder->fetchRecordFlat($this->menuID, (int)$contact_id, 'labels', true);
            $where = array("contact_id" => $contact_id);
			$record = $this->CommonModel->getMasterDetails('contacts', '', $where);
			if (isset($record) && !empty($record)) {
				$status['data'] = $record;
				$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 multipleChangeStatus()
    {
        $this->access->checkTokenKey();
        $this->response->decodeRequest();
        $action = $this->input->post("action");
        $ids = $this->input->post("list");
        $statusCode = $this->input->post("status");
        $menuId = $this->input->post("menuId");
        if (trim($action) == "delete") {
            $whereIn['contact_id'] = $ids;
            $changestatus = $this->CommonModel->multipleDeleteMasterDetails('contacts', '', $whereIn);
        } else {
            $changestatus = $this->CommonModel->changeMasterStatus('contacts', $action, $ids, 'contact_id');
        }
        if ($changestatus) {
            $status['data'] = array();
            $status['statusCode'] = 200;
            $status['flag'] = 'S';
            $this->response->output($status, 200);
        } else {
            $this->response->outputErrorResponse(996);
        }
    }
    public function search()
    {
        $this->access->checkTokenKey();
        $payload = json_decode($this->input->raw_input_stream, true);

        $q = trim($payload['q'] ?? '');
        if ($q === '') {
            $this->response->output(['flag'=>'S','data'=>[]], 200);
            return;
        }

        $this->db->select('contact_id, name, email, mobile, wa_number');
        $this->db->from('contacts');
        $this->db->group_start()
            ->like('name', $q)
            ->or_like('email', $q)
            ->or_like('mobile', $q)
            ->group_end();
        $this->db->limit(10);

        $rows = $this->db->get()->result_array();

        $this->response->output([
            'flag' => 'S',
            'data' => $rows
        ], 200);
    }
    
    public function attachContactNew($record_id)
    {
        $this->access->checkTokenKey();
        $this->response->decodeRequest();
        $updateDate = date("Y/m/d H:i:s");
        $customerDetails['name'] = $this->validatedata->validate('name', 'Name', true, '', array());
        $customerDetails['email'] = $this->validatedata->validate('email', 'Email', false, '', array());
        $customerDetails['mobile'] = $this->validatedata->validate('mobile', 'Mobile', false, '', array());
        $customerDetails['wa_number'] = $this->validatedata->validate('wa_number', 'Whats App Number', false, '', array());
        $customerDetails['designation'] = $this->validatedata->validate('designation', 'Designation', false, '', array());
        $customerDetails['department'] = $this->validatedata->validate('department', 'Department', false, '', array());
        $customerDetails['contact_type'] = $this->validatedata->validate('contact_type', 'Contact Type', false, '', array());
        $customerDetails['contact_type_other'] = $this->validatedata->validate('contact_type_other', 'Contact Other', false, '', array());
        $customerDetails['status'] = $this->validatedata->validate('status', 'Contact Status', false, '', array());
        $userId = $this->input->get_request_header('SadminID', true);
        if (!$userId) $userId = $payload['SadminID'] ?? $this->input->post('SadminID');


        $customerDetails['created_by'] = $this->input->post('SadminID');
        $customerDetails['created_date'] = $updateDate;
        $iscreated = $this->CommonModel->saveMasterDetails('contacts', $customerDetails);
        if (!$iscreated) {
            $status['msg'] = $this->systemmsg->getErrorCode(998);
            $status['statusCode'] = 998;
            $status['data'] = array();
            $status['flag'] = 'F';
            $this->response->output($status, 200);
        } else {
            $contact_id = $this->db->insert_id();
            $this->db->insert('contacts_record', [
                'record_id'  => $record_id,
                'contact_id' => $contact_id,
                'is_primary' => (int)($c['is_primary'] ?? 0)
            ]);

            if (!empty($c['is_primary'])) {
                $this->_syncPrimaryContactToRecord($record_id, $contact_id);
            }
            $status['lastID'] = $contact_id;
            $status['msg'] = $this->systemmsg->getSucessCode(400);
            $status['statusCode'] = 400;
            $status['data'] = array();
            $status['flag'] = 'S';
            $this->response->output($status, 200);
        }
    }
    public function attachContact()
    {
        $this->access->checkTokenKey();
        $payload = json_decode($this->input->raw_input_stream, true);

        $record_id  = (int)$payload['record_id'];
        $contact_id = (int)$payload['contact_id'];
        $is_primary = (int)($payload['is_primary'] ?? 0);

        // Prevent duplicate mapping
        $exists = $this->db->get_where('contacts_record', [
            'record_id' => $record_id,
            'contact_id' => $contact_id
        ])->row_array();

        if ($exists) {
            $this->response->output(['flag'=>'S','msg'=>'Already attached'], 200);
            return;
        }

        if ($is_primary) {
            $this->db->where('record_id', $record_id)
                    ->update('contacts_record', ['is_primary' => 0]);
        }

        $this->db->insert('contacts_record', [
            'record_id'   => $record_id,
            'contact_id'  => $contact_id,
            'is_primary'  => $is_primary,
            'created_date' => date('Y-m-d H:i:s')
        ]);

        // Sync cache if primary
        if ($is_primary) {
            $this->_syncPrimaryContactToRecord($record_id, $contact_id);
        }

        $this->response->output(['flag'=>'S'], 200);
    }
    public function bulkUpsertContacts()
    {
        $this->access->checkTokenKey();
        $payload = json_decode($this->input->raw_input_stream, true);

        $record_id = (int)$payload['record_id'];
        $contacts  = $payload['contacts'] ?? [];

        $this->db->trans_start();
        $userId = $this->input->get_request_header('SadminID', true);
        if (!$userId) $userId = $payload['SadminID'] ?? $this->input->post('SadminID');
        foreach ($contacts as $c) {

            // CASE 1: Existing contact → just map
            if (!empty($c['contact_id'])) {
                $contact_id = (int)$c['contact_id'];
            }
            // CASE 2: New contact → create
            else {
                $this->db->insert('contacts', [
                    'name'        => $c['name'],
                    'company_id'=>$this->company_id,
                    'email'       => $c['email'] ?? null,
                    'mobile'   => $c['mobile'] ?? null,
                    'wa_number'   => $c['wa_number'] ?? null,
                    'created_by' =>$userId,
                    'created_date'=> date('Y-m-d H:i:s')
                ]);
                //print $this->db->last_query();exit;
                $contact_id = $this->db->insert_id();
            }

            // Handle primary
            if (!empty($c['is_primary'])) {
                $this->db->where('record_id', $record_id)
                        ->update('contacts_record', ['is_primary' => 0]);
            }

            // Map
            $this->db->insert('contacts_record', [
                'record_id'  => $record_id,
                'contact_id' => $contact_id,
                'is_primary' => (int)($c['is_primary'] ?? 0)
            ]);

            if (!empty($c['is_primary'])) {
                $this->_syncPrimaryContactToRecord($record_id, $contact_id);
            }
        }
        $this->db->trans_commit();

        $this->response->output(['flag'=>'S'], 200);
    }
    public function getRecordContacts($record_id)
    {
        $this->access->checkTokenKey();

        $this->db->select('
            c.contact_id, c.name, c.email, c.mobile, c.wa_number,c.contact_type,c.contact_type_other,
            rc.is_primary
        ');
        $this->db->from('contacts_record rc');
        $this->db->join('contacts c', 'c.contact_id = rc.contact_id');
        $this->db->where('rc.record_id', $record_id);
        $this->db->order_by('rc.is_primary', 'DESC');

        $rows = $this->db->get()->result_array();

        $this->response->output([
            'flag' => 'S',
            'data' => $rows
        ], 200);
    }
    private function _syncPrimaryContactToRecord($record_id, $contact_id)
    {
        $contact = $this->db
            ->get_where('contacts', ['contact_id' => $contact_id])
            ->row_array();

        if (!$contact) return;

        $this->db->where('customer_id', $record_id)
                ->update('customer', [
                    'mobile_no'    => $contact['mobile'],
                    'wa_number' => $contact['wa_number'],
                    'email'     => $contact['email']
                ]);
    }
    public function unlinkContacts()
    {
        $this->access->checkTokenKey();
        $this->response->decodeRequest();
        $record_id = $this->input->post('record_id');
        $contact_id = $this->input->post('contact_id');
        if(empty($record_id) || empty($contact_id)){
            $status['data'] = array();
            $status['msg'] = $this->systemmsg->getErrorCode(996);
            $status['statusCode'] = 996;
            $status['flag'] = 'F';
            $this->response->output($status, 200);
        }
        $changestatus = $this->CommonModel->deleteMasterDetails('contacts_record', array("record_id"=>$record_id,"contact_id"=>$contact_id));
        if ($changestatus) {
            $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 makePrimary()
    {
        $this->access->checkTokenKey();
        $this->response->decodeRequest();
        $record_id = $this->input->post('record_id');
        $contact_id = $this->input->post('contact_id');
        if(empty($record_id) || empty($contact_id)){
            $status['data'] = array();
            $status['msg'] = $this->systemmsg->getErrorCode(996);
            $status['statusCode'] = 996;
            $status['flag'] = 'F';
            $this->response->output($status, 200);
        }
        $changestatus = $this->CommonModel->updateMasterDetails('contacts_record',array("is_primary"=>0),array("record_id"=>$record_id));
        $changestatus = $this->CommonModel->updateMasterDetails('contacts_record',array("is_primary"=>1),array("record_id"=>$record_id,"contact_id"=>$contact_id));
        if ($changestatus) {
            $this->_syncPrimaryContactToRecord($record_id, $contact_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);
        }
    }
}