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

class UserController extends CI_Controller {

    public function __construct(){
        
		parent::__construct();
		
		$this->load->helper('email'); 
		$this->load->helper('common'); 
		$this->load->model('common_model');
		$this->load->library('razorpay');
		
		$this->output
             ->set_content_type('application/json', 'utf-8')
             ->set_header('Access-Control-Allow-Origin: *')
             ->set_header('Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE')
             ->set_header('Access-Control-Allow-Headers: Content-Type, Authorization');
			 
        $api_auth= $this->db->get('tbl_api_auth')->row_array();
		if(isset($_SERVER['PHP_AUTH_USER']) and isset($_SERVER['PHP_AUTH_PW'])){
			if(($_SERVER['PHP_AUTH_USER'] != $api_auth['username']) || ($_SERVER['PHP_AUTH_PW'] != $api_auth['password']))
			{
				outputJSON(400, 'error', 'Authentication failed');
				return;
			}
	    }else{
			outputJSON(400, 'error', 'Authentication Username and password not set');
			return;
		}
 
    }
	
	
	public function update_profile()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required|integer'],
			['field' => 'name', 'label' => 'Name', 'rules' => 'required'],
			['field' => 'email', 'label' => 'Email', 'rules' => 'required|trim|valid_email'],
			['field' => 'mobile', 'label' => 'Mobile', 'rules' => 'required|trim|exact_length[10]|numeric'],
		];

		checkValidation($input, $rules);
		$check=$this->db->where(['mobile_no'=>$input['mobile'],'id!='=>$input['user_id']])->get('tbl_user')->num_rows();
		if($check>0){
			outputJSON(200, 'error', 'Mobile number already linked with another account.');
			return;
		}
		$check=$this->db->where(['email_id'=>$input['email'],'id!='=>$input['user_id']])->get('tbl_user')->num_rows();
		if($check>0){
			outputJSON(200, 'error', 'Email already linked with another account.');
			return;
		}
		$data = [
			'f_name' => $input['name'],
			'email_id' => $input['email'],
			'mobile_no' => $input['mobile'],
		];
		
		$res = $this->common_model->Update('tbl_user', $data, ['id' => $input['user_id']]);
		if ($res) {
			outputJSON(200, 'success', 'Profile updated successfully.');
		} else {
			outputJSON(200, 'error', 'Failed to update profile.');
		}
		
	}
    
	public function my_profile()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required|integer']
		];

		checkValidation($input, $rules);
		$check=$this->db->where('id',$input['user_id'])->where('delete_status', 'false')->get('tbl_user');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$res=$check->row();
		$data = [
			'id' => $res->id,
			'user_id' => $res->user_id,
			'name' => $res->f_name,
			'mobile' => $res->mobile_no,
			'email' => $res->email_id,
			'wallet_amount' => $res->wallet_amount,
			'privacy_policy' => 'https://gotejaga.com/',
			'terms_conditions' => 'https://gotejaga.com/',
			'about_us' => 'https://gotejaga.com/',
		];
		outputJSON(200, 'success', 'Data fetched successfully.',$data);
		
	}
    
	
	public function submit_address()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required|integer'],
			['field' => 'type', 'label' => 'type', 'rules' => 'required'],
			['field' => 'address', 'label' => 'address', 'rules' => 'required|trim'],
			['field' => 'latitude', 'label' => 'latitude', 'rules' => 'required|trim'],
			['field' => 'longitude', 'label' => 'longitude', 'rules' => 'required|trim'],
			['field' => 'edit_id', 'label' => 'edit id', 'rules' => ''],
		];

		checkValidation($input, $rules);
		$check=$this->db->where('id',$input['user_id'])->get('tbl_user')->num_rows();
		if($check==0){
			outputJSON(200, 'error', 'User not found with provided user ID.');
			return;
		}
		$id=$input['edit_id'] ?? null;
		$data = [
			'user_id' => $input['user_id'],
			'type' => $input['type'],
			'address' => $input['address'],
			'latitude' => $input['latitude'],
			'longitude' => $input['longitude'],
			
		];
		if(empty($id)){
			$res = $this->common_model->Insert('users_address', $data);
			if ($res) {
				outputJSON(200, 'success', 'Address updated successfully.');
			} else {
				outputJSON(200, 'error', 'Failed to update address.');
			}
		}else{
			$check=$this->db->where('id',$id)->get('users_address')->num_rows();
			if($check==0){
				outputJSON(200, 'error', 'Address not found with provided Address ID.');
				return;
			}
			$res = $this->common_model->Update('users_address', $data, ['id' => $id]);
			if ($res) {
				outputJSON(200, 'success', 'Address updated successfully.');
			} else {
				outputJSON(200, 'error', 'Failed to update address.');
			}
		}
	}
	
	public function delete_address() {
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'id', 'label' => 'ID', 'rules' => 'required|integer'],
			['field' => 'user_id', 'label' => 'user ID', 'rules' => 'required'],
		];
  
		checkValidation($input, $rules);
		$id=$input['id'];
		$user_id=$input['user_id'];
		$res = $this->common_model->Update('users_address', ['delete_status'=>'true'], ['id' => $id,'user_id'=>$user_id]);
		if($res){
			outputJSON(200, 'success', 'Deleted successfully.');
		}else{
			outputJSON(200, 'error', 'Failed to delete record, please try again.');
		}
    }
    
    public function ssy() {
		echo 'hello ssy';
    }

    public function list_address()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required|integer']
		];

		checkValidation($input, $rules);
		$check=$this->db->where('id',$input['user_id'])->get('tbl_user');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$res=$this->db->select('id,user_id,type,address,latitude,longitude')->where('user_id',$input['user_id'])->where('delete_status','false')->get('users_address')->result();
		outputJSON(200, 'success', 'Data fetched successfully.',$res);
		
	}
	
    public function get_booking_type()
	{
		if (strtoupper($this->input->method()) !== 'GET') {
			outputJSON(405, 'error', 'Invalid request method. Please use GET.');
			return;
		}

		$res=$this->db->select('id,name,booking_type,icon,image')->where('status',1)->get('tbl_booking_mode_auth')->result();
		foreach($res as $row){
			$row->icon=base_url('uploads/'.$row->icon);
			$row->image=base_url('uploads/'.$row->image);
		}
		outputJSON(200, 'success', 'Data fetched successfully.',$res);
		
	}

	public function wallet_history()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required|integer']
		];

		checkValidation($input, $rules);

		$check = $this->db->where('id', $input['user_id'])->get('tbl_user');

		if ($check->num_rows() == 0) {
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}

		$user = $check->row();

		$this->db->where('user_id', $input['user_id']);

		if (!empty($input['transaction_type'])) {
			$this->db->where('transaction_type', $input['transaction_type']); // 'credit' or 'debit'
		}

		if (!empty($input['start_date']) && !empty($input['end_date'])) {
			$this->db->where("DATE(created_at) BETWEEN '{$input['start_date']}' AND '{$input['end_date']}'");
		} elseif (!empty($input['start_date'])) {
			$this->db->where("DATE(created_at) >=", $input['start_date']);
		} elseif (!empty($input['end_date'])) {
			$this->db->where("DATE(created_at) <=", $input['end_date']);
		}

		$page = isset($input['page']) ? (int)$input['page'] : 1;
		$limit = isset($input['limit']) ? (int)$input['limit'] : 10;
		$offset = ($page - 1) * $limit;

		$total_records = $this->db->count_all_results('wallet_transactions', false);
		$this->db->limit($limit, $offset);
		$res = $this->db->get()->result();

		$response = [
			"wallet_amount" => $user->wallet_amount,
			"filters" => [
				[
					"title" => "Transaction Type",
					"value" => "transaction_type",
					"data" => [
						["value" => "credit", "title" => "Credit"],
						["value" => "debit", "title" => "Debit"]
					]
				],
				[
					"title" => "Transaction Date",
					"value" => "transaction_date",
					"data" => [
						["value" => "start_date", "title" => "Start Date"],
						["value" => "end_date", "title" => "End Date"]
					]
				]
			],
			"current_page" => $page,
			"total_pages" => ceil($total_records / $limit),
			"total_records" => $total_records,
			"records_per_page" => $limit,
			"history_list" => $res
		];

		outputJSON(200, "success", "Data fetched successfully.", $response);
	}

	public function payment_gateways()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required|integer']
		];

		checkValidation($input, $rules);
		$check=$this->db->where('id',$input['user_id'])->get('tbl_user');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$res=$this->db->where('status',1)->get('payment_gateways')->result();
		$data=[];
		foreach($res as $row){
			$credentials=json_encode([
				'key'=>$row->gateway_key,
				'secret'=>$row->gateway_secret,
			]);
			$data[]=[
				'id'=>$row->id,
				'icon'=>base_url('uploads/'.$row->icon),
				'name'=>$row->name,
				'value'=>$row->gateway_type,
				'credentials'=>bin2hex($credentials),
			];
		}
		outputJSON(200, 'success', 'Data fetched successfully.',$data);
		
	}
	public function get_rental_data()
	{
		if (strtoupper($this->input->method()) !== 'GET') {
			outputJSON(405, 'error', 'Invalid request method. Please use GET.');
			return;
		}

		$res=$this->db->select('id,km,hrs')->get('tbl_rental_km_hrs')->result();
		outputJSON(200, 'success', 'Data fetched successfully.',$res);
		
	}
    
	public function get_wallet_balance()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required|integer']
		];

		checkValidation($input, $rules);
		$check=$this->db->where('id',$input['user_id'])->get('tbl_user');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$res=$check->row();
		outputJSON(200, 'success', 'Data fetched successfully.',$res->wallet_amount);
		
	}
    
	public function get_vehicle()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

        $json = $this->security->xss_clean(file_get_contents('php://input'));
		$json = preg_replace('/,\s*([\]}])/m', '$1', trim($json));
        $data = json_decode($json);
		$waypoints = $data->waypoints;
		$user_id = $data->user_id ?? null;
		if (empty($user_id)) {
			outputJSON(200, 'error', 'Please enter user ID.');
			return;
		}

        if (empty($waypoints) || count($waypoints) < 2) {
			outputJSON(200, 'error', 'Invalid request. Provide at least pickup and destination locations.');
			return;
		}
		$check=$this->db->where('id',$user_id)->get('tbl_user');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$user=$check->row();
			
		$pickup = $waypoints[0]; // First index is pickup
		$destination = end($waypoints); // Last index is destination
		$stops = array_slice($waypoints, 1, -1); // Middle indexes are stops
		
		$pickup_lat = $pickup->lat;
		$pickup_long = $pickup->long;
		$drop_lat = $destination->lat;
		$drop_long = $destination->long;

		$get_hours = date('H');

		// Query to get vehicle details
		$qry = "SELECT tmp.*, vt.id, vt.image, vt.name, vt.description, vt.type, vt.seat, f.per_km 
				FROM (
					SELECT driver_id,
						ROUND((6371 * ACOS(
							COS(RADIANS(ROUND($pickup_lat,2))) * COS(RADIANS(curr_lat)) *
							COS(RADIANS(curr_long) - RADIANS(ROUND($pickup_long,2))) + 
							SIN(RADIANS(ROUND($pickup_lat,2))) * SIN(RADIANS(curr_lat))
						)), 2) AS distance
					FROM tbl_driver_currentLocation d 
					GROUP BY driver_id
				) AS tmp
				INNER JOIN tbl_driver d ON d.id = tmp.driver_id
				INNER JOIN tbl_vehicle tv ON tv.driver_id = d.id
				INNER JOIN tbl_map_vehicletype dmt ON dmt.vehicle_id = tv.id
				INNER JOIN tbl_vehicletype vt ON vt.id = dmt.type_id
				INNER JOIN tbl_fare f ON f.vehicle_type = vt.id 
				WHERE vt.status = 1 AND d.is_online = 1 AND d.status = 1
				AND tmp.distance <= d.pickup_radius 
				GROUP BY vt.id 
				ORDER BY tmp.distance, f.per_km ASC";

		$result = $this->db->query($qry)->result_array();

		if (!empty($result)) {
			$total_distance = 0;
			if (!empty($stops)) {
				$prev_lat = $pickup_lat;
				$prev_long = $pickup_long;
				
				foreach ($stops as $stop) {
					$total_distance += calculateDistance($prev_lat, $prev_long, $stop->lat, $stop->long);
					$prev_lat = $stop->lat;
					$prev_long = $stop->long;
				}
				$total_distance += calculateDistance($prev_lat, $prev_long, $drop_lat, $drop_long);
			} else {
				$total_distance = calculateDistance($pickup_lat, $pickup_long, $drop_lat, $drop_long);
			}
			
			$timeDisplay=travel_time($total_distance);
			$data=[];
			$con = $this->db->where('status',0)->get('tbl_conv_charge')->row();
			$conv_charge=$con->amt;
			foreach ($result as $row) {
				$fare = round($total_distance * $row['per_km'], 2);
				$netfare = $fare;
				$grand_total = round($conv_charge+$netfare,2);
				// Apply Promo Code Discount
				// if ($row['promo_status'] == 'APPLIED') {
					// $discountfare = round($fare * ($row['promo_code_discount'] / 100), 2);
					// $netfare = round($fare - $discountfare, 2);
				// }

				$data[] = [
					'id' => $row['id'],
					'name' => $row['name'],
					'image' => base_url() . $row['image'],
					'description' => $row['description'],
					'type' => $row['type'],
					'seat' => $row['seat'],
					// 'promocode_status' => $row['promo_status'],
					'distance' => $total_distance.' km',
					'travel_time' => $timeDisplay,
					'fare' => "$fare",
					'conv_charge' => "$conv_charge",
					// 'discount' => $row['promo_code_discount'] . '%',
					// 'net_fare' => "$netfare",
					'grand_total' => "$grand_total",
				];

			}

			outputJSON(200, 'success', 'Data fetched successfully.',['wallet_amount'=>$user->wallet_amount,'vehicle_list'=>$data]);
		} else {
			outputJSON(200, 'error', 'Cabs not found nearby by you.');
			return;
		}
       

		$response['status'] = $status;
		$response['message'] = $message;
		$response['statusCode'] = $statusCode;

		echo json_encode($response);
	}
	
	
    public function save_req_to_driver()
    {
        if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

        $json = $this->security->xss_clean(file_get_contents('php://input'));
		$json = preg_replace('/,\s*([\]}])/m', '$1', trim($json));
        $data = json_decode($json);
		$waypoints = $data->waypoints;
		$user_id = $data->user_id ?? null;
		if (empty($user_id)) {
			outputJSON(200, 'error', 'Please enter user ID.');
			return;
		}

        if (empty($waypoints) || count($waypoints) < 2) {
			outputJSON(200, 'error', 'Invalid request. Provide at least pickup and destination locations.');
			return;
		}
        $check=$this->db->where('id',$input['user_id'])->get('tbl_user');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$vehicle_type_id=$data->vehicle_type_id ?? null;
		$added_by_web=$data->added_by_web ?? null;
		$booking_type=$data->booking_type ?? null;
		
		$pickup = $waypoints[0];
		$destination = end($waypoints); 
		$stops = array_slice($waypoints, 1, -1); 
		
		$pickup_lat = $pickup->lat;
		$pickup_long = $pickup->long;
		$drop_lat = $destination->lat;
		$drop_long = $destination->long;
		
		if($pickup_lat && $pickup_long && $drop_lat && $drop_long && $vehicle_type_id && $booking_type)
		{
			
		    $this->db->where('user_id',$user_id);
		    $this->db->update('tbl_userwise_cabrequest',array('is_latest_request'=>0));
		    
		    $qry="SELECT tmp.*,dmt.type_id,f.per_km,d.f_token_app,TIMESTAMPDIFF(MINUTE,d.accepted_request_time,NOW()) as driverreq_accepted_time FROM(SELECT driver_id,
    	    round(( 6371 * acos( cos( radians(round($pickup_lat,2)) ) * cos( radians(curr_lat) ) *
            cos( radians(curr_long) - radians(round($pickup_long,2)) ) + sin( radians(round($pickup_lat,2)) ) * sin( radians(curr_lat) ) ) )) AS distance
    	    FROM tbl_driver_currentLocation d GROUP BY driver_id) AS tmp
    	    INNER JOIN tbl_driver d ON d.id=tmp.driver_id
    	    INNER JOIN tbl_vehicle tv ON tv.driver_id=d.id
     	    INNER JOIN tbl_map_vehicletype dmt ON dmt.vehicle_id=tv.id
     	    INNER JOIN tbl_fare f ON f.vehicle_type=dmt.type_id
     	    WHERE d.is_online=1 AND d.status=1 AND dmt.type_id=$vehicle_type_id AND tmp.distance <= d.pickup_radius ORDER BY tmp.distance ASC";
	        
		    $result=$this->db->query($qry)->result_array();
		    
		    if(!empty($result))
		    {
		        $total_distance = 0;
				if (!empty($stops)) {
					$prev_lat = $pickup_lat;
					$prev_long = $pickup_long;
					
					foreach ($stops as $stop) {
						$total_distance += calculateDistance($prev_lat, $prev_long, $stop->lat, $stop->long);
						$prev_lat = $stop->lat;
						$prev_long = $stop->long;
					}
					$total_distance += calculateDistance($prev_lat, $prev_long, $drop_lat, $drop_long);
				} else {
					$total_distance = calculateDistance($pickup_lat, $pickup_long, $drop_lat, $drop_long);
				}
    	        $request_id='REQ-'.sprintf("%08d", mt_rand(0, 999999));
    	        
    	        
		        foreach($result as $row)
    	        {
    	           // if($row['driverreq_accepted_time'] > REQUESTEXPIRE_TIME)
    	           // {
        	            $data=array(
        	                 'req_id'=>$request_id,
        	                 'waypoints'=>json_encode($waypoints),
        	                 'user_id'=>$user_id,
        	                 'booking_type'=>$booking_type,
        	                 'driver_id'=>$row['driver_id'],
        	                 'type_id'=>$row['type_id'],
        	                 'driver_away'=>$row['distance'],
        	                 'user_journey_distance'=>$total_distance,
        	                 'per_km_fare'=>$row['per_km'],
        	                 'entry_date'=>date('Y-m-d H:i:s'),
        	                 'added_by_web'=>$added_by_web,
        	                );
        	            $this->db->insert('tbl_userwise_cabrequest',$data);
        	            
        	        $req_id = $this->db->insert_id();
        	        
        	        
        	            
        	           
        	            // if($row['f_token_app'])
        	            // {
            	            //send notification
            	            // $body="You have received a new ride request of pickup locaion ".$pickup_address." from a user .";
            	            // $title="New Ride Request";
            	            // sendNotificationFlutter($row['f_token_app'],$body,$title);
        	            // }
        	            
        	           
    	           // }
    	        }
    	        
    	        
    	        $response['vehicle_type_id']=$vehicle_type_id;
    	        $response['req_id']= $req_id;
				outputJSON(200, 'success', 'Request has been send successfully',$response);
		    }
		    else
		    {
				outputJSON(200, 'error', 'No any driver found near by you.');
				return;
		    }
		}
		else
		{    
            outputJSON(200, 'error', 'Please fill in all required fields.');
			return;
		}
    }
	
	public function add_wallet_balance() {
        if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'user_id', 'rules' => 'required|integer'],
			['field' => 'amount', 'label' => 'amount', 'rules' => 'required']
		];

		checkValidation($input, $rules);
		$amount=$input['amount'];
		$user_id=$input['user_id'];
		$check=$this->db->where('id',$input['user_id'])->get('tbl_user');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		
        $receipt_id = "WADD_" . time().'_'.$user_id;

        $response = $this->razorpay->create_order($amount, $receipt_id);
		if($response['status']=='success'){
			$data=[
				'user_id'=>$user_id,
				'amount'=>$amount,
				'order_id'=>$response['order_id'],
			];
			$this->common_model->Insert('wallet_payments_transactions', $data);
		}
        outputJSON(200, 'success', 'Success',$response);
    }
	
	public function verify_wallet_payment() {
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'user id', 'rules' => 'required'],
			['field' => 'payment_id', 'label' => 'payment_id', 'rules' => 'required'],
			['field' => 'signature', 'label' => 'signature', 'rules' => 'required'],
			['field' => 'order_id', 'label' => 'order_id', 'rules' => 'required']
		];

		checkValidation($input, $rules);
		$user_id=$input['user_id'];
		$order_id=$input['order_id'];
		$payment_id=$input['payment_id'];
		$signature=$input['signature'];
		$check=$this->db->where('id',$user_id)->get('tbl_user');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
        $response = $this->razorpay->verify_payment($order_id, $payment_id, $signature);
		$user=$check->row();
		$closing=$user->wallet_amount;
		if($response['status']=='success'){
			$data=[
				'status'=>'success',
				'payment_id'=>$payment_id,
				'signature'=>$signature
			];
			$res=$this->common_model->Update('wallet_payments_transactions',$data,['order_id'=>$order_id]);
			if($res){
				$payment=$this->db->get_where('wallet_payments_transactions',['order_id'=>$order_id])->row();
				$txnc=$this->db->where('user_id',$user_id)->order_by('id','desc')->get('wallet_transactions');
				if($txnc->num_rows()>0){
					$txn=$txnc->row();
					$opening=$txn->closing_balance;
					$closing=$txn->closing_balance+$payment->amount;
				}else{
					$opening=0;
					$closing=$payment->amount;
				}
				$data=[
					'user_id'=>$user_id,
					'transaction_type'=>'credit',
					'amount'=>$payment->amount,
					'payment_id'=>$payment_id,
					'opening_balance'=>$opening,
					'closing_balance'=>$closing,
					'description'=>'Wallet recharge by razorpay',
				];
				$this->common_model->Insert('wallet_transactions', $data);
				$this->common_model->Update('tbl_user', ['wallet_amount'=>$closing],['id'=>$user_id]);
			}
		}
		$response['wallet_amount']=$closing;
        outputJSON(200, 'success', 'Success',$response);
    }
   
     public function book_cab()
    {
        if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$json = $this->security->xss_clean(file_get_contents('php://input'));
		$json = preg_replace('/,\s*([\]}])/m', '$1', trim($json));
        $data = json_decode($json);
		$waypoints = $data->waypoints ?? null;
		$user_id = $data->user_id ?? null;
		if (empty($user_id)) {
			outputJSON(200, 'error', 'Please enter user ID.');
			return;
		}

        if (empty($waypoints) || count($waypoints) < 2) {
			outputJSON(200, 'error', 'Invalid request. Provide at least pickup and destination locations.');
			return;
		}
        $check=$this->db->where('id',$user_id)->get('tbl_user');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$vehicle_type_id=$data->vehicle_type_id ?? null;
		$added_by_web=$data->added_by_web ?? null;
		$booking_type=$data->booking_type ?? null;
		$payment_mode=$data->payment_mode ?? null;
		$km=$data->kms ?? '';
		$hrs=$data->hrs ?? '';
		$selecteddate=$data->selecteddate ?? '';
		$selectedtime=$data->selectedtime ?? '';
		
		$pickup = $waypoints[0];
		$destination = end($waypoints); 
		$stops = array_slice($waypoints, 1, -1); 
		
		$pickup_lat = $pickup->lat;
		$pickup_long = $pickup->long;
		$drop_lat = $destination->lat;
		$drop_long = $destination->long;
		
		if($pickup_lat && $pickup_long && $drop_lat && $drop_long && $vehicle_type_id && $booking_type && $payment_mode)
		{
			$this->db->where('user_id',$user_id);
		    $this->db->update('tbl_userwise_cabrequest',array('is_latest_request'=>0));
		    
		    $qry="SELECT tmp.*,dmt.type_id,f.per_km,d.f_token_app,TIMESTAMPDIFF(MINUTE,d.accepted_request_time,NOW()) as driverreq_accepted_time FROM(SELECT driver_id,
    	    round(( 6371 * acos( cos( radians(round($pickup_lat,2)) ) * cos( radians(curr_lat) ) *
            cos( radians(curr_long) - radians(round($pickup_long,2)) ) + sin( radians(round($pickup_lat,2)) ) * sin( radians(curr_lat) ) ) )) AS distance
    	    FROM tbl_driver_currentLocation d GROUP BY driver_id) AS tmp
    	    INNER JOIN tbl_driver d ON d.id=tmp.driver_id
    	    INNER JOIN tbl_vehicle tv ON tv.driver_id=d.id
     	    INNER JOIN tbl_map_vehicletype dmt ON dmt.vehicle_id=tv.id
     	    INNER JOIN tbl_fare f ON f.vehicle_type=dmt.type_id
     	    WHERE d.is_online=1 AND d.status=1 AND dmt.type_id=$vehicle_type_id AND tmp.distance <= d.pickup_radius ORDER BY tmp.distance ASC";
	        
		    $result=$this->db->query($qry)->result_array();
		    
		    if(!empty($result))
		    {
		        $total_distance = 0;
				if (!empty($stops)) {
					$prev_lat = $pickup_lat;
					$prev_long = $pickup_long;
					
					foreach ($stops as $stop) {
						$total_distance += calculateDistance($prev_lat, $prev_long, $stop->lat, $stop->long);
						$prev_lat = $stop->lat;
						$prev_long = $stop->long;
					}
					$total_distance += calculateDistance($prev_lat, $prev_long, $drop_lat, $drop_long);
				} else {
					$total_distance = calculateDistance($pickup_lat, $pickup_long, $drop_lat, $drop_long);
				}
				$travel_time=travel_time($total_distance);
				$prkm = $this->db->where('vehicle_type',$vehicle_type_id)->get('tbl_fare')->row();
				$per_km=$prkm->per_km ?? 0;
				$con = $this->db->where('status',0)->get('tbl_conv_charge')->row();
				$conv_charge=$con->amt;
				if($booking_type=='rental'){
					$total_fare=round($per_km*$km);
				}else{
					$total_fare=round($per_km*$total_distance);
				}
				$grand_total=round($conv_charge+$total_fare);
				$booking_id = 'Book-'.$user_id.'-' . time();
				$user=$check->row();
				if($payment_mode=='wallet'){
					if($user->wallet_amount<$grand_total){
						outputJSON(200, 'error', 'Insufficient balance, please add balance in wallet');
						return;
					}
				}
				$data=array(
					'book_id'=>$booking_id,
					'user_id'=>$user_id,
					'booking_type'=>$booking_type,
					'kms'=>$km,
					'hours'=>$hrs,
					'selecteddate'=>$selecteddate,
					'selectedtime'=>$selectedtime,
					'waypoints'=>json_encode($waypoints),
					'type_id'=>$vehicle_type_id,
					'user_journey_distance'=>$total_distance,
					'travel_time'=>$travel_time,
					'per_km_fare'=>$per_km,
					'total_fare'=>$total_fare,
					'grand_total'=>$grand_total,
					'conv_charge'=>$conv_charge,
					'ride_status'=>0,
					'payment_status'=>0,
					'paymenttype'=>$payment_mode,
					'entry_date'=>date('Y-m-d H:i:s'),
					'added_by_web'=>$added_by_web,
				);
				
				$res=$this->db->insert('tbl_booking',$data);
				if($res){
					if($payment_mode=='wallet'){
						$txnc=$this->db->where('user_id',$user_id)->order_by('id','desc')->get('wallet_transactions');
						if($txnc->num_rows()>0){
							$txn=$txnc->row();
							$opening=$txn->closing_balance;
							$closing=$txn->closing_balance-$grand_total;
						}else{
							$opening=0;
							$closing=$grand_total;
						}
						$data=[
							'user_id'=>$user_id,
							'transaction_type'=>'debit',
							'amount'=>$grand_total,
							'payment_id'=>$booking_id,
							'opening_balance'=>$opening,
							'closing_balance'=>$closing,
							'description'=>'Wallet debit for cab booking',
						];
						$this->common_model->Insert('wallet_transactions', $data);
						$this->common_model->Update('tbl_user', ['wallet_amount'=>$closing],['id'=>$user_id]);
						$this->common_model->Update('tbl_booking', ['payment_status'=>1],['book_id'=>$booking_id]);
					}
					
					$request_id='REQ-'.sprintf("%08d", mt_rand(0, 999999));
					
					foreach($result as $row)
					{
						
						$data=array(
							 'req_id'=>$request_id,
							 'waypoints'=>json_encode($waypoints),
							 'user_id'=>$user_id,
							 'booking_type'=>$booking_type,
							 'kms'=>$km,
							 'hours'=>$hrs,
							 'selecteddate'=>$selecteddate,
							 'selectedtime'=>$selectedtime,
							 'booking_id'=>$booking_id,
							 'driver_id'=>$row['driver_id'],
							 'type_id'=>$row['type_id'],
							 'driver_away'=>$row['distance'],
							 'user_journey_distance'=>$total_distance,
							 'travel_time'=>$travel_time,
							 'travel_time_to_pickup_location'=>travel_time($row['distance']),
							 'per_km_fare'=>$row['per_km'],
							 'total_fare'=>round($total_distance*$row['per_km']),
							 'entry_date'=>date('Y-m-d H:i:s'),
							 'added_by_web'=>$added_by_web,
							);
						$this->db->insert('tbl_userwise_cabrequest',$data);
						 
						// if($row['f_token_app'])
						// {
							//send notification
							// $body="You have received a new ride request of pickup locaion ".$pickup_address." from a user .";
							// $title="New Ride Request";
							// sendNotificationFlutter($row['f_token_app'],$body,$title);
						// }
					   
					}
				
					outputJSON(200, 'success', 'Request has been send successfully',['booking_id'=>$booking_id]);
				}else{
					outputJSON(200, 'error', 'Something went wrong, request not submitted');
				}
		    }
		    else
		    {
				outputJSON(200, 'error', 'No any driver found near by you.');
				return;
		    }	   
		}else{
			outputJSON(200, 'error', 'Please fill in all required fields.');
			return;
		}
    }
    
    public function bookings_history()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}

		$input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required']
		];

		checkValidation($input, $rules);

		$check = $this->db->where('id', $input['user_id'])->get('tbl_user');
		if ($check->num_rows() == 0) {
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}

		$start_date = $input['start_date'] ?? null;
		$end_date = $input['end_date'] ?? null;
		$search = $input['search'] ?? null;
		$status = $input['status'] ?? null;
		$booking_type = $input['booking_type'] ?? null;
		$limit = isset($input['limit']) ? (int)$input['limit'] : 10;
		$page = isset($input['page']) ? (int)$input['page'] : 1;
		$offset = ($page - 1) * $limit;

		$this->db
			->select('b.book_id as booking_id, u.driver_name , b.waypoints, b.user_journey_distance, b.travel_time, b.final_grandtotal as grand_total, b.booking_type, b.entry_date as created_at, r.selecteddate as booking_date, r.selectedtime as booking_time, b.paymenttype, u.driver_profile_pic, m.model_name, mk.name as make_name,b.is_cancle,b.ride_status,b.cancle_reason')
			->from('tbl_booking as b')
			->join('tbl_driver as u', 'b.driver_id = u.id')
			->join('tbl_vehicle as v', 'u.id = v.driver_id')
			->join('tbl_vehiclemake as mk', 'v.make_id = mk.id')
			->join('tbl_vehiclemodel as m', 'v.model_id = m.id')
			->join('tbl_userwise_cabrequest as r', 'b.driver_id = r.driver_id and b.book_id=r.booking_id')
			->where('b.user_id', $input['user_id']);
			if (!empty($status)) {

    if ($status == 'completed') {
        $this->db->where('b.ride_status', 2);
        $this->db->where('b.is_cancle', 0);
    }

    if ($status == 'cancelled') {
        $this->db->group_start();
        $this->db->where('b.is_cancle', 1);
        $this->db->or_where('b.ride_status', 3);
        $this->db->group_end();
    }

} else {
    // Default → show both completed and cancelled
    $this->db->group_start();
    $this->db->where([
        'b.ride_status' => 2,
        'b.is_cancle' => 0
    ]);
    $this->db->or_group_start();
    $this->db->where('b.is_cancle', 1);
    $this->db->or_where('b.ride_status', 3);
    $this->db->group_end();
    $this->db->group_end();
}

			// ->where('b.ride_status', 2)
			// ->where('b.is_cancle', 0);
		if (!empty($booking_type)) {
			$this->db->where('b.booking_type', $booking_type);
		}
		if (!empty($start_date) && !empty($end_date)) {
			$from = $start_date . ' 00:00:00';
			$to = $end_date . ' 23:59:59';
			$this->db->where('b.entry_date >=', $from);
			$this->db->where('b.entry_date <=', $to);
		}

		if (!empty($search)) {
			$this->db->like('u.driver_name', $search);
		}

		$count_query = clone $this->db;
		$total_records = $count_query->get()->num_rows();

		$this->db->limit($limit, $offset);
		$bookings = $this->db->order_by('b.id', 'desc')->get()->result();

		$data = [];
		foreach ($bookings as $row) {
			
			$booking_date = ($row->booking_type === 'pre_booking') ?
				date('d M, Y', strtotime($row->booking_date)) . ' ' . date('h:i A', strtotime($row->booking_time)) :
				date('d M, Y h:i A', strtotime($row->created_at));

			$data[] = [
				'booking_id' => $row->booking_id,
				'booking_type' => $row->booking_type,
				'driver_name' => $row->driver_name,
				'driver_profile' => IMAGE_URL . $row->driver_profile_pic,
				'make_name' => $row->make_name,
				'model_name' => $row->model_name,
				'user_journey_distance' => $row->user_journey_distance,
				'travel_time' => $row->travel_time,
				'grand_total' => $row->grand_total,
				'payment_type' => $row->paymenttype,
				'booking_date' => $booking_date,
				'ride_status' => $row->is_cancle == 1 || $row->ride_status == 3 
					? 'cancelled' 
					: 'completed',
				'cancle_reason' => $row->cancle_reason,
				'waypoints' => json_decode($row->waypoints, true),
			];
		}

		$response = [
			'current_page' => $page,
			'total_pages' => ceil($total_records / $limit),
			'total_records' => $total_records,
			'records_per_page' => $limit,
			'data' => $data
		];

		outputJSON(200, 'success', 'Data fetched successfully.', $response);
	}

	public function get_active_ride()
	{

		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}


	   $input = inputJson();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required']
		];

		checkValidation($input, $rules);

		$check = $this->db->where('id', $input['user_id'])->get('tbl_user');
		if ($check->num_rows() == 0) {
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$user_id = (int)$input['user_id'];

		$sql = "
			SELECT b.book_id,
				b.driver_id            AS d_id,
				r.travel_time_to_pickup_location,
				d.driver_name,
				d.mobile_no,
				d.driver_profile_pic,
				v.image                AS vehicle_image,
				v.number,
				v.color,
				v.year,
				m.name                 AS vehicle_make,
				md.model_name,
				b.waypoints,
				b.user_journey_distance,
				b.travel_time,
				b.total_fare,
				b.conv_charge,
				b.grand_total,
				b.user_id              AS u_id,
				u.wallet_amount,
				vt.active_image        AS vehicle_type_image,
				vt.type                AS vehicle_type,
				b.ride_status, b.is_arrive
			FROM tbl_booking b
			INNER JOIN tbl_userwise_cabrequest r 
				ON r.driver_id = b.driver_id 
			   AND r.booking_id = b.book_id
			INNER JOIN tbl_driver d 
				ON d.id = b.driver_id 
			INNER JOIN tbl_vehicle v 
				ON v.driver_id = b.driver_id
			INNER JOIN tbl_vehiclemake m 
				ON m.id = v.make_id 
			INNER JOIN tbl_vehicletype vt 
				ON vt.id = b.type_id 
			INNER JOIN tbl_vehiclemodel md 
				ON md.id = v.model_id 
			INNER JOIN tbl_user u 
				ON u.id = b.user_id 
			WHERE b.user_id = ? and b.driver_id!=0 and b.is_cancle=0 AND b.ride_status NOT IN (2, 3) order by b.id desc limit 1
		";

		$user = $this->db->query($sql, [$user_id,])->row();
		if (!$user) {
			outputJSON(200, 'success', 'No ride data found.');
			return;
		}
		$rating_data = $this->get_driver_rating($user->d_id);
		$response['booking_data'] = [
			'driver_id'             => (string)$user->d_id,
			'arriving_time'         => $user->travel_time_to_pickup_location,
			'rating'                => (string)$rating_data['avg_rating'],
            'total_ratings'         => $rating_data['total_ratings'],
			'driver_name'           => $user->driver_name,
			'driver_mobile'         => (string)$user->mobile_no,
			'driver_profile'        => IMAGE_URL.$user->driver_profile_pic,
			'vehicle_type_image'    => IMAGE_URL.$user->vehicle_type_image,
			'vehicle_image'         => IMAGE_URL.$user->vehicle_image,
			'vehicle_type'          => $user->vehicle_type,
			'vehicle_make'          => $user->vehicle_make,
			'vehicle_model'         => $user->model_name,
			'vehicle_no'            => (string)$user->number,
			'vehicle_colour'        => $user->color,
			'vehicle_reg_year'      => (string)$user->year,
			'waypoints'             => $user->waypoints ? json_decode($user->waypoints) : [],
			'user_journey_distance' => (string)$user->user_journey_distance,
			'total_fare'            => (string)$user->total_fare,
			'conv_charge'           => (string)$user->conv_charge,
			'grand_total'           => (string)$user->grand_total,
			'user_id'               => (string)$user->u_id,
			'wallet_amount'         => (string)$user->wallet_amount,
			'booking_id'            => $user->book_id,
			'ride_status'           => (string)$user->ride_status,
			'is_arrive'             => (string)$user->is_arrive,
		];
		$corr=$this->db->select('curr_lat as latitude, curr_long as longitude')->where('driver_id',$user->d_id)->get('tbl_driver_currentLocation')->row();
		$response['driver_current_location']=$corr;
		outputJSON(200, 'success', 'Ride data fetched.', $response);
	}
public function update_fcm_token()
{
    if (strtoupper($this->input->method()) !== 'POST') {
        outputJSON(405, 'error', 'Invalid request method. Please use POST.');
        return;
    }

    $input = inputJson();

    $rules = [
        ['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required'],
        ['field' => 'fcm_token', 'label' => 'FCM Token', 'rules' => 'required']
    ];

    checkValidation($input, $rules);

    $user_id   = $input['user_id'];
    $fcm_token = $input['fcm_token'];

    $driver = $this->db->where('id', $user_id)
                       ->get('tbl_user')
                       ->row();

    if (!$driver) {
        outputJSON(200, 'error', 'User not found.');
        return;
    }

    $this->db->where('id', $user_id)
             ->update('tbl_user', ['f_token_app' => $fcm_token]);

    outputJSON(200, 'success', 'FCM token updated successfully.');
}

public function delete_account()
{
    if (strtoupper($this->input->method()) !== 'POST') {
        outputJSON(405, 'error', 'Invalid request method. Please use POST.');
        return;
    }

    $input = inputJson();

    $rules = [
        ['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required|integer']
    ];

    checkValidation($input, $rules);

    $user = $this->db->where('id', $input['user_id'])
                     ->get('tbl_user')
                     ->row();

    if (!$user) {
        outputJSON(200, 'error', 'User not found with this ID.');
        return;
    }

    if ($user->delete_status == 'true') {
        outputJSON(200, 'error', 'Account already deleted.');
        return;
    }

    $update = [
        'delete_status' => 'true',
        // 'email'         => NULL,
        // 'mobile'        => NULL,
        // 'name'          => 'Deleted User',
        'deleted_at'    => date('Y-m-d H:i:s')
    ];

    $this->db->where('id', $input['user_id'])
             ->update('tbl_user', $update);

    outputJSON(200, 'success', 'Account deleted successfully.');
}

public function current_booking_status()
{
    if (strtoupper($this->input->method()) !== 'POST') {
        outputJSON(405, 'error', 'Invalid request method. Please use POST.');
        return;
    }

    $input = inputJson();

    $rules = [
        ['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required']
    ];

    checkValidation($input, $rules);

    $user = $this->db->where('id', $input['user_id'])->get('tbl_user');
    if ($user->num_rows() == 0) {
        outputJSON(200, 'error', 'User not found.');
        return;
    }

    // Get latest active booking
    $this->db->select('b.*, r.travel_time_to_pickup_location');
    $this->db->from('tbl_booking as b');
    $this->db->join('tbl_userwise_cabrequest as r', 'r.booking_id = b.book_id AND r.driver_id = b.driver_id', 'left');
    $this->db->where('b.user_id', $input['user_id']);
    $this->db->where_in('b.ride_status', [0,1]);
    $this->db->where('b.is_cancle', 0);
    
    // For book_now: check today's entry_date
    // For pre_booking/rental: check if is_active_schedule_ride = 1
    $this->db->group_start();
        $this->db->group_start();
            $this->db->where('b.booking_type', 'book_now');
            $this->db->where('DATE(b.entry_date)', date('Y-m-d'));
        $this->db->group_end();
        $this->db->or_group_start();
            $this->db->where_in('b.booking_type', ['pre_booking', 'rental']);
            $this->db->where('b.is_active_schedule_ride', 1);
        $this->db->group_end();
    $this->db->group_end();
    
    $this->db->order_by('b.id', 'DESC');
    $this->db->limit(1);
    
    $booking = $this->db->get()->row();

    if (!$booking) {
        outputJSON(200, 'success', 'No active booking found.', [
            'has_active_booking' => false
        ]);
        return;
    }

    if ($booking->driver_id == 0 && $booking->booking_type =='book_now') {

        $data = [
            'has_active_booking' => true,
            'ride_status' => 0,
            'booking_id' => $booking->book_id,
            'booking_type' => $booking->booking_type,
            'waypoints' => json_decode($booking->waypoints, true),
            'user_journey_distance' => $booking->user_journey_distance,
            'estimated_fare' => $booking->grand_total,
            'message' => 'Waiting for driver acceptance'
        ];

        outputJSON(200, 'success', 'Pending booking found.', $data);
        return;
    }


    if ($booking->driver_id != 0 ) {

        $details = $this->db
            ->select('
                b.book_id,
                b.driver_id as d_id,
                d.driver_id as driver_id,
				b.otp,
				b.booking_type,
				b.paymenttype,
                d.driver_name,
                d.mobile_no,
                d.driver_profile_pic,
                v.image as vehicleimage,
                v.number,
                v.color,
                v.year,
                m.name as vehicle_make,
                md.model_name,
                b.waypoints,
                b.user_journey_distance,
                b.total_fare,
                b.conv_charge,
                b.grand_total,
                u.wallet_amount,
                vt.active_image,
                vt.type as vehicle_type,
                u.id as u_id,
                u.user_id as user_id,
                r.travel_time_to_pickup_location
            ')
            ->from('tbl_booking as b')
            ->join('tbl_driver d', 'd.id = b.driver_id')
            ->join('tbl_vehicle v', 'v.driver_id = b.driver_id')
            ->join('tbl_vehiclemake m', 'm.id = v.make_id')
            ->join('tbl_vehiclemodel md', 'md.id = v.model_id')
            ->join('tbl_vehicletype vt', 'vt.id = b.type_id')
            ->join('tbl_user u', 'u.id = b.user_id')
            ->join('tbl_userwise_cabrequest r', 'r.driver_id = b.driver_id AND r.booking_id = b.book_id')
            ->where('b.book_id', $booking->book_id)
            ->get()
            ->row();
		$rating_data = $this->get_driver_rating($details->d_id);
        $data = [
    'has_active_booking' => true,
    'ride_status' => 1,
    'booking_id' => (string) ($details->book_id ?? ''),
	'booking_type' => $details->booking_type,
    'driver_id' => (string) ($details->d_id ?? ''),
    'driver_string_id' => (string) ($details->driver_id ?? ''),
    'user_id' => (string) ($details->u_id ?? ''),
    'user_string_id' => (string) ($details->user_id ?? ''),
    'arriving_time' => (string) ($details->travel_time_to_pickup_location ?? ''),
    'driver_name' => $details->driver_name ?? '',
    'driver_mobile' => (string) ($details->mobile_no ?? ''),

    'driver_profile' => !empty($details->driver_profile_pic)
        ? IMAGE_URL . $details->driver_profile_pic
        : null,

    'vehicle_type_image' => !empty($details->active_image)
        ? IMAGE_URL . $details->active_image
        : null,

    'vehicle_image' => !empty($details->vehicleimage)
        ? IMAGE_URL . $details->vehicleimage
        : null,

    'vehicle_type' => $details->vehicle_type ?? '',
    'vehicle_make' => $details->vehicle_make ?? '',
    'vehicle_model' => $details->model_name ?? '',

    'vehicle_no' => (string) ($details->number ?? ''),
    'vehicle_colour' => $details->color ?? '',
    'vehicle_reg_year' => (string) ($details->year ?? ''),

    'waypoints' => !empty($details->waypoints)
        ? json_decode($details->waypoints, true)
        : [],

    'user_journey_distance' => (string) ($details->user_journey_distance ?? ''),
    'total_fare' => (string) ($details->total_fare ?? ''),
    'conv_charge' => (string) ($details->conv_charge ?? ''),
    'grand_total' => (string) ($details->grand_total ?? ''),
    'wallet_amount' => (string) ($details->wallet_amount ?? ''),
    'payment_type' => (string) ($details->paymenttype ?? ''),
    'otp' => (string) ($details->otp ?? ''),
    'rating'                => (string)$rating_data['avg_rating'],
    'total_ratings'         => $rating_data['total_ratings'],
];


        outputJSON(200, 'success', 'Active ride found.', $data);
        return;
    }
}

public function get_notifications()
{
	if (strtoupper($this->input->method()) !== 'POST') {
		outputJSON(405, 'error', 'Invalid request method. Please use POST.');
		return;
	}

	$input = inputJson();

	$rules = [
		['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required']
	];

	checkValidation($input, $rules);

	$user = $this->db->where('user_id', $input['user_id'])->get('tbl_user');
	if ($user->num_rows() == 0) {
		outputJSON(200, 'error', 'User not found.');
		return;
	}

	$this->db->where('user_id', $user->row()->user_id);
	$this->db->where('user_type', 'user');

	if (!empty($input['search'])) {
		$this->db->group_start();
		$this->db->like('title', $input['search']);
		$this->db->or_like('body', $input['search']);
		$this->db->group_end();
	}

	if (!empty($input['notification_type'])) {
		$this->db->where('notification_type', $input['notification_type']);
	}

	if (isset($input['is_read']) && $input['is_read'] !== '') {
		$this->db->where('is_read', (int)$input['is_read']);
	}

	$page = isset($input['page']) ? (int)$input['page'] : 1;
	$limit = isset($input['limit']) ? (int)$input['limit'] : 20;
	$offset = ($page - 1) * $limit;

	$total_records = $this->db->count_all_results('tbl_notifications', false);

	$this->db->order_by('created_at', 'DESC');
	$this->db->limit($limit, $offset);

	$res = $this->db->get()->result();

	foreach ($res as $row) {
		$row->payload = json_decode($row->payload, true);
	}

	$unread_count = $this->db
		->where('user_id', $user->row()->user_id)
		->where('user_type', 'user')
		->where('is_read', 0)
		->count_all_results('tbl_notifications');

	$response = [
		"current_page" => $page,
		"total_pages" => ceil($total_records / $limit),
		"total_records" => $total_records,
		"records_per_page" => $limit,
		"unread_count" => $unread_count,
		"notification_list" => $res
	];

	outputJSON(200, "success", "Notification list fetched successfully.", $response);
}

public function mark_notification_read()
{
	if (strtoupper($this->input->method()) !== 'POST') {
		outputJSON(405, 'error', 'Invalid request method. Please use POST.');
		return;
	}

	$input = inputJson();

	$rules = [
		['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required']
	];

	checkValidation($input, $rules);

	$user = $this->db->where('user_id', $input['user_id'])->get('tbl_user');
	if ($user->num_rows() == 0) {
		outputJSON(200, 'error', 'User not found.');
		return;
	}

	if (!empty($input['notification_id'])) {
		// Mark single notification as read
		$this->db->where('id', $input['notification_id']);
		$this->db->where('user_id', $user->row()->user_id);
		$this->db->where('user_type', 'user');
		$this->db->update('tbl_notifications', ['is_read' => 1]);

		if ($this->db->affected_rows() > 0) {
			outputJSON(200, 'success', 'Notification marked as read.');
		} else {
			outputJSON(200, 'error', 'Notification not found.');
		}
	} else {
		// Mark all notifications as read
		$this->db->where('user_id', $user->row()->user_id);
		$this->db->where('user_type', 'user');
		$this->db->where('is_read', 0);
		$this->db->update('tbl_notifications', ['is_read' => 1]);

		$updated_count = $this->db->affected_rows();
		outputJSON(200, 'success', 'All notifications marked as read.', ['updated_count' => $updated_count]);
	}
}


public function submit_rating()
{
	if (strtoupper($this->input->method()) !== 'POST') {
		outputJSON(405, 'error', 'Invalid request method. Please use POST.');
		return;
	}

	$input = inputJson();

	$rules = [
		['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required'],
		['field' => 'booking_id', 'label' => 'Booking ID', 'rules' => 'required'],
		['field' => 'driver_id', 'label' => 'Driver ID', 'rules' => 'required'],
		['field' => 'rating', 'label' => 'Rating', 'rules' => 'required|numeric|greater_than[0]|less_than_equal_to[5]']
	];

	checkValidation($input, $rules);

	$booking = $this->db->where('book_id', $input['booking_id'])
						->where('user_id', $input['user_id'])
						->get('tbl_booking');
	
	if ($booking->num_rows() == 0) {
		outputJSON(200, 'error', 'Booking not found.');
		return;
	}

	$existing = $this->db->where('booking_id', $input['booking_id'])
						 ->where('user_id', $input['user_id'])
						 ->get('tbl_ratings');
	
	if ($existing->num_rows() > 0) {
		outputJSON(200, 'error', 'Rating already submitted for this booking.');
		return;
	}

	$data = [
		'user_id' => $input['user_id'],
		'booking_id' => $input['booking_id'],
		'driver_id' => $input['driver_id'],
		'rating' => $input['rating'],
		'review' => $input['review'] ?? '',
		'tags' => !empty($input['tags']) ? json_encode($input['tags']) : null,
		'created_at' => date('Y-m-d H:i:s')
	];

	$this->db->insert('tbl_ratings', $data);

	outputJSON(200, 'success', 'Rating submitted successfully.');
}

private function get_driver_rating($driver_id) {
    $result = $this->db
        ->select('COALESCE(AVG(rating), 0) as avg_rating, COUNT(*) as total_ratings')
        ->where('driver_id', $driver_id)
        ->get('tbl_ratings')
        ->row();
    
    return [
        'avg_rating' => number_format($result->avg_rating, 1),
        'total_ratings' => (int)$result->total_ratings
    ];
}
	


public function scheduled_bookings()
{
	if (strtoupper($this->input->method()) !== 'POST') {
		outputJSON(405, 'error', 'Invalid request method. Please use POST.');
		return;
	}

	$input = inputJson();

	$rules = [
		['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required']
	];

	checkValidation($input, $rules);

	$user = $this->db->where('id', $input['user_id'])->get('tbl_user');
	if ($user->num_rows() == 0) {
		outputJSON(200, 'error', 'User not found.');
		return;
	}

	$current_date = date('Y-m-d');
	$current_time = date('H:i');

	$bookings = $this->db
		->select('b.book_id as booking_id, b.waypoints, b.user_journey_distance, b.booking_type, b.travel_time, b.grand_total, r.selecteddate as booking_date, r.selectedtime as booking_time')
		->from('tbl_booking as b')
		->join('tbl_userwise_cabrequest as r', 'r.booking_id = b.book_id')
		->where(['b.user_id' => $input['user_id'], 'b.ride_status' => 0, 'b.is_cancle' => 0, 'b.is_active_schedule_ride' => 0])
		->where_in('b.booking_type', ['pre_booking', 'rental'])
		->group_start()
			->where('r.selecteddate >', $current_date)
			->or_group_start()
				->where('r.selecteddate', $current_date)
				->where('r.selectedtime >', $current_time)
			->group_end()
		->group_end()
		->order_by('r.selecteddate', 'ASC')
		->order_by('r.selectedtime', 'ASC')
		->get()
		->result();

	foreach ($bookings as $row) {
		$row->booking_date = date('d M, D', strtotime($row->booking_date));
		$row->booking_time = date('h:i A', strtotime($row->booking_time));
		$row->waypoints = json_decode($row->waypoints, true);
	}

	outputJSON(200, 'success', 'Scheduled bookings fetched successfully.', $bookings);
}
	

}

?>
