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

class DriverController 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 send_otp()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}
		$input = inputJson();
		$rules = [
			['field' => 'phone', 'label' => 'Mobile Number', 'rules' => 'required|trim|exact_length[10]|numeric']
		];
		checkValidation($input,$rules);
		$phone=$input['phone'];

		$check = $this->db->where('mobile_no', $phone)->get('tbl_driver')->num_rows();
		if($check==0){

			
			$data = [
				'mobile_no'   => $phone
			];

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

			if ($this->db->affected_rows() == 0) {
				outputJSON(200, 'error', 'something went wrong, please try after sometime.');
				return;
			}
			$id=$this->db->insert_id(); 
			// $names = str_replace(' ', '', $name);
			$driver_id=date('YmdHi').'-'.$id."-Drv";
			$this->db->update('tbl_driver',['driver_id'=>$driver_id],['id'=>$id]);
			
		}

		$template = $this->db->where(['status'=>0,'type'=>'send_otp'])->get('sms_template')->row();

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

		$otp = "123456";
		// $otp = sprintf("%06d", mt_rand(0, 999999));
		$user = $this->db->where('mobile_no', $phone)->get('tbl_driver')->row();
		$username = !empty($user->driver_name) ? str_replace(' ', '', $user->driver_name) : 'User';

		$message = str_replace(
			['mobile_number', 'user_name', 'otp_now'],
			[$phone,$username, $otp],
			$template->body
		);

		$otpData = [
			'otp' => $otp,
			'user_id' => $user->driver_id,
			'status' => 0 ,
		];

		$existingOtp = $this->db->where('user_id',$user->driver_id)->get('mobile_otp')->num_rows();

		if ($existingOtp>0) {
			$this->db->update('mobile_otp', ['otp' => $otp, 'status'=> 0 ,'updated_at' => date('Y-m-d H:i:s')], ['user_id' => $user->driver_id]);
		} else {
			$this->db->insert('mobile_otp', $otpData);
		}

		// $result=send_text_msg_new($message);
		// if (!$result) {
		// 	outputJSON(200, 'error', 'Failed to send sms, try again');
		// 	return;
		// }
		outputJSON(200, 'success', 'OTP has been sent successfully',['phone'=>$phone,'otp'=>$otp]);
		return;
	}

    
     public function verify_otp()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}
		$input = inputJson();
		$rules = [
			['field' => 'phone', 'label' => 'Mobile Number', 'rules' => 'required|trim|exact_length[10]|numeric'],
			['field' => 'otp', 'label' => 'OTP', 'rules' => 'required|trim']
		];
		checkValidation($input,$rules);
		$phone=$input['phone'];
		$otp=$input['otp'];

		$check = $this->db->where('mobile_no', $phone)->get('tbl_driver');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'Invalid User mobile number, Record not found.');
			return;
		}
		$userRecord=$check->row();
		$user_id=$userRecord->driver_id;
		$otpQuery = "SELECT * FROM mobile_otp WHERE user_id = ? AND otp = ? AND status = 0";
		$otpRecord = $this->db->query($otpQuery, [$user_id, $otp])->row();

		if (!$otpRecord) {
			outputJSON(200, 'error', 'Incorrect otp.');
			return;
		}

		$otpTime = strtotime($otpRecord->updated_at);
		$currentTime = time();
		$expiryTime = 10 * 60;

		if (($currentTime - $otpTime) > $expiryTime) {
			outputJSON(200, 'error', 'OTP has expired. Please request a new one.');
			return;
		}

		$this->db->update('mobile_otp', ['status' => 1], ['user_id' => $user_id, 'otp' => $otp]);

		$vehical = $this->db->where(['driver_id'=>$userRecord->id])->get('tbl_vehicle')->num_rows();
		if($userRecord->driver_name=='' or $vehical==0){
			$profile_status=false;
		}else{
			$profile_status=true;
		}

	   $response = [
			'id' => $userRecord->id,
			'driver_id' => $userRecord->driver_id,
			'name' => $userRecord->driver_name,
			'email' => $userRecord->email,
			'mobile' => $userRecord->mobile_no,
			'profile_status' => $profile_status,
			
		];

		outputJSON(200, 'success', 'Login successfully',$response);
		return;
	}
     
	 public function verify_multi_user()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}
		$input = inputJson();
		$rules = [
			['field' => 'phone', 'label' => 'Mobile Number', 'rules' => 'required|trim|exact_length[10]|numeric']
		];
		checkValidation($input,$rules);
		$phone=$input['phone'];

		$check = $this->db->where('mobile_no', $phone)->get('tbl_driver');
		if($check->num_rows()==0){
			$data = [
				'mobile_no'   => $phone
			];

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

			if ($this->db->affected_rows() == 0) {
				outputJSON(200, 'error', 'something went wrong, please try after sometime.');
				return;
			}
			$id=$this->db->insert_id(); 
			$driver_id=date('YmdHi').'-'.$id."-Drv";
			$this->db->update('tbl_driver',['driver_id'=>$driver_id],['id'=>$id]);
			$check = $this->db->where('mobile_no', $phone)->get('tbl_driver');
		}
		$userRecord=$check->row();
		

		$vehical = $this->db->where(['driver_id'=>$userRecord->id])->get('tbl_vehicle')->num_rows();
		if($userRecord->driver_name=='' or $vehical==0){
			$profile_status=false;
		}else{
			$profile_status=true;
		}

	   $response = [
			'id' => $userRecord->id,
			'driver_id' => $userRecord->driver_id,
			'name' => $userRecord->driver_name,
			'email' => $userRecord->email,
			'mobile' => $userRecord->mobile_no,
			'profile_status' => $profile_status,
			
		];

		outputJSON(200, 'success', 'Verify successfully',$response);
		return;
	}
    
	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'])->get('tbl_driver');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$res=$check->row();
		$profile=[
			'id' => $res->id,
			'user_id' => $res->driver_id,
			'name' => $res->driver_name,
			'mobile' => $res->mobile_no,
			'email' => $res->email,
			'pickup_radius' => $res->pickup_radius,
			'profile_pic' => IMAGE_URL.$res->driver_profile_pic,
			'driving_license' => IMAGE_URL.$res->driving_license_image,
			'driver_pancard' => IMAGE_URL.$res->driver_pancard,
			'vehicle_rc' => IMAGE_URL.$res->vehicle_rc,
			'vehicle_insurance' => IMAGE_URL.$res->vehicle_endurance,
			'wallet_amount' => $res->wallet_amount,
			'rating' => '4.1',
		];
		$checkv = $this->db->where('driver_id', $input['user_id'])->get('tbl_vehicle');

if ($checkv->num_rows() > 0) {

    $vehicle = $checkv->row();

    $make  = $this->db->where('id', $vehicle->make_id)->get('tbl_vehiclemake')->row();
    $model = $this->db->where('id', $vehicle->model_id)->get('tbl_vehiclemodel')->row();

    $type_ids_data = $this->db
        ->where('vehicle_id', $vehicle->id)
        ->get('tbl_map_vehicletype')
        ->result_array();

    $type_ids = array_column($type_ids_data, 'type_id');

    if (!empty($type_ids)) {
        $type_names_data = $this->db
            ->where_in('id', $type_ids)
            ->get('tbl_vehicletype')
            ->result_array();

        $type_id   = implode(',', $type_ids);
        $type_name = implode(',', array_column($type_names_data, 'name'));
    } else {
        $type_id   = '';
        $type_name = '';
    }

    $vehical_details = [
        'make_id'            => $vehicle->make_id,
        'model_id'           => $vehicle->model_id,
        'vehicle_type_id'    => $type_id,
        'vehicle_type_name'  => $type_name,
        'make_name'          => $make->name ?? '',
        'model_name'         => $model->model_name ?? '',
        'vehicle_no'         => $vehicle->number,
        'colour'             => $vehicle->color,
        'year'               => $vehicle->year,
        'image'              => !empty($vehicle->image) ? IMAGE_URL . $vehicle->image : '',
    ];

} else {
    $vehical_details = [];
}

		$verification=[
			'driving_license'=>$res->driving_license_status,
			'pancard'=>$res->pancard_status,
			'rc_status'=>$res->rc_status,
			'insurance_status'=>$res->insurance_status,
		];
		
		$this->db
		->select('b.book_id as booking_id, u.f_name as username, b.waypoints, b.user_journey_distance, b.travel_time, b.final_grandtotal as grand_total, b.booking_type, b.entry_date as created_at,b.selecteddate as booking_date , b.selectedtime as booking_time , r.selecteddate, r.selectedtime')
		->from('tbl_booking as b')
		->join('tbl_user as u', 'b.user_id = u.id')
		->join('tbl_userwise_cabrequest as r', 'b.driver_id = r.driver_id and b.book_id=r.booking_id')
		->where('b.driver_id', $input['user_id'])
		->where('b.ride_status', 2)
		->where('b.is_cancle', 0);

		$bookings = $this->db->order_by('b.id','desc')->limit(3)->get()->result();
		$ride_history=[];
		foreach($bookings as $row){
			if($row->booking_type =='pre_booking'){
				$booking_date=date('d M, Y',strtotime($row->booking_date)).' '.date('h:i A',strtotime($row->booking_time));
			}else{
				$booking_date=date('d M, Y h:i A',strtotime($row->created_at));
			}
			$ride_history[]=[
				'booking_id'=>$row->booking_id,
				'booking_type'=>$row->booking_type,
				'username'=>$row->username,
				'user_journey_distance'=>$row->user_journey_distance,
				'travel_time'=>$row->travel_time,
				'grand_total'=>$row->grand_total,
				'booking_date'=>$booking_date,
				'waypoints'=>json_decode($row->waypoints, true),
			];
		}
		$data = [
			'profile_details'=>$profile,
			'vehical_details'=>$vehical_details,
			'doc_verifications'=>$verification,
			'ride_history'=>$ride_history,
		];
		outputJSON(200, 'success', 'Data fetched successfully.',$data);
		
	}
    
    
    public function get_scheduled_booking()
{
    if (strtoupper($this->input->method()) !== 'GET') {
        echo json_encode([
            'status' => false,
            'statusCode' => 200 ,
                
            'message' => 'Invalid request method'
        ]);
        return;
    }

    $booking_id = $this->input->get('booking_id');

    if (empty($booking_id)) {
        echo json_encode([
            'status' => false,
            'statusCode' => 200 ,
                
            'message' => 'Booking ID is required'
        ]);
        return;
    }

   $booking = $this->db
    ->select("
        b.id,
        b.book_id,
        b.user_id,
        b.payment_status,
        b.cancle_reason ,
        b.ride_status ,
        b.cancle_date,
        u.f_name as username,
        u.mobile_no,
        b.pickup_address,
        b.drop_address,
        b.kms,
        b.hours,
        b.total_fare,
        b.user_journey_distance,
        b.travel_time ,
        b.waypoints,
        b.selecteddate,
        b.selectedtime,
        b.booking_type,

    ")
    ->from('tbl_booking b')
    ->join('tbl_user u', 'u.id = b.user_id', 'left')
    ->where('b.book_id', $booking_id)
    //  ->where('b.booking_type', 'pre_booking')
       ->where('b.is_cancle', '0')
    ->get()
    ->row_array();

if (!$booking) {
    echo json_encode([
        'status' => false,
        'statusCode' => 200 ,
                
        'message' => 'Booking not found'
    ]);
    return;
}

/* ✅ decode waypoint string into array */
$waypoints = [];

if (!empty($booking['waypoints'])) {
    $waypoints = json_decode($booking['waypoints'], true);
}



$status_map = [
    0 => "Pending",
    1 => "Start",
    2 => "Complete",
    3 => "Rejected"
];


echo json_encode([
    'status' => true,
    'statusCode' => 200 ,
                
    'message' => 'Booking fetched successfully',
    'data' => [
        'booking_id' => $booking['id'],
        'username' => $booking['username'],
        'mobile_no' => $booking['mobile_no'],
       'distance_km' => $booking['user_journey_distance'],
        'user_journey_distance' => $booking['user_journey_distance'],
        'travel_time' => $booking['travel_time'],
        'fare' => $booking['total_fare'],
        "booking_type" =>  $booking['booking_type'],
        "ride_status" => $status_map[$booking['ride_status']] ?? "",
    "payment_status" => ($booking['payment_status'] == 1) ? "Complete" : "Pending",
    "cancel_reason" =>$booking['cancle_reason'],
    "cancel_date" =>  $booking['cancle_date'],
        'scheduled_date' => $booking['selecteddate'],
        'scheduled_time' => $booking['selectedtime'],
        'kms' => $booking['kms'],
        'hours' => $booking['hours'],
        /* ✅ proper formatted waypoint */
        'waypoints' => $waypoints
    ]
]);


}
    
  public function cancel_ride()
{
    // Only POST allowed
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(405)
            ->set_output(json_encode([
                'status' => false,
                'statusCode' => 200 ,
                
                'message' => 'Invalid request method. POST required.'
            ]));
    }

    // Get JSON input
    $input = json_decode(file_get_contents("php://input"), true);

    // Validate JSON format
    if (!$input) {
        return $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode([
                'status' => false,
                'statusCode' => 200 ,
                
                'message' => 'Invalid JSON format'
            ]));
    }

    // Get values
    $booking_id    = isset($input['booking_id']) ? trim($input['booking_id']) : '';
    $cancel_reason = isset($input['cancel_reason']) ? trim($input['cancel_reason']) : '';

    // Validation
    if (empty($booking_id)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode([
                'status' => false,
                'statusCode' => 200 ,
                
                'message' => 'Booking ID is required'
            ]));
    }

    if (empty($cancel_reason)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode([
                'status' => false,
                'statusCode' => 200 ,
                
                'message' => 'Cancel reason is required'
            ]));
    }

    // Check booking exists
    $booking = $this->db
        ->where('book_id', $booking_id)
        ->get('tbl_booking')
        ->row();

    if (!$booking) {
        return $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode([
                'status' => false,
                'statusCode' => 200 ,
                
                'message' => 'Invalid booking ID'
            ]));
    }

    // Check already cancelled
    if ($booking->is_cancle == 1) {
        return $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode([
                'status' => false,
                'statusCode' => 200 ,
                
                'message' => 'Ride already cancelled'
            ]));
    }

    // Update booking
    $update = [
       
        'cancle_reason' => $cancel_reason,
        'cancle_reason'   => date('Y-m-d H:i:s'),
        'is_cancle'     => 1
    ];

    $this->db->where('book_id', $booking_id);
    $result = $this->db->update('tbl_booking', $update);

    if ($result) {
        return $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode([
                'status' => true,
                'statusCode' => 200 ,
                
                'message' => 'Ride cancelled successfully',
                'data' => [
                    'booking_id' => $booking_id,
                    'cancle_reason' => $cancel_reason,
                    'cancle_date' => date('Y-m-d H:i:s')
                ]
            ]));
    } else {
        return $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode([
                'status' => false,
                'statusCode' => 200 ,
                
                'message' => 'Failed to cancel ride'
            ]));
    }
}






	public function online_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|integer']
		];

		checkValidation($input, $rules);
		$check=$this->db->where('id',$input['user_id'])->get('tbl_driver');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$res=$check->row();
		$profile=[
			'id' => $res->id,
			'user_id' => $res->driver_id,
			'is_online' => $res->is_online,
		];
		
		outputJSON(200, 'success', 'Data fetched successfully.',$profile);
	}
    
	
	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_driver');

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

		$user = $check->row();

		
		$bank=$this->db->select('bank_name,account_number as account_no,ifsc as ifsc_code,branch as branch_address,account_type,account_holder_name')->where('driver_id',$input['user_id'])->where('delete_status', 'false')->get('driver_bank_details')->result();
		$response = [
			"bank_details" => $bank,
			"wallet_amount" => (string)$user->wallet_amount,
			"amount_received"=>[
				'cash'=>'0',
				'wallet'=>'0',
				'phonepe'=>'0',
			]
		];

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

	public function recent_transaction_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_driver');

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

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

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

	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('driver_wallet_transactions', false);
	$this->db->limit($limit, $offset);
	$res = $this->db->get()->result();
	foreach($res as $row){
		$row->type='Wallet';
	}

	$response = [
		"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 cashout_details()
	{
		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_driver');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		$res=$check->row();
		$bank=$this->db->select('bank_name,account_number as account_no,ifsc as ifsc_code,branch as branch_address,account_type,account_holder_name')->where('driver_id',$input['user_id'])->where('delete_status', 'false')->get('driver_bank_details')->result();
		outputJSON(200, 'success', 'Data fetched successfully.',['wallet_balance'=>(int)$res->wallet_amount,'bank_detail'=>$bank]);
		
	}

	public function withdraw_request()
	{
		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' => 'account_no', 'label' => 'Account Number', 'rules' => 'required'],
			['field' => 'amount', 'label' => 'Amount', 'rules' => 'required|numeric']
		];

		checkValidation($input, $rules);

		$user_id   = $input['user_id'];
		$account_no = $input['account_no'];
		$amount    = (float)$input['amount'];

		if ($amount <= 0) {
			outputJSON(200, 'error', 'Withdraw amount must be greater than zero.');
			return;
		}

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

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

		$bank = $this->db->where('driver_id', $user_id)
						->where('account_number', $account_no)
						->where('delete_status', 'false')
						->get('driver_bank_details')
						->row();

		if (!$bank) {
			outputJSON(200, 'error', 'Bank account not found with provided account number.');
			return;
		}

		// Insufficient Balance Check
		if ($driver->wallet_amount < $amount) {
			outputJSON(200, 'error', 'Insufficient wallet balance.');
			return;
		}

		$this->db->trans_begin();

		$opening_balance = $driver->wallet_amount;
		$closing_balance = $opening_balance - $amount;

		// 1️⃣ Insert Withdraw Request
		$withdraw_data = [
			'driver_id' => $user_id,
			// 'order_id'  => null,
			// 'txn_id'    => null,
			'amount'    => $amount,
			'bank_id'   => $bank->id,
			'status'    => 0
		];

		$this->db->insert('driver_withdraw_request', $withdraw_data);
		$withdraw_id = $this->db->insert_id();

		$wallet_txn = [
			'user_id'         => $user_id,
			'source'          => 'withdraw',
			'source_id'       => $withdraw_id,
			'transaction_type'=> 'debit',
			'amount'          => $amount,
			'opening_balance' => $opening_balance,
			'closing_balance' => $closing_balance,
			'description'     => 'Withdraw request submitted'
		];

		$this->db->insert('driver_wallet_transactions', $wallet_txn);

		$this->db->where('id', $user_id)
				->update('tbl_driver', ['wallet_amount' => $closing_balance]);

		if ($this->db->trans_status() === FALSE) {
			$this->db->trans_rollback();
			outputJSON(500, 'error', 'Something went wrong. Please try again.');
		} else {
			$this->db->trans_commit();
			outputJSON(200, 'success', 'Withdraw request submitted successfully.');
		}
	}

	public function withdraw_request_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 Driver
		$driver = $this->db->where('id', $input['user_id'])
						->get('tbl_driver')
						->row();

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

		$this->db->select("
			driver_withdraw_request.id,
			driver_withdraw_request.amount,
			driver_withdraw_request.status,
			driver_withdraw_request.created_at,
			driver_bank_details.bank_name,
			driver_bank_details.account_number as account_no
		");

		$this->db->from('driver_withdraw_request');
		$this->db->join('driver_bank_details', 'driver_bank_details.id = driver_withdraw_request.bank_id', 'left');
		$this->db->where('driver_withdraw_request.driver_id', $input['user_id']);

		// ✅ Status Filter (Optional)
		if (isset($input['status']) && $input['status'] !== '') {
			$this->db->where('driver_withdraw_request.status', $input['status']);
		}

		// ✅ Date Filter (same pattern as your previous API)
		if (!empty($input['start_date']) && !empty($input['end_date'])) {
			$this->db->where("DATE(driver_withdraw_request.created_at) BETWEEN '{$input['start_date']}' AND '{$input['end_date']}'");
		} elseif (!empty($input['start_date'])) {
			$this->db->where("DATE(driver_withdraw_request.created_at) >=", $input['start_date']);
		} elseif (!empty($input['end_date'])) {
			$this->db->where("DATE(driver_withdraw_request.created_at) <=", $input['end_date']);
		}

		// ✅ Pagination
		$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('', false);

		$this->db->order_by('driver_withdraw_request.id', 'DESC');
		$this->db->limit($limit, $offset);

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

		// ✅ Status Text Mapping
		foreach ($res as $row) {
			if ($row->status == 0) {
				$row->status_text = "Processing";
			} elseif ($row->status == 1) {
				$row->status_text = "Success";
			} elseif ($row->status == 2) {
				$row->status_text = "Failed";
			}
		}

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

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


	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_driver');
		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 vehicle_make()
	{
		if (strtoupper($this->input->method()) !== 'GET') {
			outputJSON(405, 'error', 'Invalid request method. Please use GET.');
			return;
		}

		$res=$this->db->select('id,name')->where('status',1)->get('tbl_vehiclemake')->result();
		outputJSON(200, 'success', 'Data fetched successfully.',$res);
		
	}
	 public function vehicle_model()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}
		$input = inputJson();

		$rules = [
			['field' => 'vehicle_make_id', 'label' => 'Vehicle make ID', 'rules' => 'required|integer']
		];

		checkValidation($input, $rules);
		$check=$this->db->where('id',$input['vehicle_make_id'])->get('tbl_vehiclemake');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'Vehicle make not found with this ID.');
			return;
		}
		
		$res=$this->db->select('id,make_id,model_name')->where('status',1)->where('make_id',$input['vehicle_make_id'])->get('tbl_vehiclemodel')->result();
		outputJSON(200, 'success', 'Data fetched successfully.',$res);
		
	}
    
	 public function vehicle_type()
	{
		if (strtoupper($this->input->method()) !== 'GET') {
			outputJSON(405, 'error', 'Invalid request method. Please use GET.');
			return;
		}
		
		$res=$this->db->select('id,name,description,type,seat,image,active_image')->where('status',1)->get('tbl_vehicletype')->result();
		foreach($res as $row){
			$row->image=IMAGE_URL.$row->image;
			$row->active_image=IMAGE_URL.$row->active_image;
		}
		outputJSON(200, 'success', 'Data fetched successfully.',$res);
		
	}
	
	public function personal_details(){
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}
		$input = $_POST;

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required|integer'],
			['field' => 'pickup_radius', 'label' => 'Pickup radius', 'rules' => 'required'],
			['field' => 'name', 'label' => 'Name', 'rules' => 'required'],
			['field' => 'make_id', 'label' => 'make id', 'rules' => 'required'],
			['field' => 'model_id', 'label' => 'model id', 'rules' => 'required'],
			['field' => 'vehicle_type', 'label' => 'vehicle type', 'rules' => 'required'],
			['field' => 'vehicle_no', 'label' => 'vehicle number', 'rules' => 'required'],
			['field' => 'colour', 'label' => 'vehicle colour', 'rules' => 'required'],
			['field' => 'year', 'label' => 'vehicle registration year', 'rules' => 'required'],
		];

		checkValidation($input, $rules);

		$user_id = $input['user_id'];
		$name = $input['name'];
		$email = $input['email'] ?? null;
		$make_id = $input['make_id'];
		$model_id = $input['model_id'];
		$vehicle_type = $input['vehicle_type'];
		$vehicle_no = $input['vehicle_no'];
		$colour = $input['colour'];
		$year = $input['year'];
		$pickup_radius = $input['pickup_radius'];
		$check=$this->db->where('id',$input['user_id'])->get('tbl_driver');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'User not found with this ID.');
			return;
		}
		if (isset($_FILES['pancard'], $_FILES['driving_licence'], $_FILES['vehicle_rc'], $_FILES['insurance'], $_FILES['profile_pic'], $_FILES['vehicle_image'])) {
			$time = time();
			$documentFields = [
				'pancard' => 'uploads/images/Pan/',
				'driving_licence' => 'uploads/images/Licence/',
				'vehicle_rc' => 'uploads/images/Rc/',
				'insurance' => 'uploads/images/Insurance/',
				'profile_pic' => 'uploads/images/DriverProfile/',
				'vehicle_image' => 'uploads/images/DriverVehicle/'
			];

			$uploadedImages = [];
			foreach ($documentFields as $field => $uploadPath) {
				$ext = pathinfo($_FILES[$field]['name'], PATHINFO_EXTENSION);
				$imagePath = $uploadPath . 'img_' . $time . '.' . $ext;

				$this->my_upload->upload($_FILES[$field]);

				if ($this->my_upload->uploaded) {
					$this->my_upload->allowed = ['image/*'];
					$this->my_upload->file_new_name_body = 'img_' . $time;
					$this->my_upload->jpeg_quality = 100;
					$this->my_upload->image_resize = true;
					$this->my_upload->image_ratio_fill = true;
					$this->my_upload->image_x = 270;
					$this->my_upload->image_y = 168;

					$this->my_upload->process($uploadPath);
					if ($this->my_upload->processed) {
						$this->my_upload->clean();
						$uploadedImages[$field] = $imagePath;
					} else {
						outputJSON(200, 'error', "Error processing $field");
						return;
					}
				} else {
					outputJSON(200, 'error', "$field upload failed");
					return;
				}
			}

			$data = [
				'driver_name' => $name,
				'pickup_radius' => $pickup_radius,
				'email' => $email,
				'driving_license_image' => $uploadedImages['driving_licence'],
				'driver_pancard' => $uploadedImages['pancard'],
				'vehicle_rc' => $uploadedImages['vehicle_rc'],
				'vehicle_endurance' => $uploadedImages['insurance'],
				'driver_profile_pic' => $uploadedImages['profile_pic']
			];
			$res=$this->common_model->Update('tbl_driver', $data, ['id' => $user_id]);
			if($res){
				$check=$this->db->where('driver_id',$input['user_id'])->get('tbl_vehicle');
				if($check->num_rows()==0){
					$dataVehicle = [
						'driver_id' => $user_id,
						'make_id' => $make_id,
						'model_id' => $model_id,
						'number' => $vehicle_no,
						'color' => $colour,
						'year' => $year,
						'entry_date' => date('Y-m-d H:i:s'),
						'image' => $uploadedImages['vehicle_image'],
					];
					$this->db->insert('tbl_vehicle', $dataVehicle);
					if ($this->db->affected_rows() > 0) {
						$id = $this->db->insert_id();
						$types=explode(',',$vehicle_type);
						for($i=0;$i<sizeof($types);$i++)
						{
							$data_sub = array(
							"vehicle_id" => $id,
							"type_id"=>$types[$i],
							"entry_date"=>date('Y-m-d H:i:s'),
							);
							$this->db->insert('tbl_map_vehicletype',$data_sub);
						}
					} else {
						outputJSON(200, 'error', 'Failed to update vehicle details.');
						return;
					}
				}
				outputJSON(200, 'success', 'Data updated successfully');
			}else{
				outputJSON(200, 'error', 'Failed to update data');
				return;
			}
		} else {
			outputJSON(200, 'error', 'Please fill all required fields.');
			return;
		}
	}

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


        $input = $this->input->post();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required'],
			['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'],
			['field' => 'pickup_radius', 'label' => 'Pickup radius', 'rules' => 'required'],
		];

		checkValidation($input, $rules);
		$user_id=$input['user_id'];
		$check=$this->db->where('id!=', $user_id)->where('mobile_no', $input['mobile'])->get('tbl_driver')->num_rows();
		if($check>0){
			outputJSON(409, 'error', 'This mobile number is already registered with us.');
			return;
		}
		
		$user=$this->db->where('id', $user_id)->get('tbl_driver')->row();
		

	   if (!empty($_FILES["profile_pic"]['name'])) {
			$time = time();
			$ext = pathinfo($_FILES['profile_pic']['name'], PATHINFO_EXTENSION);
			$imagePath = 'uploads/images/DriverProfile/img_' . $time . '.' . $ext;

			$this->my_upload->upload($_FILES['profile_pic']);

			if ($this->my_upload->uploaded) {
				$this->my_upload->allowed = ['image/*'];
				$this->my_upload->file_new_name_body = 'img_' . $time;
				$this->my_upload->jpeg_quality = 100;
				$this->my_upload->image_resize = true;
				$this->my_upload->image_ratio_fill = true;
				$this->my_upload->image_x = 270;
				$this->my_upload->image_y = 168;

				$this->my_upload->process('uploads/images/DriverProfile/');
				if ($this->my_upload->processed) {
					$this->my_upload->clean();
					$profile_pic = $imagePath;
				} else {
					outputJSON(200, 'error', "Error processing profile_pic");
					return;
				}
			} else {
				outputJSON(200, 'error', "profile pic upload failed");
				return;
			}
			
		}
		$data = [
			'driver_name' => $input['name'],
			'mobile_no' => $input['mobile'],
			'email' => $input['email'],
			'pickup_radius' => $input['pickup_radius'],
		];
		if(!empty($_FILES["profile_pic"]['name'])) {
			unlink($user->driver_profile_pic);
			$data['driver_profile_pic']=$profile_pic;
		}
				
		$res = $this->common_model->Update('tbl_driver', $data, ['id' => $user_id]);
		if ($res) {
			outputJSON(200, 'success', 'Profile updated successfully.');
			return;
		} else {
			outputJSON(400, 'error', 'Failed to update, please try again');
			return;
		}
	}
	
	public function update_vehical()
	{
		if (strtoupper($this->input->method()) !== 'POST') {
			outputJSON(405, 'error', 'Invalid request method. Please use POST.');
			return;
		}


        $input = $this->input->post();

		$rules = [
			['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required'],
			['field' => 'make_id', 'label' => 'make id', 'rules' => 'required'],
			['field' => 'model_id', 'label' => 'model id', 'rules' => 'required'],
			['field' => 'vehicle_type', 'label' => 'vehicle types', 'rules' => 'required'],
			['field' => 'colour', 'label' => 'vehicle colour', 'rules' => 'required'],
			['field' => 'vehicle_no', 'label' => 'vehicle number', 'rules' => 'required'],
			['field' => 'year', 'label' => 'vehicle registered year', 'rules' => 'required'],
			['field' => 'vehicle_image', 'label' => 'vehicle image', 'rules' => ''],
		];

		checkValidation($input, $rules);
		$user_id=$input['user_id'];
		$make_id=$input['make_id'];
		$model_id=$input['model_id'];
		$vehicle_type=$input['vehicle_type'];
		$colour=$input['colour'];
		$vehicle_no=$input['vehicle_no'];
		$year=$input['year'];

	   if (!empty($_FILES["vehicle_image"]['name'])) {
			$time = time();
			$ext = pathinfo($_FILES['vehicle_image']['name'], PATHINFO_EXTENSION);
			$imagePath = 'uploads/images/DriverVehicle/img_' . $time . '.' . $ext;

			$this->my_upload->upload($_FILES['vehicle_image']);

			if ($this->my_upload->uploaded) {
				$this->my_upload->allowed = ['image/*'];
				$this->my_upload->file_new_name_body = 'img_' . $time;
				$this->my_upload->jpeg_quality = 100;
				$this->my_upload->image_resize = true;
				$this->my_upload->image_ratio_fill = true;
				$this->my_upload->image_x = 270;
				$this->my_upload->image_y = 168;

				$this->my_upload->process('uploads/images/DriverVehicle/');
				if ($this->my_upload->processed) {
					$this->my_upload->clean();
					$vehicle_image = $imagePath;
				} else {
					outputJSON(200, 'error', "Error processing vehicle_image");
					return;
				}
			} else {
				outputJSON(200, 'error', "vehicle_image upload failed");
				return;
			}
			
		}
		$vehicle=$this->db->where('driver_id',$user_id)->get('tbl_vehicle')->row();
		$data = [
			'make_id' => $make_id,
			'model_id' => $model_id,
			'number' => $vehicle_no,
			'color' => $colour,
			'year' => $year,
		];
		if(!empty($_FILES["vehicle_image"]['name'])) {
			unlink($vehicle->image);
			$data['image']=$vehicle_image;
		}
		$res=$this->common_model->Update('tbl_vehicle', $data,['driver_id'=>$user_id]);
		if ($res) {
			
			$id = $vehicle->id;
			$this->db->where('vehicle_id',$id);
    		$this->db->delete('tbl_map_vehicletype');
			$types=explode(',',$vehicle_type);
			for($i=0;$i<sizeof($types);$i++)
			{
				$data_sub = array(
				"vehicle_id" => $id,
				"type_id"=>$types[$i],
				"entry_date"=>date('Y-m-d H:i:s'),
				);
				$this->db->insert('tbl_map_vehicletype',$data_sub);
			}
			outputJSON(200, 'success', 'Vehicle updated successfully.');
			return;
		} else {
			outputJSON(200, 'error', 'Failed to update vehicle details.');
			return;
		}
	}

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

		$input = $this->input->post();
		checkValidation($input, [['field' => 'user_id', 'label' => 'User ID', 'rules' => 'required']]);

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

		$documentFields = [
			'pancard' => ['folder' => 'Pan', 'db_field' => 'driver_pancard', 'status_field' => 'pancard_status'],
			'driving_licence' => ['folder' => 'Licence', 'db_field' => 'driving_license_image', 'status_field' => 'driving_license_status'],
			'vehicle_rc' => ['folder' => 'Rc', 'db_field' => 'vehicle_rc', 'status_field' => 'rc_status'],
			'insurance' => ['folder' => 'Insurance', 'db_field' => 'vehicle_endurance', 'status_field' => 'insurance_status'],
		];

		$data = [];

		foreach ($documentFields as $field => $info) {
			if (!empty($_FILES[$field]['name'])) {
				$time = time();
				$ext = pathinfo($_FILES[$field]['name'], PATHINFO_EXTENSION);
				$uploadFolder = $info['folder'];
				$dbField = $info['db_field'];
				$statusField = $info['status_field'];
				$imagePath = "uploads/images/$uploadFolder/img_$time.$ext";

				$this->my_upload->upload($_FILES[$field]);
				if ($this->my_upload->uploaded) {
					$this->my_upload->allowed = ['image/*'];
					$this->my_upload->file_new_name_body = "img_$time";
					$this->my_upload->jpeg_quality = 100;
					$this->my_upload->image_resize = true;
					$this->my_upload->image_ratio_fill = true;
					$this->my_upload->image_x = 270;
					$this->my_upload->image_y = 168;
					$this->my_upload->process("uploads/images/$uploadFolder/");

					if ($this->my_upload->processed) {
						$this->my_upload->clean();
						if (!empty($user->$dbField)) {
							unlink($user->$dbField);
						}
						$data[$dbField] = $imagePath;
						$data[$statusField] = 0;  
					} else {
						outputJSON(200, 'error', "Error processing $field image");
						return;
					}
				} else {
					outputJSON(200, 'error', "$field image upload failed");
					return;
				}
			} 
		}

		if (!empty($data) && $this->common_model->Update('tbl_driver', $data, ['id' => $user_id])) {
			outputJSON(200, 'success', 'Document updated successfully.');
		} else {
			outputJSON(200, 'error', 'Failed to update documents.');
		}
	}


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

		$rules = [
			['field' => 'user_id', 'label' => 'Driver ID', 'rules' => 'required'], 
			['field' => 'booking_id', 'label' => 'Booking ID', 'rules' => 'required']
		];

		checkValidation($input, $rules);
		$check=$this->db->where('id',$input['user_id'])->get('tbl_driver');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'Driver not found with this ID.');
			return;
		}
		$checkreq=$this->db->where('booking_id',$input['booking_id'])->where('driver_id',$input['driver_id'])->get('tbl_userwise_cabrequest');
		if($checkreq->num_rows()==0){
			outputJSON(200, 'error', 'Request not found with this booking ID.');
			return;
		}
		$checkride=$this->db->where('book_id',$input['booking_id'])->get('tbl_booking');
		if($checkride->num_rows()==0){
			outputJSON(200, 'error', 'Booking not found with this booking ID.');
			return;
		}
		$booking=$checkride->row();
		if($booking->driver_id!=0 && $booking->send_request_id!=0){
			outputJSON(200, 'error', 'Ride already accepted by another driver.');
			return;
		}
		$req=$checkreq->row();
		$data=[
			'driver_away'=>$req->driver_away,
            'send_request_id'=>$req->id,
            'driver_id'=>$driver_id,
		];
		$this->common_model->Update('tbl_booking', $data,['book_id'=>$booking_id]);
		$this->common_model->Update('tbl_userwise_cabrequest', ['status',1],['booking_id'=>$booking_id,'driver_id'=>$driver_id]);
		outputJSON(200, 'success', 'Ride accepted successfully.');
		
	}
    

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

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

		checkValidation($input, $rules);
		$check=$this->db->where('id',$input['user_id'])->get('tbl_driver');
		if($check->num_rows()==0){
			outputJSON(200, 'error', 'Driver not found with this ID.');
			return;
		}
		$from=$input['start_date'] ?? null;
		$to=$input['end_date'] ?? null;
		$driver=$check->row();
		$activeMinutes = $driver->total_active_minutes ?? 0;

		if ($activeMinutes < 60) {
			$active_hours= "{$activeMinutes} min";
		} else {
			$hours = floor($activeMinutes / 60);
			$minutes = $activeMinutes % 60;
			
			if ($minutes > 0) {
				$active_hours= "{$hours} h {$minutes} min";
			} else {
				$active_hours= "{$hours} h";
			}
		}
		if(empty($from) and empty($to)){
			$earning=$this->db->select('SUM(amount) as total_earning')->where('user_id',$input['user_id'])->where('transaction_type','credit')->get('driver_wallet_transactions')->row();
			$total_completed_ride=$this->db->where('driver_id',$input['user_id'])->where('ride_status',2)->where('is_cancle',0)->get('tbl_booking')->num_rows();
		}else{
			 $from_date = $from . ' 00:00:00';
			$to_date = $to . ' 23:59:59';

			$earning = $this->db->select('SUM(amount) as total_earning')
				->where('user_id', $input['user_id'])
				->where('transaction_type', 'credit')
				->where('created_at >=', $from_date)
				->where('created_at <=', $to_date)
				->get('driver_wallet_transactions')->row();

			$total_completed_ride = $this->db->where('driver_id', $input['user_id'])
				->where('ride_status', 2)
				->where('is_cancle', 0)
				->where('entry_date >=', $from_date)
				->where('entry_date <=', $to_date)
				->get('tbl_booking')->num_rows();
		}
		$bookings = $this->db
			->select('r.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,u.f_name as username')
			->from('tbl_userwise_cabrequest as r')
			->join('tbl_booking as b', 'r.booking_id = b.book_id AND r.driver_id = b.driver_id')
			->join('tbl_user as u', 'u.id = b.user_id')
			->where(['r.driver_id'=> $input['user_id'],'r.status'=>1,'b.ride_status'=>0,'b.is_cancle'=>0])
			->where_in('b.booking_type', ['pre_booking','rental'])
			->order_by('r.selecteddate', 'DESC')
			->limit(10)
			->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);
		}


		
		$data=[
			'total_earning'=>$earning->total_earning ?? '0',
            'active_hours'=>$active_hours,
            'total_completed_ride'=>$total_completed_ride,
            'upcoming_bookings'=>$bookings,
		];
		outputJSON(200, 'success', 'Data fetched successfully.',$data);
		
	}
    

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

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

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

		$bookings = $this->db
			->select('r.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,u.f_name as username')
			->from('tbl_userwise_cabrequest as r')
			->join('tbl_booking as b', 'r.booking_id = b.book_id AND r.driver_id = b.driver_id')
			->join('tbl_user as u', 'u.id = b.user_id')
			->where(['r.driver_id'=> $input['user_id'],'r.status'=>1,'b.ride_status'=> 0,'b.is_cancle'=> 0])
			->where_in('b.booking_type', ['pre_booking','rental'])
			->order_by('r.selecteddate', 'DESC')
			->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', 'Data fetched successfully.',$bookings);
		
	}
    
	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' => 'Driver ID', 'rules' => 'required']
		];

		checkValidation($input, $rules);

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

		$from = $input['start_date'] ?? null;
		$to = $input['end_date'] ?? null;
		$search = $input['search'] ?? 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, b.paymenttype, u.f_name as username, 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')
			->from('tbl_booking as b')
			->join('tbl_user as u', 'b.user_id = u.id')
			->join('tbl_userwise_cabrequest as r', 'b.driver_id = r.driver_id and b.book_id = r.booking_id')
			->where('b.driver_id', $input['user_id'])
			->where('b.ride_status', 2)
			->where('b.is_cancle', 0);

		if (!empty($booking_type)) {
			$this->db->where('b.booking_type', $booking_type);
		}

		if (!empty($from) && !empty($to)) {
			$from_date = $from . ' 00:00:00';
			$to_date = $to . ' 23:59:59';
			$this->db->where('b.entry_date >=', $from_date);
			$this->db->where('b.entry_date <=', $to_date);
		}

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

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

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

		$query = [];
		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));

			$query[] = [
				'booking_id' => $row->booking_id,
				'booking_type' => $row->booking_type,
				'username' => $row->username,
				'user_journey_distance' => $row->user_journey_distance,
				'travel_time' => $row->travel_time,
				'grand_total' => $row->grand_total,
				'booking_date' => $booking_date,
				'payment_type' => $row->paymenttype,
				'waypoints' => json_decode($row->waypoints, true),
			];
		}

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

		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|integer'],
		];
		checkValidation($input, $rules);
		$user_id = (int)$input['user_id'];

		$sql = "
			SELECT b.book_id,
				d.driver_id         AS d_id,
				u.f_name            AS username,
				r.travel_time_to_pickup_location,
				r.driver_away,
				r.waypoints,
				r.user_journey_distance,
				b.travel_time,
				d.wallet_amount,
				b.total_fare,
				b.conv_charge,
				b.grand_total,
				b.paymenttype,
				vt.active_image     AS vehicle_type_image,
				vt.type             AS vehicle_type
			FROM tbl_booking AS 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_vehicletype vt 
				ON vt.id = b.type_id 
			INNER JOIN tbl_user u 
				ON u.id = b.user_id
			WHERE b.driver_id = ? and b.is_cancle=0 AND b.ride_status NOT IN (2, 3) order by b.id desc limit 1
		";
		$driverR = $this->db->query($sql, [$user_id])->row();

		if (!$driverR) {
			outputJSON(200, 'success', 'No ride data found.');
			return;
		}

		$response = [
			'booking_id'               => $driverR->book_id,
			'is_you'                   => true,
			'driver_id'                => (string)$driverR->d_id,
			'username'                 => $driverR->username,
			'pickup_arriving_time'     => $driverR->travel_time_to_pickup_location,
			'pickup_location_distance' => (string)$driverR->driver_away,
			'waypoints'                => $driverR->waypoints ? json_decode($driverR->waypoints) : [],
			'user_journey_distance'    => (string)$driverR->user_journey_distance,
			'vehicle_type_image'       => IMAGE_URL.$driverR->vehicle_type_image,
			'vehicle_type'             => $driverR->vehicle_type,
			'travel_time'              => $driverR->travel_time,
			'total_fare'               => (string)$driverR->total_fare,
			'conv_charge'              => (string)$driverR->conv_charge,
			'grand_total'              => (string)$driverR->grand_total,
			'payment_type'             => $driverR->paymenttype,
		];

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

	public function add_bank()
	{
		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' => 'bank_name', 'label' => 'Bank name', 'rules' => 'required'],
			['field' => 'account_holder_name', 'label' => 'Account holder name', 'rules' => 'required'],
			['field' => 'account_no', 'label' => 'Account number', 'rules' => 'required'],
			['field' => 'account_type', 'label' => 'Account type', 'rules' => 'required'],
			['field' => 'ifsc_code', 'label' => 'IFSC Code', 'rules' => 'required'],
			['field' => 'branch_address', 'label' => 'Branch name', 'rules' => 'required']
		];

		checkValidation($input, $rules);

		$user_id = $input['user_id'];

		$data = [
			'driver_id'            => $user_id,
			'bank_name'            => $input['bank_name'],
			'account_holder_name'  => $input['account_holder_name'],
			'account_number'       => $input['account_no'],
			'account_type'         => $input['account_type'],
			'ifsc'                 => $input['ifsc_code'],
			'branch'               => $input['branch_address'],
		];
		$check = $this->db->where('id', $user_id)->get('tbl_driver')->row();
		if(!$check){
			outputJSON(200, 'error', 'Driver not found with provided driver id.');
			return;
		}

		$duplicate = $this->db->where('driver_id', $user_id)
                          ->where('account_number', $input['account_no'])
						  ->where('delete_status', 'false')
                          ->get('driver_bank_details')
                          ->row();

		if ($duplicate) {
			outputJSON(200, 'error', 'This bank account already exists for this driver.');
			return;
		}

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

		outputJSON(200, 'success', 'Bank details added successfully.');
		
	}

	public function remove_bank_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'],
        ['field' => 'account_no', 'label' => 'Account number', 'rules' => 'required']
    ];

    checkValidation($input, $rules);

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

    // Check driver exists
    $driver = $this->db->where('id', $user_id)
                       ->get('tbl_driver')
                       ->row();

    if (!$driver) {
        outputJSON(404, 'error', 'Driver not found with provided driver id.');
        return;
    }

    // Check bank account exists & not already deleted
    $bank = $this->db->where('driver_id', $user_id)
                     ->where('account_number', $account_no)
                     ->where('delete_status', 'false')
                     ->get('driver_bank_details')
                     ->row();

    if (!$bank) {
        outputJSON(404, 'error', 'Bank account not found.');
        return;
    }

    // ✅ Soft delete (update instead of delete)
    $this->db->where('driver_id', $user_id)
             ->where('account_number', $account_no)
             ->update('driver_bank_details', [
                 'delete_status' => 'true',
                 'deleted_at'    => date('Y-m-d H:i:s')
             ]);

    outputJSON(200, 'success', 'Bank account removed successfully.');
}



	public function get_bank_details()
{
    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_id = $input['user_id'];

    // Check driver exists
    $driver = $this->db->where('id', $user_id)->get('tbl_driver')->row();

    if (!$driver) {
        outputJSON(200, 'error', 'Driver not found with provided driver id.');
        return;
    }

    // Get bank details (keys same as yours)
    $bank = $this->db
        ->select('
            bank_name,
            account_number as account_no,
            ifsc as ifsc_code,
            branch as branch_address,
            account_type,
            account_holder_name
        ')
        ->where('driver_id', $user_id)
		->where('delete_status', 'false')
        ->get('driver_bank_details')
        ->result_array();

    if (empty($bank)) {
        outputJSON(200, 'error', 'Bank details not found.');
        return;
    }

    // Format response structure
    $response = [
        'bank_detail' => $bank
    ];

    // Custom response format
    echo json_encode([
        'status'      => 'success',
        'status_code' => 200,
        'message'     => 'Data Found',
        'data'        => $response
    ]);
}

public function notification_list()
{
	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);

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

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

	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', $driver->row()->driver_id)
		->where('user_type', 'driver')
		->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);

	$driver = $this->db->where('driver_id', $input['user_id'])->get('tbl_driver');
	if ($driver->num_rows() == 0) {
		outputJSON(200, 'error', 'Driver 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', $driver->row()->driver_id);
		$this->db->where('user_type', 'driver');
		$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', $driver->row()->driver_id);
		$this->db->where('user_type', 'driver');
		$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 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_driver')
                       ->row();

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

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

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

public function send_test_notification()
{
    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' => 'title', 'label' => 'Title', 'rules' => 'required'],
        ['field' => 'body', 'label' => 'Body', 'rules' => 'required']
    ];

    checkValidation($input, $rules);

    // Check driver
    $driver = $this->db->where('id', $input['user_id'])
                       ->get('tbl_driver')
                       ->row();

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

    if (empty($driver->f_token_app)) {
        outputJSON(200, 'error', 'FCM token not found for this driver.');
        return;
    }

    // Load Firebase Library
    $this->load->library('Firebase');

    // Send Notification
    $response = $this->firebase->send(
        $driver->f_token_app,
        $input['title'],
        $input['body']
    );

    // Optional: Save notification in DB
    $insertData = [
        'event_key'   => 'test_notification',
        'title'       => $input['title'],
        'body'        => $input['body'],
        'icon'        => '',
        'data_json'   => json_encode([]),
        'user_id'     => $input['user_id'],
        'user_type'     => 'driver',
    ];

    $this->db->insert('notifications', $insertData);

    outputJSON(200, 'success', 'Notification sent successfully.', $response);
}
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' => 'Driver ID', 'rules' => 'required']
    ];

    checkValidation($input, $rules);

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

    $this->db->where('driver_id', $input['user_id']);
    $this->db->where_in('ride_status', [0,1]);
    $this->db->where('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('booking_type', 'book_now');
            $this->db->where('DATE(entry_date)', date('Y-m-d'));
        $this->db->group_end();
        $this->db->or_group_start();
            $this->db->where_in('booking_type', ['pre_booking', 'rental']);
            $this->db->where('is_active_schedule_ride', 1);
        $this->db->group_end();
    $this->db->group_end();
    
    $this->db->order_by('id', 'DESC');
    $this->db->limit(1);
    
    $booking = $this->db->get('tbl_booking')->row();

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

    $details = $this->db
        ->select('
            b.book_id,
            b.ride_status,
            b.user_id,
            b.booking_type,
            u.f_name as username,
            r.travel_time_to_pickup_location,
            r.driver_away,
            b.waypoints,
            b.user_journey_distance,
            b.travel_time,
            b.total_fare,
            b.conv_charge,
            b.grand_total,
            b.paymenttype,
            d.wallet_amount,
            d.id as d_id,
            d.driver_id as driver_string_id,
			u.id as user_id,
			u.user_id as user_string_id,
            vt.active_image,
            vt.type as vehicle_type
        ')
        ->from('tbl_booking as b')
        ->join('tbl_userwise_cabrequest r', 'r.driver_id = b.driver_id AND r.booking_id = b.book_id')
        ->join('tbl_driver d', 'd.id = b.driver_id')
        ->join('tbl_vehicletype vt', 'vt.id = b.type_id')
        ->join('tbl_user u', 'u.id = b.user_id')
        ->where('b.book_id', $booking->book_id)
        ->get()
        ->row();

    $data = [
        'has_active_booking' => true,
		'driver_id' => (string) $details->d_id,
		'driver_string_id' => $details->driver_string_id,
		'user_id' => (string) $details->user_id,
		'user_string_id' => $details->user_string_id,
        'ride_status' => (int) $details->ride_status,
        'booking_id' => (string) $details->book_id,
		'booking_type' => $details->booking_type,
        'username' => $details->username ?? '',
        'pickup_arriving_time' => (string) ($details->travel_time_to_pickup_location ?? ''),
        'pickup_location_distance' => (string) ($details->driver_away ?? ''),

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

        'user_journey_distance' => (string) ($details->user_journey_distance ?? ''),
        'travel_time' => (string) ($details->travel_time ?? ''),

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

        'vehicle_type' => $details->vehicle_type ?? '',

        'total_fare' => (string) ($details->total_fare ?? ''),
        'conv_charge' => (string) ($details->conv_charge ?? ''),
        'grand_total' => (string) ($details->grand_total ?? ''),

        'payment_type' => $details->paymenttype ?? '',
        'wallet_amount' => (string) ($details->wallet_amount ?? ''),
		'ongoing' => [
        'driver_id' => (string) $input['user_id'],
        'username' => $details->username ?? '',
        'booking_type' => $details->booking_type ?? '',
        'booking_type_title' => $details->vehicle_type ?? '',
        'user_journey_distance' => (string) ($details->user_journey_distance ?? ''),
        'total_fare' => (string) ($details->total_fare ?? ''),
        'booking_id' => (string) $details->book_id,
        'waypoints' => !empty($details->waypoints)
            ? json_decode($details->waypoints, true)
            : []
    ]
    ];

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

?>