'failure', 'message' => 'Unauthorized: invalid API key']); exit; } $input = []; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $raw = file_get_contents('php://input'); $input = json_decode($raw, true) ?: []; } else { $input = $_GET; } $queryType = $input['query_type'] ?? ''; $phone = preg_replace('/[^0-9]/', '', $input['phone'] ?? ''); $driverId = $input['driver_id'] ?? ''; $tripId = $input['trip_id'] ?? ''; $limit = min((int)($input['limit'] ?? 10), 50); if (empty($queryType)) { http_response_code(400); echo json_encode(['status' => 'failure', 'message' => 'query_type is required. Options: driver_info, driver_trips, driver_stats, trip_detail']); exit; } $validTypes = ['driver_info', 'driver_trips', 'driver_stats', 'trip_detail']; if (!in_array($queryType, $validTypes, true)) { http_response_code(400); echo json_encode(['status' => 'failure', 'message' => 'Invalid query_type. Options: ' . implode(', ', $validTypes)]); exit; } try { global $encryptionHelper; $mainDb = Database::get('main'); $rideDb = Database::get('ride'); // ======================================================================== if ($queryType === 'driver_info') { if (empty($phone)) { jsonError('phone parameter is required'); } $encryptedPhone = $encryptionHelper->encryptData($phone); $stmt = $mainDb->prepare(" SELECT d.id, d.phone, d.first_name, d.last_name, d.name_arabic, d.status, d.created_at, d.birthdate, d.gender, d.site, cr.id as car_id, cr.make, cr.model, cr.year, cr.car_plate, cr.color, cr.color_hex, cr.fuel, cr.vin, cr.status as car_status, cr.expiration_date FROM driver d LEFT JOIN CarRegistration cr ON cr.driverID = d.id WHERE d.phone = :phone OR d.email LIKE :phoneLike LIMIT 1 "); $stmt->execute([ ':phone' => $encryptedPhone, ':phoneLike' => $phone . '%', ]); $driver = $stmt->fetch(PDO::FETCH_ASSOC); if (!$driver) { echo json_encode(['status' => 'success', 'data' => null, 'message' => 'Driver not found']); exit; } $decrypt = function($val) use ($encryptionHelper) { return $val ? $encryptionHelper->decryptData($val) : $val; }; echo json_encode([ 'status' => 'success', 'data' => [ 'driver_id' => $driver['id'], 'phone' => $decrypt($driver['phone']), 'first_name' => $decrypt($driver['first_name']), 'last_name' => $decrypt($driver['last_name']), 'name_arabic' => $decrypt($driver['name_arabic']), 'gender' => $decrypt($driver['gender']), 'birthdate' => $driver['birthdate'], 'status' => $driver['status'], 'site' => $decrypt($driver['site']), 'registered_at' => $driver['created_at'], 'car' => $driver['car_id'] ? [ 'id' => $driver['car_id'], 'make' => $driver['make'], 'model' => $driver['model'], 'year' => $driver['year'], 'plate' => $driver['car_plate'], 'color' => $driver['color'], 'color_hex' => $driver['color_hex'], 'fuel' => $driver['fuel'], 'vin' => $decrypt($driver['vin']), 'status' => $driver['car_status'], 'expiration_date' => $driver['expiration_date'], ] : null, ], ], JSON_UNESCAPED_UNICODE); exit; } // ======================================================================== if ($queryType === 'driver_trips') { if (empty($driverId) && empty($phone)) { jsonError('driver_id or phone is required'); } if (empty($driverId) && !empty($phone)) { $encryptedPhone = $encryptionHelper->encryptData($phone); $stmt = $mainDb->prepare("SELECT id FROM driver WHERE phone = :phone LIMIT 1"); $stmt->execute([':phone' => $encryptedPhone]); $driverRow = $stmt->fetch(PDO::FETCH_ASSOC); if (!$driverRow) { echo json_encode(['status' => 'success', 'data' => [], 'message' => 'Driver not found']); exit; } $driverId = $driverRow['id']; } $stmt = $rideDb->prepare(" SELECT id, start_location, end_location, date, time, endtime, price, price_for_driver, price_for_passenger, status, paymentMethod, carType, distance, created_at FROM ride WHERE driver_id = :driver_id ORDER BY created_at DESC LIMIT :lim "); $stmt->bindValue(':driver_id', $driverId, PDO::PARAM_STR); $stmt->bindValue(':lim', $limit, PDO::PARAM_INT); $stmt->execute(); $trips = $stmt->fetchAll(PDO::FETCH_ASSOC); echo json_encode([ 'status' => 'success', 'data' => $trips, 'count' => count($trips), ], JSON_UNESCAPED_UNICODE); exit; } // ======================================================================== if ($queryType === 'driver_stats') { if (empty($driverId) && empty($phone)) { jsonError('driver_id or phone is required'); } if (empty($driverId) && !empty($phone)) { $encryptedPhone = $encryptionHelper->encryptData($phone); $stmt = $mainDb->prepare("SELECT id FROM driver WHERE phone = :phone LIMIT 1"); $stmt->execute([':phone' => $encryptedPhone]); $driverRow = $stmt->fetch(PDO::FETCH_ASSOC); if (!$driverRow) { echo json_encode(['status' => 'success', 'data' => null, 'message' => 'Driver not found']); exit; } $driverId = $driverRow['id']; } $stmt = $rideDb->prepare(" SELECT COUNT(*) as total_trips, COALESCE(SUM(price_for_driver), 0) as total_earnings, COALESCE(SUM(price_for_passenger), 0) as total_collected, COALESCE(AVG(price_for_driver), 0) as avg_earning_per_trip, COALESCE(SUM(distance), 0) as total_distance, COUNT(CASE WHEN status = 'completed' THEN 1 END) as completed_trips, COUNT(CASE WHEN status = 'cancelled' THEN 1 END) as cancelled_trips FROM ride WHERE driver_id = :driver_id "); $stmt->execute([':driver_id' => $driverId]); $stats = $stmt->fetch(PDO::FETCH_ASSOC); $driverStmt = $mainDb->prepare("SELECT status, created_at FROM driver WHERE id = :id LIMIT 1"); $driverStmt->execute([':id' => $driverId]); $driverStatus = $driverStmt->fetch(PDO::FETCH_ASSOC); echo json_encode([ 'status' => 'success', 'data' => [ 'driver_id' => $driverId, 'status' => $driverStatus['status'] ?? 'unknown', 'registered_at' => $driverStatus['created_at'] ?? null, 'stats' => [ 'total_trips' => (int)$stats['total_trips'], 'completed_trips' => (int)$stats['completed_trips'], 'cancelled_trips' => (int)$stats['cancelled_trips'], 'total_earnings' => (float)$stats['total_earnings'], 'total_collected' => (float)$stats['total_collected'], 'avg_earning_per_trip' => (float)$stats['avg_earning_per_trip'], 'total_distance_km' => (float)$stats['total_distance'], ], ], ], JSON_UNESCAPED_UNICODE); exit; } // ======================================================================== if ($queryType === 'trip_detail') { if (empty($tripId)) { jsonError('trip_id is required'); } $stmt = $rideDb->prepare(" SELECT r.*, p.first_name as passenger_first_name, p.last_name as passenger_last_name, p.phone as passenger_phone FROM ride r LEFT JOIN driver p ON p.id = r.passenger_id WHERE r.id = :id LIMIT 1 "); $stmt->execute([':id' => $tripId]); $trip = $stmt->fetch(PDO::FETCH_ASSOC); if (!$trip) { echo json_encode(['status' => 'success', 'data' => null, 'message' => 'Trip not found']); exit; } echo json_encode([ 'status' => 'success', 'data' => $trip, ], JSON_UNESCAPED_UNICODE); exit; } } catch (\Exception $e) { error_log("[Nabeh Query Error] " . $e->getMessage()); http_response_code(500); echo json_encode(['status' => 'failure', 'message' => 'Internal server error']); }