<?php	
	defined('BASEPATH') or exit('No direct script access allowed');	
	use Curl\Curl;
	
	class Promo extends CI_Controller	
	{		
		public function __construct()		
		{			
			parent::__construct();		
			cek_session_login();
			$this->load->model("model_promo");
			$this->perPage = 10; 		
			$this->iduser = $this->session->idu;
			$this->title = info()['title'];
			$this->curl = new Curl();
		}		
		
		public function panel()
		{
			cek_menu_akses();
			cek_crud_akses(8);
			$data['title'] ='Kirim Promo| '.$this->title;
			$data['promo'] = $this->model_promo->get_promo();
			$data['template_cards'] = $this->model_promo->get_template_cards();
			$data['report_count'] = $this->db->count_all('report');
			$data['member_levels'] = $this->model_promo->get_member_levels();
			$data['device'] = get_device();
			// $data['status'] = $this->cek_status();
			$this->template->load('main/themes','promo/kirim_promo',$data);
			
		}
		
		/**
			* load_device
			*
			* @param  mixed $param
			* @return void
		*/
		public function load_device()
		{
			$load = $this->model_app->views('device')->result();
			foreach($load AS $row)
			{
				$response[] = array("id"=>encrypt_url($row->token),"name"=>$row->device);
			}
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($response));
		}
		
		public function report()
		{
			cek_menu_akses();
			cek_crud_akses(8);
			$data['title'] ='Report Promo| '.$this->title;
			$this->template->load('main/themes','promo/report',$data);
			
		}
		
		public function ajaxReport()
		{
			$page = $this->input->post('page');
			if(!$page){ 
				$offset = 0; 
				}else{ 
				$offset = $page; 
			} 
			
			$limits = $this->input->post('limits'); 
			if(!empty($limits)){ 
				$limit = $limits; 
				}else{ 
				$limit = $this->perPage; 
			} 
			// Set conditions for search and filter 
			$keywords = $this->input->post('keywords'); 
			$sortBy = $this->input->post('sortBy'); 
			$statusFilter = $this->input->post('statusFilter');
			if(!empty($keywords)){ 
				$conditions['search']['keywords'] = $keywords; 
			} 
			if(!empty($sortBy)){ 
				$conditions['search']['sortBy'] = $sortBy; 
			} 
			if($statusFilter !== null && $statusFilter !== '') $conditions['search']['status'] = $this->db->escape_str($statusFilter);
			
			$conditions['returnType'] = 'count'; 
			$totalRec = $this->model_promo->getReport($conditions); 
			
			// Pagination configuration 
			$config['target']      = '#data_report'; 
			$config['base_url']    = base_url('promo/ajaxReport'); 
			$config['total_rows']  = $totalRec; 
			$config['per_page']    = $limit; 
			$config['link_func']   = 'search_LaporanGrup'; 
			
			// Initialize pagination library 
			$this->ajax_pagination->initialize($config); 
			// Get records 
			$conditions['start'] = $offset; 
			$conditions['limit'] = $limit;
			unset($conditions['returnType']); 
			
			$data['result'] = $this->model_promo->getReport($conditions); 
			$data['offset'] = $offset;
			$data['pagination'] = $this->ajax_pagination->create_links();
			$data['stats'] = ['total'=>0,'success'=>0,'delivered'=>0,'read'=>0,'failed'=>0];
			$statFields = 'status'.($this->db->field_exists('state', 'report') ? ',state' : '');
			foreach ($this->db->select($statFields)->get('report')->result() as $statRow) {
				$data['stats']['total']++;
				$statusRaw = strtolower(trim((string) $statRow->status));
				$stateRaw = strtolower(trim((string) ($statRow->state ?? '')));
				$rank = ['0'=>0,'pending'=>10,'waiting'=>20,'processing'=>30,'1'=>40,'sent'=>40,'2'=>50,'delivered'=>50,'3'=>60,'read'=>60];
				$statusValue = (($rank[$statusRaw] ?? 0) > ($rank[$stateRaw] ?? 0)) ? $statusRaw : ($stateRaw !== '' ? $stateRaw : $statusRaw);
				if ($statusValue === '2' || $statusValue === 'delivered') $data['stats']['delivered']++;
				if ($statusValue === '3' || $statusValue === 'read') $data['stats']['read']++;
				if (in_array($statusValue, ['1','2','3','sent','delivered','read','success','true','done','berhasil'], true)) $data['stats']['success']++;
				if (in_array($statusValue, ['0','failed','gagal','false','error','invalid','expired','url unreachable'], true)) $data['stats']['failed']++;
			}
			// dump($data['result']);
			$this->load->view('promo/ajax-report', $data, false); 
		}
		
		public function hapus_report(){
			$id = decrypt_url($this->input->post('id'));
			$konsumen = decrypt_url($this->input->post('konsumen'));
			
			$delete = $this->model_promo->delete_report($id,$konsumen);
			
			if ($delete == true) {
				$result = array('status' => 200, 'msg' => 'Data berhasil dihapus');
				} else {
				$result = array('status' => 400, 'msg' => 'Data gagal dihapus');
			}
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($result));
		}
		
		public function cek_status(){
			$token = decrypt_url($this->input->post('token'));
			$result = $this->fonnte('https://api.fonnte.com/device',$token);
			if($result['status']==true){
				if($result['msg']->status==true){
					$data = $result['msg'];
					}else{
					$data = $result['msg'];
				}
			}
			if($result['status']==false){
				$data = ['status'=>false,'msg'=>$result['msg']];
			}
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($data));
		}
		
		public function template(){
			cek_crud_akses(8);
			$data['title'] ='Template promo | '.$this->title;
			$this->template->load('main/themes','promo/template',$data);
			$this->load->view('promo/media');
		}
		
		public function data_template()
		{
			cek_crud_akses(8);
			$data['record'] = $this->model_app->view_where_ordering('template_promo',array(),'id','DESC')->result();
			$this->load->view('promo/data_template',$data);
		}
		
		public function get_template()
		{
			
			if ( $this->input->is_ajax_request() )
			{
				cek_crud_akses(8,'json');
				$id = $this->db->escape_str($this->input->post('id'));
				
				if($id > 0){
					$row = $this->model_app->view_where('template_promo',['id'=>$id])->row(); 
					
					$result = ['status'=>true,
					'id'=>$id,
					'title'=>$row->title,
					'deskripsi'=>$row->deskripsi,
					'status_pesan'=>$row->status,
					'jenis_pesan'=>$row->jenis_pesan,
					'publish'=>$row->active,
					'msg'=>'',
					'readonly'=>false,
					'disabled'=>false
					];
					
					}else{
					
					$result = ['status'=>true,
					'id'=>0,
					'title'=>'',
					'deskripsi'=>'',
					'status_pesan'=>0,
					'jenis_pesan'=>0,
					'publish'=>'Y',
					'modal_title'=>'Form Input',
					'msg'=>'',
					'readonly'=>false,
					'disabled'=>false
					];
				}
				
				}else{
				$result = ['status'=>false];
			}
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($result));
		}	
		
		
		public function save_template()
		{
			if ( $this->input->is_ajax_request() )
			{
				$id = $this->db->escape_str($this->input->post('id'));
				$type = $this->db->escape_str($this->input->post('type'));
				$title = $this->db->escape_str($this->input->post('title'));
				$deskripsi = $this->input->post('deskripsi');
				$active = $this->input->post('publish');
				$status = $this->input->post('status');
				$jenis_pesan = $this->input->post('jenis_pesan');
				
				$this->form_validation->set_rules(array(array(
				'field' => 'title',
				'label' => 'Title',
				'rules' => 'required|trim',
				'errors' => array(
				'required' => '%s. Harus di isi'
				)
				)));
				
				$this->form_validation->set_rules(array(array(
				'field' => 'deskripsi',
				'label' => 'Deskripsi',
				'rules' => 'required|trim',
				'errors' => array(
				'required' => '%s. Harus di isi'
				)
				)));
				
				if ($this->form_validation->run())
				{
					if($jenis_pesan==1){
						$media = $this->input->post('media');
						$a = explode('/', $media);
						$filename = $a[count($a) - 1];
						$a2 = explode('.', $filename);
						$namefile = $a2[count($a2) - 2];
						$filetype = $a2[count($a2) - 1];
						$getstorage = $this->db->get_where('storage', ['namafile' => $filename])->row();
						$filename = $getstorage->nama_original;
						}else{
						$media = '';
						$filename = '';
						$filetype = '';
					}
					
					if($type=='add'){
						simpan_demo('Simpan');
						cek_crud_akses(7,'json');
						$param = [
						'title'=>$title,
						'deskripsi'=>$deskripsi,
						'status'=>$status,
						'jenis_pesan'=>$jenis_pesan,
						'active'=>$active,
						'url' => $media,
						'filename' =>$filename,
						'filetype' => $filetype,
						'create_date' => today()
						];
						
						$input=  $this->model_app->input('template_promo',$param);
						if($input['status']=='ok'){
							$result = array('status'=>200,'msg'=>'Data berhasil diinput');
							}else{
							$result = array('status'=>false);
						}
					}
					if($type=='edit'  AND $id > 0){
						simpan_demo('Simpan');
						cek_crud_akses(9,'json');
						
						$param = [
						'title'=>$title,
						'deskripsi'=>$deskripsi,
						'status'=>$status,
						'jenis_pesan'=>$jenis_pesan,
						'active'=>$active,
						'url' => $media,
						'filename' =>$filename,
						'filetype' => $filetype
						];
						
						$update = $this->model_app->update('template_promo',$param,['id'=>$id]);
						if($update['status']=='ok')
						{
							$result = ['status'=>200,'msg'=>'Berhasil'];
							}else{
							$result = ['status'=>false,'msg'=>'Gagal'];
						}
					}
				}
				else 
				{
					
					$result['status'] = 'error';
					$result['alert']['type'] = 'error';
					$result['alert']['content'] = validation_errors();
				}
				if($type=='hapus' AND $id > 0){
					simpan_demo('Hapus');
					cek_crud_akses(10,'json');//delete
					$cek = $this->model_app->view_where('template_promo',array('id' => $id));
					if($cek->num_rows() > 0){
						$res=$this->model_app->hapus('template_promo',array('id' => $id));
						if($res['status']=='ok'){
							$result = array('status'=>200,'msg'=>'Data berhasil dihapus');
							}else{
							$result = array('status'=>400,'msg'=>'Data gagal dihapus');
						}
						}else{
						$result = array('status'=>400,'msg'=>'Data tidak ditemukan');
					}
				}
				}else{
				$result = ['status'=>false];
			}
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($result));
		}
		
		private function fonnte($url,$token)
		{
			$this->curl->setOpt(CURLOPT_SSL_VERIFYPEER, false);
			$this->curl->setDefaultJsonDecoder($assoc = true);
			$this->curl->setHeader('Authorization', $token);
			$this->curl->setHeader('Content-Type', 'application/json');
			$this->curl->post($url);
			if ($this->curl->error) {
				$result = ['status'=>false,'msg'=>$this->curl->errorMessage];
				} else {
				$result = ['status'=>true,'msg'=>(object)$this->curl->response];
			}
			return $result;
		}
		
		public function cek_paket(){
			$token = decrypt_url($this->input->post('token'));
			$result = $this->fonnte('https://api.fonnte.com/device',$token);
			if($result['status']==true){
				if($result['msg']->status==true){
					$data = $result['msg'];
					}else{
					$data = $result['msg'];
				}
			}
			if($result['status']==false){
				$data = ['status'=>false,'msg'=>$result['msg']];
			}
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($data));
		}
		
		public function cek_paket_promo(){
			$token = $this->get_token()->token;
			$result = $this->fonnte('https://api.fonnte.com/device',$token);
			if($result['status']==true){
				if($result['msg']->status==true){
					$data = $result['msg'];
					}else{
					$data = $result['msg'];
				}
			}
			if($result['status']==false){
				$data = ['status'=>false,'msg'=>$result['msg']];
			}
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($data));
		}
		public function get_token()
		{
			$this->db->select('*');
			$this->db->from('device');
			$this->db->where('device_status','connect');
			$this->db->limit(1);
			$query = $this->db->get(); 
			$result = ($query->num_rows() > 0)?$query->row():FALSE; 
			return $result;
		}	
		public function cek_label(){
			$id = $this->db->escape_str($this->input->post('id'));
			if($id==1){
				$where = ['kunci'=>0];
				}else{
				$where = ['panggilan'=>$id,'kunci'=>0];
			}
			$data = $this->model_promo->total_label($where);
			
			$response =['status'=>true,'total'=>$data];
			
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($response));
		}
		
		public function cek_nomor()
		{
			simpan_demo('Simpan');
			$promo = $this->db->escape_str($this->input->post('promo'));
			$label = $this->db->escape_str($this->input->post('label'));
			
			if($label==1){
				$where = ['kunci'=>0];
				}else{
				$where = ['panggilan'=>$label,'kunci'=>0];
			}
			$total = $this->model_promo->total_label($where);
			if($total > 0){
				$data = $this->model_promo->cek_nomor_bylabel($where);
				$pesan = $this->model_promo->get_promo_byid($promo);
				
				
				if($pesan->jenis_pesan==0){
					$response =[
					'status'=>true,
					'id'=>$data->id,
					'name'=>$data->nama,
					'number'=>$data->no_hp,
					'title'=>$pesan->title,
					'message'=>'',
					'url'=>'',
					'filename'=>'',
					'filetype'=>''
					];
					}else{
					$response =[
					'status'=>true,
					'id'=>$data->id,
					'name'=>$data->nama,
					'number'=>$data->no_hp,
					'title'=>$pesan->title,
					'message'=>'',
					'url'=>$pesan->url,
					'filename'=>$pesan->filename,
					'filetype'=>$pesan->filetype
					];
				}
				
				}else{
				$response =[
				'status'=>false,
				'msg'=>'Nomor tidak ditemukan'
				];
			}
			
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($response));
		}

		public function target_contacts()
		{
			$level = $this->db->escape_str($this->input->post('level', TRUE));
			$contacts = [];
			if ($level !== '') {
				foreach ($this->model_promo->get_target_contacts($level) as $contact) {
					$contacts[] = [
						'id' => (int) $contact->id,
						'nama' => (string) $contact->nama,
						'no_hp' => (string) $contact->no_hp,
						'label' => (string) ($contact->member_title ?: $contact->panggilan ?: 'Regular'),
						'poin' => 0
					];
				}
			}
			$this->output->set_content_type('application/json')->set_output(json_encode([
				'status' => true,
				'contacts' => $contacts
			]));
		}
		
		public function cek_contoh()
		{
			simpan_demo('Simpan');
			$id = $this->db->escape_str($this->input->post('id'));
			
			$pesan = $this->model_promo->get_promo_byid($id);
			
			$nama = 'Jhon';
			$panggilan = 'Mas';
			
			$searchVal = array(
			"{perusahaan}",
			"{web}",
			"{selamat}",
			"{hp}",
			"{email}",
			"{alamat}",
			"{nama}",
			"{panggilan}"
			);
			
			// Array containing replace string from  search string
			$replaceVal = array(
			info()['perusahaan'],
			base_url(),
			ucapan(),
			hp62(info()['phone']),
			info()['email'],
			strip_word_html(base64_decode(info()['deskripsi'])),
			$nama,
			$panggilan
			);
			$msg = str_replace($searchVal, $replaceVal, $pesan->deskripsi);
			$response =[
			'status'=>true,
			'name'=>$nama,
			'number'=>info()['phone'],
			'title'=>$pesan->title,
			'message'=>$msg,
			'template'=>(string) $pesan->deskripsi,
			'replacements'=>[
				'nama_toko'=>(string) info()['perusahaan'],
				'telepon_toko'=>(string) hp62(info()['phone']),
				'perusahaan'=>(string) info()['perusahaan'],
				'hp'=>(string) hp62(info()['phone']),
				'selamat'=>(string) ucapan()
			],
			'url'=>'',
			'filename'=>'',
			'filetype'=>''
			];
			
			
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($response));
		}
		
		public function kirim_pesan()
		{
			simpan_demo('Simpan');
			$token = decrypt_url($this->input->post('device'));
			$format_pesan = $this->db->escape_str($this->input->post('format_pesan'));
			$promo = $this->db->escape_str($this->input->post('promo'));
			// Safe mode server-side: klien tidak dapat menurunkan jeda di bawah 5 detik.
			$delay = max(5, min(15, (int) $this->input->post('delay')));
			$optout = ((int) $this->input->post('optout') === 1);
			$message_template = (string) $this->input->post('message_template', FALSE);
			
			$nomor_tujuan = $this->db->escape_str($this->input->post('number'));
			$schedule = $this->input->post('schedule');
			$device = $token ? $this->model_app->view_where('device', ['token'=>$token])->row() : null;
			if (!$device || $nomor_tujuan === '' || !preg_match('/^[0-9+\-\s()]{8,25}$/', $nomor_tujuan)) {
				return $this->promo_send_response(false, 'Device WhatsApp atau nomor penerima tidak valid.');
			}
			
			$data = $this->model_promo->get_contact_for_promo($nomor_tujuan);
			$pesan = $this->model_promo->get_promo_byid($promo);
			if (!$data || !$pesan) return $this->promo_send_response(false, 'Kontak atau template promo tidak ditemukan.');
			
			$nama = cekKonsumen($data->id)['nama'];
			$panggilan = cekKonsumen($data->id)['panggilan'];
			
			$member_title = member((int) cek_member($data->id));
			$searchVal = array(
			"{perusahaan}",
			"{web}",
			"{selamat}",
			"{hp}",
			"{email}",
			"{alamat}",
			"{nama}",
			"{panggilan}",
			"{level_member}",
			"{poin}",
			"{nama_toko}",
			"{telepon_toko}"
			);
			
			// Array containing replace string from  search string
			$replaceVal = array(
			info()['perusahaan'],
			base_url(),
			ucapan(),
			hp62(info()['phone']),
			info()['email'],
			strip_word_html(base64_decode(info()['deskripsi'])),
			$nama,
			$panggilan,
			$member_title,
			'0',
			info()['perusahaan'],
			hp62(info()['phone'])
			);
			
			// Function to replace string
			$template_text = trim($message_template) !== '' ? $message_template : $pesan->deskripsi;
			$msg = str_replace($searchVal, $replaceVal, $template_text);
			// Spintax diacak ulang pada setiap request/penerima.
			$msg = $this->resolve_spintax($msg, (string) $promo);
			if ($optout) {
				$msg = rtrim($msg)."\n\n_Balas STOP untuk berhenti menerima promo_";
			}
			if (trim(strip_tags($msg)) === '') {
				return $this->promo_send_response(false, 'Isi pesan promosi tidak boleh kosong.');
			}
			
			if($format_pesan==0){
				$_schedule = 0;
				}else{
				$min=1;
				$max=59;
				$var2 =  rand($min,$max);
				$_delay = sprintf('%02s', $var2);
				if (!$schedule) return $this->promo_send_response(false, 'Jadwal pengiriman belum diisi.');
				try { $dateTime = new DateTime($schedule); }
				catch (Exception $e) { return $this->promo_send_response(false, 'Format jadwal pengiriman tidak valid.'); }
				$timeIn24HourFormat = $dateTime->format('Y-m-d H:i:'.$_delay);
				$_schedule = strtotime($timeIn24HourFormat);
			}
			
			if($pesan->jenis_pesan==0){
				
				$isi_pesan = $msg;
				$url       = '';
				$filename  = '';
				}else{
				$isi_pesan = $msg;
				$url       = $pesan->url;
				$filename  = $pesan->filename;
				
			}
			
			$data_send = array(
			'target' => $nomor_tujuan,
			'message' => $isi_pesan,
			'url' => $url,
			'filename' => $filename,
			'schedule' => $_schedule,
			'typing' => false,
			'delay' => $delay,
			'countryCode' => '62'
			);
			
			// Fonnte mengirim perubahan sent/delivered/read melalui webhook status
			// yang tersimpan di konfigurasi device, bukan parameter endpoint /send.
			$webhookRegistration = $this->register_status_webhook($token);
			if (empty($webhookRegistration['status'])) {
				error_log('Fonnte promo webhook registration failed: '.($webhookRegistration['msg'] ?? 'unknown error'));
			}
			$this->curl->setOpt(CURLOPT_SSL_VERIFYPEER, false);
			$this->curl->setDefaultJsonDecoder($assoc = true);
			$this->curl->setHeader('Authorization', $token);
			// Endpoint /send membaca field form. Header JSON pada array PHP membuat
			// gateway membalas "invalid/empty body value" karena body tidak terbaca.
			$this->curl->setHeader('Content-Type', 'application/x-www-form-urlencoded');
			$this->curl->post('https://api.fonnte.com/send', http_build_query($data_send));
			if ($this->curl->error) return $this->promo_send_response(false, $this->curl->errorMessage);
			$response = is_array($this->curl->response) ? $this->curl->response : (array) $this->curl->response;
			if (empty($response['status'])) {
				$message = $response['reason'] ?? $response['message'] ?? 'Pengiriman ditolak oleh Fonnte.';
				return $this->promo_send_response(false, $message);
			}
			if (empty($response['id'])) {
				return $this->promo_send_response(false, 'Fonnte tidak mengembalikan ID pengiriman.');
			}
			$response['id'] = is_array($response['id']) ? $response['id'] : [$response['id']];
			if (empty($response['target'])) $response['target'] = [$nomor_tujuan];
			$saved = $this->report_pesan($response,$isi_pesan,$data->id,$token);
			if ($saved < 1) return $this->promo_send_response(false, 'Pesan diterima Fonnte, tetapi riwayat pengiriman gagal disimpan.');
			return $this->promo_send_response(true, 'Pesan masuk antrean Fonnte.', [
				'provider'=>$response,
				'rendered_message'=>$isi_pesan,
				'tracking'=>[
					'active'=>!empty($webhookRegistration['status']),
					'message'=>(string) ($webhookRegistration['msg'] ?? '')
				]
			]);
		}

		private function resolve_spintax($message, $scope = '')
		{
			$position = 0;
			return preg_replace_callback('/\{([^{}|]+(?:\|[^{}]+)+)\}/u', function ($matches) use ($scope, &$position) {
				$options = array_values(array_filter(array_map('trim', explode('|', $matches[1])), 'strlen'));
				if (count($options) < 2) return $matches[0];
				$key = 'promo_spintax_'.sha1($scope.'|'.$position++.'|'.$matches[1]);
				$last = (string) $this->session->userdata($key);
				$available = array_values(array_filter($options, function ($option) use ($last) { return $option !== $last; }));
				if (empty($available)) $available = $options;
				$choice = $available[random_int(0, count($available) - 1)];
				$this->session->set_userdata($key, $choice);
				return $choice;
			}, (string) $message);
		}

		private function promo_send_response($status, $message, array $extra = [])
		{
			$this->output->set_content_type('application/json')->set_output(json_encode(array_merge([
				'status'=>(bool)$status,
				'msg'=>$message
			], $extra)));
			return;
		}
		
		private function report_pesan($response,$message,$id_konsumen,$token = '')
		{
			$this->ensure_report_tracking();
			$inserted = 0;
			$deviceNumber = '';
			if ($token !== '') {
				$deviceRow = $this->model_app->view_where('device', ['token' => $token])->row();
				$deviceNumber = !empty($deviceRow) ? (string) $deviceRow->device : '';
			}
			if ($deviceNumber === '') $deviceNumber = (string) get_device();
			$targets = is_array($response['target'] ?? null) ? $response['target'] : [($response['target'] ?? '')];
			foreach((array) $response["id"] as $k=>$v){
				$target = $targets[$k] ?? $targets[0] ?? '';
				$process = is_array($response["process"] ?? null) ? ($response["process"][$k] ?? 'waiting') : ($response["process"] ?? 'waiting');
				$status = !empty($response["status"]);
				$data = ['id_kirim'=>$v,'id_konsumen'=>$id_konsumen,'device'=>$deviceNumber,'target'=>$target,'message'=>$message,'status'=>strtolower(trim((string) $process)),'create_date'=>date('Y-m-d H:i:s')];
				if($status==true){
					if ($this->model_promo->insert_report($data)) $inserted++;
				}
			}
			return $inserted;
		}

		private function ensure_report_tracking()
		{
			$this->load->dbforge();
			// Skema lama hanya memberi UNIQUE pada id. Tanpa AUTO_INCREMENT,
			// respons kirim sukses tetapi baris riwayat promo gagal disimpan.
			$idColumn = $this->db->query("SHOW COLUMNS FROM `report` LIKE 'id'")->row_array();
			if (!empty($idColumn) && stripos((string) ($idColumn['Extra'] ?? ''), 'auto_increment') === false) {
				$this->db->query('ALTER TABLE `report` MODIFY `id` INT(11) NOT NULL AUTO_INCREMENT');
			}
			if (!$this->db->field_exists('id_konsumen', 'report')) $this->dbforge->add_column('report', ['id_konsumen'=>['type'=>'INT','constraint'=>11,'null'=>true,'after'=>'id_kirim']]);
			if (!$this->db->field_exists('state', 'report')) $this->dbforge->add_column('report', ['state'=>['type'=>'VARCHAR','constraint'=>30,'null'=>true,'after'=>'status']]);
			if (!$this->db->field_exists('stateid', 'report')) $this->dbforge->add_column('report', ['stateid'=>['type'=>'VARCHAR','constraint'=>100,'null'=>true,'after'=>'state']]);
			if (!$this->db->field_exists('create_date', 'report')) {
				$this->dbforge->add_column('report', ['create_date'=>['type'=>'DATETIME','null'=>true,'after'=>'stateid']]);
			} else {
				$column = $this->db->query("SHOW COLUMNS FROM `report` LIKE 'create_date'")->row_array();
				if (!empty($column) && strtolower((string) $column['Type']) === 'date') $this->db->query('ALTER TABLE `report` MODIFY `create_date` DATETIME NULL');
			}
		}

		private function register_status_webhook($token)
		{
			$callbackUrl = base_url('fonnte/status-callback');
			$host = strtolower((string) parse_url($callbackUrl, PHP_URL_HOST));
			if (strtolower((string) parse_url($callbackUrl, PHP_URL_SCHEME)) !== 'https' || $host === 'localhost' || substr($host, -5) === '.test' || filter_var($host, FILTER_VALIDATE_IP)) return ['status'=>false,'msg'=>'Callback memerlukan domain HTTPS publik.'];
			// Versi key dipisahkan agar deployment yang sempat memakai URL callback
			// lain wajib mendaftarkan ulang endpoint stabil pada pengiriman pertama.
			$sessionKey = 'promo_fonnte_webhook_v2_'.sha1($token.'|'.$callbackUrl);
			$registeredAt = (int) $this->session->userdata($sessionKey);
			if ($registeredAt > 0 && (time() - $registeredAt) < 3600) return ['status'=>true,'msg'=>'Webhook status sudah aktif.'];
			$deviceResult = $this->fonnte('https://api.fonnte.com/device', $token);
			if (empty($deviceResult['status']) || empty($deviceResult['msg']->status)) return ['status'=>false,'msg'=>'Data device Fonnte tidak dapat dibaca.'];
			$post = ['name'=>(string)$deviceResult['msg']->name,'device'=>(string)$deviceResult['msg']->device,'webhookstatus'=>$callbackUrl];
			$ch = curl_init('https://api.fonnte.com/update-device');
			curl_setopt_array($ch,[CURLOPT_RETURNTRANSFER=>true,CURLOPT_POST=>true,CURLOPT_POSTFIELDS=>$post,CURLOPT_HTTPHEADER=>['Authorization: '.$token],CURLOPT_CONNECTTIMEOUT=>8,CURLOPT_TIMEOUT=>20,CURLOPT_SSL_VERIFYPEER=>true]);
			$body=curl_exec($ch); $error=curl_error($ch); $httpCode=(int)curl_getinfo($ch,CURLINFO_HTTP_CODE); curl_close($ch);
			$response=json_decode((string)$body,true); $ok=$error==='' && $httpCode>=200 && $httpCode<300 && is_array($response) && !empty($response['status']);
			if ($ok) $this->session->set_userdata($sessionKey, time());
			return ['status'=>$ok,'msg'=>$ok?'Webhook status aktif.':($error!==''?$error:($response['reason']??'Fonnte menolak konfigurasi webhook.'))];
		}
		
		public function pesan_terkirim()
		{
			$type = $this->db->escape_str($this->input->post('type'));
			$number = $this->db->escape_str($this->input->post('number'));
			
			$pesan = $this->model_promo->update_konsumen(['kunci'=>2],['no_hp'=>$number]);
			if($pesan==true){
				$response =['status'=>true,'msg'=>'Sukses update'];
				}else{
				$response =['status'=>false,'msg'=>'Gagal update'];
			}
			
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($response));
		}
		
		
		public function pesan_gagal()
		{
			$type = $this->db->escape_str($this->input->post('type'));
			$number = $this->db->escape_str($this->input->post('number'));
			
			$pesan = $this->model_promo->update_konsumen(['kunci'=>3],['no_hp'=>$number]);
			if($pesan==true){
				$response =['status'=>true,'msg'=>'Sukses update'];
				}else{
				$response =['status'=>false,'msg'=>'Gagal update'];
			}
			
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($response));
		}
		
		
		public function reset_promo()
		{
			 
			$pesan = $this->model_promo->update_konsumen(['kunci'=>0],['kunci >'=>1]);
			if($pesan==true){
				$response =['status'=>true,'msg'=>'Sukses update'];
				}else{
				$response =['status'=>false,'msg'=>'Gagal update'];
			}
			
			$this->output
			->set_content_type('application/json')
			->set_output(json_encode($response));
		}
		
		public function get_media()
		{
			$media = $this->db->query('SELECT * FROM storage ORDER BY id DESC')->result();
			echo '<div class="row">';
			foreach ($media as $m) {
				if (preg_match('/.pdf/', $m->namafile)) {
					$namafile = 'pdf.png';
					} else {
					$namafile = $m->namafile;
				}
				$bb = _storage() .$m->namafile;
				echo '  <div class="col-6 col-xl-2 col-lg-3 col-md-4 col-sm-4">
				<a href="javascript:void(0)" style="text-decoration: none; color: black" data-dismiss="modal" onclick="getmedia(' . "'$bb'" . ')">
				<div class="card">
				<img src="' . base_url('uploads/whatsapp/') . $namafile . '" class="card-img-top" style="max-height: 8rem; min-height: 8rem; object-fit: cover;">
				<div class="card-body p-1 text-center">
				<small style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">' . $m->nama_original . '</small>
				</div>
				</div>
				</a>
				</div>';
			}
			echo '</div>';
		}
		
		public function upload()
		{
			// echo FCPATH;
			
			$img = uploadimg([
			'path' => FCPATH."/uploads/whatsapp/",
			'name' => 'fileupload',
			'compress' => false
			]);
			if ($img['result'] == 'success') {
				$this->db->insert('storage', [
				'namafile' => $img['nama_file'],
				'nama_original' => $_FILES['fileupload']['name']
				]);
				echo 'berhasil';
				} else {
				echo 'Hanya File pdf | jpeg | jpg | png yang diizinkan';
			}
		}
	}																																																																																																																																																										
