// food_delivery_models.dart — نماذج بيانات وحدة التوصيل (جهة السائق) class FoodDeliveryTask { final int id; final String status; // courier_assigned | picked_up final int merchantId; final String merchantNameAr; final double? merchantLat; final double? merchantLng; final String? merchantAddress; final int deliveryFee; final String? deliveryAddress; final double deliveryLat; final double deliveryLng; final DateTime? createdAt; FoodDeliveryTask({ required this.id, required this.status, required this.merchantId, required this.merchantNameAr, required this.deliveryFee, required this.deliveryLat, required this.deliveryLng, this.merchantLat, this.merchantLng, this.merchantAddress, this.deliveryAddress, this.createdAt, }); factory FoodDeliveryTask.fromJson(Map j) => FoodDeliveryTask( id: int.tryParse(j['id'].toString()) ?? 0, status: j['status']?.toString() ?? '', merchantId: int.tryParse(j['merchant_id'].toString()) ?? 0, merchantNameAr: j['merchant_name_ar']?.toString() ?? '', merchantLat: double.tryParse(j['merchant_lat']?.toString() ?? ''), merchantLng: double.tryParse(j['merchant_lng']?.toString() ?? ''), merchantAddress: j['merchant_address']?.toString(), deliveryFee: int.tryParse(j['delivery_fee']?.toString() ?? '0') ?? 0, deliveryAddress: j['delivery_address']?.toString(), deliveryLat: double.tryParse(j['delivery_lat']?.toString() ?? '0') ?? 0, deliveryLng: double.tryParse(j['delivery_lng']?.toString() ?? '0') ?? 0, createdAt: DateTime.tryParse(j['created_at']?.toString() ?? ''), ); } // عرض توصيل وارد — من polling على food/courier/pending_offers.php class FoodDeliveryOffer { final int orderId; final int merchantId; final String merchantNameAr; final double? merchantLat; final double? merchantLng; final int deliveryFee; final DateTime? offeredAt; FoodDeliveryOffer({ required this.orderId, required this.merchantId, required this.merchantNameAr, required this.deliveryFee, this.merchantLat, this.merchantLng, this.offeredAt, }); factory FoodDeliveryOffer.fromJson(Map j) => FoodDeliveryOffer( orderId: int.tryParse(j['order_id'].toString()) ?? 0, merchantId: int.tryParse(j['merchant_id'].toString()) ?? 0, merchantNameAr: j['merchant_name_ar']?.toString() ?? '', merchantLat: double.tryParse(j['merchant_lat']?.toString() ?? ''), merchantLng: double.tryParse(j['merchant_lng']?.toString() ?? ''), deliveryFee: int.tryParse(j['delivery_fee']?.toString() ?? '0') ?? 0, offeredAt: DateTime.tryParse(j['offered_at']?.toString() ?? ''), ); // مهلة العرض 20 ثانية من الخادم (SET NX EX 20) — عدّاد تقريبي للعرض فقط، // الخادم هو الحكم الفعلي (رفض offer_respond إن انتهت المهلة فعلاً). int get secondsRemaining { if (offeredAt == null) return 20; final elapsed = DateTime.now().difference(offeredAt!).inSeconds; return (20 - elapsed).clamp(0, 20); } } const int foodCurrencyDivisor = 1000; String foodFormatPrice(int smallestUnit, {String currencySymbol = 'د.أ'}) { final decimal = smallestUnit / foodCurrencyDivisor; return '${decimal.toStringAsFixed(3)} $currencySymbol'; }