241 lines
12 KiB
PHP
241 lines
12 KiB
PHP
<?php
|
|
|
|
namespace App\Core\Flows;
|
|
|
|
use App\Services\SiroService;
|
|
|
|
/**
|
|
* ComplaintFlow — Submit a trip complaint via WhatsApp
|
|
*
|
|
* Flow: start → await_description → await_ride → await_confirmation → finished
|
|
*
|
|
* Steps:
|
|
* start → resolve user, ask for problem description
|
|
* await_description → collect description text (or voice transcription)
|
|
* await_ride → fetch recent rides, let user pick one
|
|
* await_confirmation → show full details, ask to confirm
|
|
* finished → show AI analysis result
|
|
*/
|
|
class ComplaintFlow extends BaseFlow
|
|
{
|
|
public function handleStep(string $step, array $messageData, array &$context): FlowResult
|
|
{
|
|
$phone = $messageData['phone'] ?? '';
|
|
$text = $messageData['body'] ?? $messageData['text'] ?? '';
|
|
$country = $context['country'] ?? SiroService::detectCountry($phone);
|
|
|
|
switch ($step) {
|
|
// ─────────────────────────────────────────────────
|
|
// START: resolve user, ask for description
|
|
// ─────────────────────────────────────────────────
|
|
case 'start':
|
|
$context['country'] = $country;
|
|
|
|
// Resolve user type via Siro
|
|
try {
|
|
$driverData = SiroService::checkDriverStatus($phone, $country);
|
|
if ($driverData && !empty($driverData['data']['driver_id'])) {
|
|
$context['user_type'] = 'driver';
|
|
$context['user_id'] = $driverData['data']['driver_id'];
|
|
$context['user_name'] = $driverData['data']['name'] ?? '';
|
|
} else {
|
|
$context['user_type'] = 'passenger';
|
|
}
|
|
} catch (\Exception $e) {
|
|
$context['user_type'] = 'driver';
|
|
}
|
|
|
|
return new FlowResult(
|
|
"أهلاً بك في نظام الشكاوى.\n\n"
|
|
. "📝 يرجى وصف المشكلة التي حدثت بالتفصيل.\n"
|
|
. "مثال: \"السائق تأخر 20 دقيقة واتصلت فيه وما رد\"\n"
|
|
. "يمكنك إرسال النص أو تسجيل مقطع صوتي.\n\n"
|
|
. "🟡 للخروج اكتب: إلغاء",
|
|
"await_description"
|
|
);
|
|
|
|
// ─────────────────────────────────────────────────
|
|
// AWAIT_DESCRIPTION: collect complaint text
|
|
// ─────────────────────────────────────────────────
|
|
case 'await_description':
|
|
if (empty(trim($text))) {
|
|
return new FlowResult(
|
|
"الرجاء كتابة وصف المشكلة أو تسجيل مقطع صوتي:",
|
|
"await_description"
|
|
);
|
|
}
|
|
|
|
$context['complaint_text'] = trim($text);
|
|
|
|
// Fetch recent rides from Siro
|
|
try {
|
|
$rides = SiroService::getUserRides($country, $phone, 5);
|
|
$context['rides'] = $rides ?? [];
|
|
} catch (\Exception $e) {
|
|
$context['rides'] = [];
|
|
}
|
|
|
|
if (empty($context['rides'])) {
|
|
return new FlowResult(
|
|
"تم حفظ وصف المشكلة. ✅\n\n"
|
|
. "لم نتمكن من العثور على رحلات حديثة لحسابك.\n"
|
|
. "الرجاء إرسال رقم الرحلة (مثال: 831):",
|
|
"await_ride"
|
|
);
|
|
}
|
|
|
|
$rideList = "تم حفظ وصف المشكلة. ✅\n\n"
|
|
. "🚖 آخر رحلاتك:\n\n";
|
|
foreach ($context['rides'] as $i => $r) {
|
|
$num = $i + 1;
|
|
$date = $r['date'] ?? '';
|
|
$time = $r['time'] ?? '';
|
|
$from = $r['start_location'] ?? '---';
|
|
$to = $r['end_location'] ?? '---';
|
|
$price = $r['price'] ?? '0';
|
|
$status = $r['status'] ?? '';
|
|
$rideList .= "{$num}. رحلة #{$r['id']} | {$date} {$time}\n"
|
|
. " من: {$from} → إلى: {$to}\n"
|
|
. " السعر: {$price} | الحالة: {$status}\n\n";
|
|
}
|
|
$rideList .= "الرجاء إرسال رقم الرحلة من القائمة (1-{$num})\n"
|
|
. "أو اكتب رقم الرحلة كاملاً (مثال: 831):";
|
|
|
|
return new FlowResult($rideList, "await_ride");
|
|
|
|
// ─────────────────────────────────────────────────
|
|
// AWAIT_RIDE: let user pick a ride
|
|
// ─────────────────────────────────────────────────
|
|
case 'await_ride':
|
|
$selectedRide = null;
|
|
$rides = $context['rides'] ?? [];
|
|
|
|
// Check if user entered a list number (1, 2, 3...)
|
|
$cleanNum = preg_replace('/[^0-9]/', '', $text);
|
|
if (!empty($cleanNum) && is_numeric($cleanNum)) {
|
|
$index = (int)$cleanNum - 1;
|
|
if (isset($rides[$index])) {
|
|
$selectedRide = $rides[$index];
|
|
}
|
|
// If not found in list, try as ride_id directly
|
|
if (!$selectedRide) {
|
|
foreach ($rides as $r) {
|
|
if ((string)$r['id'] === $cleanNum) {
|
|
$selectedRide = $r;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// If still not found, try the number as ride_id
|
|
if (!$selectedRide) {
|
|
$selectedRide = ['id' => $cleanNum];
|
|
}
|
|
}
|
|
|
|
if (!$selectedRide) {
|
|
return new FlowResult(
|
|
"لم نتعرف على الرقم. الرجاء إرسال رقم الرحلة من القائمة:",
|
|
"await_ride"
|
|
);
|
|
}
|
|
|
|
$context['ride_id'] = $selectedRide['id'];
|
|
$context['ride_details'] = $selectedRide;
|
|
|
|
$locFrom = $selectedRide['start_location'] ?? '---';
|
|
$locTo = $selectedRide['end_location'] ?? '---';
|
|
$date = $selectedRide['date'] ?? '---';
|
|
$time = $selectedRide['time'] ?? '---';
|
|
$price = $selectedRide['price'] ?? '---';
|
|
$status = $selectedRide['status'] ?? '---';
|
|
|
|
return new FlowResult(
|
|
"🚖 تفاصيل الرحلة المحددة:\n"
|
|
. "• رقم الرحلة: {$selectedRide['id']}\n"
|
|
. "• التاريخ: {$date} {$time}\n"
|
|
. "• من: {$locFrom}\n"
|
|
. "• إلى: {$locTo}\n"
|
|
. "• السعر: {$price}\n"
|
|
. "• الحالة: {$status}\n\n"
|
|
. "📋 وصف المشكلة:\n"
|
|
. "{$context['complaint_text']}\n\n"
|
|
. "هل تريد تأكيد إرسال الشكوى؟\n"
|
|
. "✅ أرسل: تأكيد\n"
|
|
. "🔄 أرسل: تعديل (لإعادة كتابة الوصف)\n"
|
|
. "🟡 أرسل: إلغاء",
|
|
"await_confirmation"
|
|
);
|
|
|
|
// ─────────────────────────────────────────────────
|
|
// AWAIT_CONFIRMATION: confirm and submit
|
|
// ─────────────────────────────────────────────────
|
|
case 'await_confirmation':
|
|
$clean = trim(mb_strtolower($text));
|
|
|
|
if (in_array($clean, ['تعديل', 'edit', 'تعديل الوصف'])) {
|
|
return new FlowResult(
|
|
"الرجاء إرسال وصف المشكلة الجديد:",
|
|
"await_description"
|
|
);
|
|
}
|
|
|
|
if (!in_array($clean, ['تأكيد', 'نعم', 'اكيد', 'ok', 'yes', 'confirm', 'تاكيد', 'okay'])) {
|
|
return new FlowResult(
|
|
"❌ لم يتم التأكيد.\n"
|
|
. "✅ للتأكيد أرسل: تأكيد\n"
|
|
. "🔄 للتعديل أرسل: تعديل\n"
|
|
. "🟡 للإلغاء أرسل: إلغاء",
|
|
"await_confirmation"
|
|
);
|
|
}
|
|
|
|
// Submit complaint via Siro
|
|
try {
|
|
$result = SiroService::submitComplaint(
|
|
$country,
|
|
$phone,
|
|
$context['ride_id'],
|
|
$context['complaint_text']
|
|
);
|
|
|
|
if ($result && ($result['status'] ?? '') === 'success') {
|
|
$aiResult = $result['ai_result'] ?? [];
|
|
$report = $result['report'] ?? [];
|
|
$reportTitle = $report['title'] ?? '';
|
|
$reportBody = $report['body'] ?? '';
|
|
|
|
$reply = "✅ تم إرسال شكواك بنجاح!\n\n"
|
|
. "📋 نتيجة التحليل:\n"
|
|
. "• تصنيف الشكوى: " . ($aiResult['complaint_type'] ?? '---') . "\n"
|
|
. "• الطرف المخطئ: " . ($aiResult['fault_determination'] ?? '---') . "\n"
|
|
. "• طبيعة الشكوى: " . ($aiResult['complaint_nature'] ?? '---') . "\n\n";
|
|
|
|
if ($reportBody) {
|
|
$reply .= "📄 {$reportTitle}\n{$reportBody}\n\n";
|
|
}
|
|
|
|
$reply .= "سيتم التواصل معك من قبل فريق الدعم إذا لزم الأمر.";
|
|
|
|
return new FlowResult($reply, "finished", true);
|
|
}
|
|
|
|
return new FlowResult(
|
|
"⚠️ حدث خطأ في إرسال الشكوى. يرجى المحاولة مرة أخرى أو التواصل مع الدعم الفني.",
|
|
"finished",
|
|
true
|
|
);
|
|
} catch (\Exception $e) {
|
|
error_log("[ComplaintFlow] Submit error: " . $e->getMessage());
|
|
return new FlowResult(
|
|
"⚠️ تعذر إرسال الشكوى حالياً. يرجى المحاولة لاحقاً.",
|
|
"finished",
|
|
true
|
|
);
|
|
}
|
|
|
|
default:
|
|
return new FlowResult("حدث خطأ في المسار.", "finished", true);
|
|
}
|
|
}
|
|
}
|