false, 'message' => 'method_not_allowed']); exit; } require_once __DIR__ . '/../includes/Database.php'; require_once __DIR__ . '/../includes/Auth.php'; require_once __DIR__ . '/../includes/Logger.php'; // Authenticate — requires device key (Caller Android App) Auth::requireAuth('device'); $deviceId = $_GET['device_id'] ?? null; if (!$deviceId) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'missing_device_id']); RequestLogger::log('pending-call', 'GET', $_GET, 400, 'missing_device_id'); exit; } $db = Database::getInstance(); try { // Verify device exists and is active $stmt = $db->prepare( "SELECT id, device_id, is_active FROM caller_devices WHERE device_id = ?" ); $stmt->execute([$deviceId]); $device = $stmt->fetch(); if (!$device || !$device['is_active']) { http_response_code(403); echo json_encode(['success' => false, 'message' => 'device_not_registered_or_inactive']); RequestLogger::log('pending-call', 'GET', $_GET, 403, 'invalid_device'); exit; } // Update last_seen $stmt = $db->prepare("UPDATE caller_devices SET last_seen = NOW() WHERE device_id = ?"); $stmt->execute([$deviceId]); // Find oldest pending flash call task // Priority: tasks assigned to this device first, then unassigned tasks $stmt = $db->prepare( "SELECT id, phone, caller_id, expires_at FROM otp_requests WHERE method = 'flash_call' AND status = 'pending' AND expires_at > NOW() AND (device_id IS NULL OR device_id = ?) ORDER BY CASE WHEN device_id = ? THEN 0 ELSE 1 END, created_at ASC LIMIT 1" ); $stmt->execute([$deviceId, $deviceId]); $task = $stmt->fetch(); if (!$task) { echo json_encode(['success' => true, 'task_id' => null]); RequestLogger::log('pending-call', 'GET', $_GET, 200); exit; } // Claim this task — update status and assign device $stmt = $db->prepare( "UPDATE otp_requests SET status = 'calling', device_id = ?, updated_at = NOW() WHERE id = ? AND status = 'pending'" ); $stmt->execute([$deviceId, $task['id']]); // Check if update affected any row (race condition handling) if ($stmt->rowCount() === 0) { // Another device claimed it first echo json_encode(['success' => true, 'task_id' => null]); RequestLogger::log('pending-call', 'GET', $_GET, 200); exit; } // Calculate remaining timeout $expiresAt = new \DateTime($task['expires_at']); $now = new \DateTime(); $timeoutSeconds = max(10, $expiresAt->getTimestamp() - $now->getTimestamp()); echo json_encode([ 'success' => true, 'task_id' => (int) $task['id'], 'phone' => $task['phone'], 'caller_id' => $task['caller_id'], 'timeout_seconds' => $timeoutSeconds, ]); RequestLogger::log('pending-call', 'GET', $_GET, 200); } catch (\Throwable $e) { error_log('pending-call error: ' . $e->getMessage()); http_response_code(500); echo json_encode(['success' => false, 'message' => 'internal_error']); RequestLogger::log('pending-call', 'GET', $_GET, 500, $e->getMessage()); }