import 'dart:async'; import 'dart:convert'; import 'dart:developer'; import 'dart:io'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:driver/app/chat_screens/ChatVideoContainer.dart'; import 'package:driver/app/wallet_screen/payment_list_screen.dart'; import 'package:driver/constant/collection_name.dart'; import 'package:driver/constant/constant.dart'; import 'package:driver/constant/show_toast_dialog.dart'; import 'package:driver/firebase_options.dart'; import 'package:driver/models/cab_order_model.dart'; import 'package:driver/models/car_makes.dart'; import 'package:driver/models/car_model.dart'; import 'package:driver/models/conversation_model.dart'; import 'package:driver/models/document_model.dart'; import 'package:driver/models/driver_document_model.dart'; import 'package:driver/models/email_template_model.dart'; import 'package:driver/models/inbox_model.dart'; import 'package:driver/models/mail_setting.dart'; import 'package:driver/models/notification_model.dart'; import 'package:driver/models/on_boarding_model.dart'; import 'package:driver/models/order_model.dart'; import 'package:driver/models/parcel_order_model.dart'; import 'package:driver/models/payment_model/cod_setting_model.dart'; import 'package:driver/models/payment_model/flutter_wave_model.dart'; import 'package:driver/models/payment_model/mercado_pago_model.dart'; import 'package:driver/models/payment_model/mid_trans.dart'; import 'package:driver/models/payment_model/orange_money.dart'; import 'package:driver/models/payment_model/pay_fast_model.dart'; import 'package:driver/models/payment_model/pay_stack_model.dart'; import 'package:driver/models/payment_model/paypal_model.dart'; import 'package:driver/models/payment_model/paytm_model.dart'; import 'package:driver/models/payment_model/razorpay_model.dart'; import 'package:driver/models/payment_model/stripe_model.dart'; import 'package:driver/models/payment_model/wallet_setting_model.dart'; import 'package:driver/models/payment_model/xendit.dart'; import 'package:driver/models/referral_model.dart'; import 'package:driver/models/rental_order_model.dart'; import 'package:driver/models/section_model.dart'; import 'package:driver/models/tax_model.dart'; import 'package:driver/models/user_model.dart'; import 'package:driver/models/vehicle_type.dart'; import 'package:driver/models/vendor_model.dart'; import 'package:driver/models/wallet_transaction_model.dart'; import 'package:driver/models/withdraw_method_model.dart'; import 'package:driver/models/withdrawal_model.dart'; import 'package:driver/models/zone_model.dart'; import 'package:driver/services/audio_player_service.dart'; import 'package:driver/themes/app_them_data.dart'; import 'package:driver/utils/preferences.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/material.dart'; import 'package:geocoding/geocoding.dart'; import 'package:http/http.dart' as http; import 'package:intl/intl.dart'; import 'package:uuid/uuid.dart'; import 'package:video_compress/video_compress.dart'; import '../models/parcel_category.dart'; import '../models/rating_model.dart'; class FireStoreUtils { static FirebaseFirestore fireStore = FirebaseFirestore.instance; static String getCurrentUid() { return FirebaseAuth.instance.currentUser!.uid; } static Future isLogin() async { bool isLogin = false; if (FirebaseAuth.instance.currentUser != null) { isLogin = await userExistOrNot(FirebaseAuth.instance.currentUser!.uid); } else { isLogin = false; } return isLogin; } static Future userExistOrNot(String uid) async { bool isExist = false; await fireStore.collection(CollectionName.users).doc(uid).get().then( (value) { if (value.exists) { isExist = true; } else { isExist = false; } }, ).catchError((error) { log("Failed to check user exist: $error"); isExist = false; }); return isExist; } static Future getUserProfile(String uuid) async { UserModel? userModel; await fireStore.collection(CollectionName.users).doc(uuid).get().then((value) { if (value.exists) { userModel = UserModel.fromJson(value.data()!); } }).catchError((error) { log("Failed to update user: $error"); userModel = null; }); return userModel; } static Future updateUserWallet({required String amount, required String userId}) async { bool isAdded = false; await getUserProfile(userId).then((value) async { if (value != null) { UserModel userModel = value; userModel.walletAmount = double.parse(userModel.walletAmount.toString()) + double.parse(amount); await FireStoreUtils.updateUser(userModel).then((value) { isAdded = value; }); } }); return isAdded; } static Future updateUser(UserModel userModel) async { try { final docRef = fireStore.collection(CollectionName.users).doc(userModel.id); final Map data = userModel.toJson(); // First, merge the user's JSON to update/insert other fields safely await docRef.set(data, SetOptions(merge: true)); // If orderCabRequestData is null, explicitly delete the Firestore field // (omitting the field in toJson doesn't remove it from Firestore when using merge) if (userModel.orderCabRequestData == null) { await docRef.update({'ordercabRequestData': FieldValue.delete()}); } if (userModel.id == getCurrentUid()) { Constant.userModel = userModel; } return true; } catch (error) { log("Failed to update user: $error"); return false; } } // static Future updateUser(UserModel userModel) async { // bool isUpdate = false; // await fireStore.collection(CollectionName.users).doc(userModel.id).set(userModel.toJson()).whenComplete(() { // Constant.userModel = userModel; // isUpdate = true; // }).catchError((error) { // log("Failed to update user: $error"); // isUpdate = false; // }); // return isUpdate; // } static Future> getOnBoardingList() async { List onBoardingModel = []; await fireStore.collection(CollectionName.onBoarding).where("type", isEqualTo: "driver").get().then((value) { for (var element in value.docs) { OnBoardingModel documentModel = OnBoardingModel.fromJson(element.data()); onBoardingModel.add(documentModel); } }).catchError((error) { log(error.toString()); }); return onBoardingModel; } static Future> getSections(String serviceType) async { List sections = []; QuerySnapshot> productsQuery = await fireStore .collection(CollectionName.sections) .where("serviceTypeFlag", isEqualTo: serviceType) .where("isActive", isEqualTo: true) .get(); await Future.forEach(productsQuery.docs, (QueryDocumentSnapshot> document) { try { sections.add(SectionModel.fromJson(document.data())); } catch (e) { print('**-FireStoreUtils.getSection Parse error $e'); } }); return sections; } static Future setWalletTransaction(WalletTransactionModel walletTransactionModel) async { bool isAdded = false; await fireStore.collection(CollectionName.wallet).doc(walletTransactionModel.id).set(walletTransactionModel.toJson()).then((value) { isAdded = true; }).catchError((error) { log("Failed to update user: $error"); isAdded = false; }); return isAdded; } Future getSettings() async { try { await FirebaseFirestore.instance.collection(CollectionName.settings).doc("globalSettings").get().then((value) async { Constant.orderRingtoneUrl = value.data()?['order_ringtone_url'] ?? ''; Constant.isSelfDeliveryFeature = value.data()!['isSelfDelivery'] ?? false; Constant.defaultCountryCode = value.data()?['defaultCountryCode'] ?? ''; Constant.defaultCountry = value.data()?['defaultCountry'] ?? ''; Preferences.setString(Preferences.orderRingtone, Constant.orderRingtoneUrl); AppThemeData.primary300 = Color(int.parse(value.data()!['app_driver_color'].replaceFirst("#", "0xff"))); if (Constant.orderRingtoneUrl.isNotEmpty) { await AudioPlayerService.initAudio(); } }); fireStore.collection(CollectionName.settings).doc("googleMapKey").snapshots().listen((event) { if (event.exists) { Constant.mapAPIKey = event.data()!["key"]; } }); fireStore.collection(CollectionName.settings).doc("notification_setting").snapshots().listen((event) { if (event.exists) { Constant.senderId = event.data()?["senderId"]; Constant.jsonNotificationFileURL = event.data()?["serviceJson"]; } }); fireStore.collection(CollectionName.settings).doc("RestaurantNearBy").snapshots().listen((event) { if (event.exists) { Constant.distanceType = event.data()!["distanceType"]; } }); fireStore.collection(CollectionName.settings).doc("maintenance_settings").snapshots().listen((event) { if (event.exists && event.data() != null) { Constant.isMaintenanceModeForDriver = event.data()?["isMaintenanceModeForDriver"] ?? false; } }); fireStore.collection(CollectionName.settings).doc("privacyPolicy").snapshots().listen((event) { if (event.exists) { Constant.privacyPolicy = event.data()!["privacy_policy"]; } }); fireStore.collection(CollectionName.settings).doc("termsAndConditions").snapshots().listen((event) { if (event.exists) { Constant.termsAndConditions = event.data()?["terms_and_condition"] ?? ''; } }); fireStore.collection(CollectionName.settings).doc("Version").snapshots().listen((event) { if (event.exists) { Constant.googlePlayLink = event.data()!["googlePlayLink"] ?? ''; Constant.appStoreLink = event.data()!["appStoreLink"] ?? ''; Constant.appVersion = event.data()!["app_version"] ?? ''; } }); // fireStore.collection(CollectionName.settings).doc('referral_amount').get().then((value) { // Constant.referralAmount = value.data()!['referralAmount']; // }); FirebaseFirestore.instance.collection(CollectionName.settings).doc("emailSetting").get().then((value) { if (value.exists) { Constant.mailSettings = MailSettings.fromJson(value.data()!); } }); fireStore.collection(CollectionName.settings).doc('placeHolderImage').get().then((value) { Constant.placeHolderImage = value.data()!['image']; }); await FirebaseFirestore.instance.collection(CollectionName.settings).doc("document_verification_settings").get().then((value) { Constant.isDriverVerification = value.data()!['isDriverVerification']; Constant.isOwnerVerification = value.data()!['isOwnerVerification']; }); await FirebaseFirestore.instance.collection(CollectionName.settings).doc("DriverNearBy").get().then((value) { Constant.minimumDepositToRideAccept = value.data()!['minimumDepositToRideAccept']; Constant.ownerMinimumDepositToRideAccept = value.data()!['ownerMinimumDepositToRideAccept']; Constant.minimumAmountToWithdrawal = value.data()!['minimumAmountToWithdrawal']; Constant.driverLocationUpdate = value.data()!['driverLocationUpdate']; Constant.singleOrderReceive = value.data()!['singleOrderReceive']; Constant.selectedMapType = value.data()!["selectedMapType"]; Constant.mapType = value.data()!["mapType"]; Constant.autoApproveDriver = value.data()!["auto_approve_driver"]; Constant.enableOTPTripStart = value.data()!["enableOTPTripStart"]; Constant.enableOTPTripStartForRental = value.data()!["enableOTPTripStartForRental"]; Constant.parcelRadius = value.data()!["parcelRadius"]; Constant.rentalRadius = value.data()!["rentalRadius"]; log("Constant.singleOrderReceive :: ${Constant.singleOrderReceive}"); }); } catch (e) { log(e.toString()); } } static Future?> getZone() async { List airPortList = []; await fireStore.collection(CollectionName.zone).where('publish', isEqualTo: true).get().then((value) { for (var element in value.docs) { ZoneModel ariPortModel = ZoneModel.fromJson(element.data()); airPortList.add(ariPortModel); } }).catchError((error) { log(error.toString()); }); return airPortList; } static Future> getCarMakes() async { List airPortList = []; await fireStore.collection(CollectionName.carMake).where('isActive', isEqualTo: true).get().then((value) { for (var element in value.docs) { CarMakes ariPortModel = CarMakes.fromJson(element.data()); airPortList.add(ariPortModel); } }).catchError((error) { log(error.toString()); }); return airPortList; } static Future> getOnGoingParcelList() async { List parcelOrderList = []; QuerySnapshot> currencyQuery = await fireStore .collection(CollectionName.parcelOrders) .where("driverId", isEqualTo: FireStoreUtils.getCurrentUid()) .where("status", whereIn: [Constant.driverAccepted, Constant.orderInTransit, Constant.orderShipped]).get(); await Future.forEach(currencyQuery.docs, (QueryDocumentSnapshot> document) { try { parcelOrderList.add(ParcelOrderModel.fromJson(document.data())); } catch (e) { debugPrint('FireStoreUtils.get Currency Parse error $e'); } }); return parcelOrderList; } static Future> getRentalOnGoingParcelList() async { List parcelOrderList = []; QuerySnapshot> currencyQuery = await fireStore .collection(CollectionName.rentalOrders) .where("driverId", isEqualTo: FireStoreUtils.getCurrentUid()) .where("status", whereIn: [Constant.driverAccepted, Constant.orderInTransit, Constant.orderShipped]).get(); await Future.forEach(currencyQuery.docs, (QueryDocumentSnapshot> document) { try { parcelOrderList.add(RentalOrderModel.fromJson(document.data())); } catch (e) { debugPrint('FireStoreUtils.get Currency Parse error $e'); } }); return parcelOrderList; } static Future> getOwnerDriver() async { List userList = []; QuerySnapshot> currencyQuery = await fireStore .collection(CollectionName.users) .where("ownerId", isEqualTo: FireStoreUtils.getCurrentUid()) .where("isOwner", isEqualTo: false) .get(); await Future.forEach(currencyQuery.docs, (QueryDocumentSnapshot> document) { try { userList.add(UserModel.fromJson(document.data())); } catch (e) { debugPrint('FireStoreUtils.get Currency Parse error $e'); } }); return userList; } static Future> getCarModel(String name) async { List airPortList = []; await fireStore .collection(CollectionName.carModel) .where("car_make_name", isEqualTo: name) .where('isActive', isEqualTo: true) .get() .then((value) { for (var element in value.docs) { CarModel ariPortModel = CarModel.fromJson(element.data()); airPortList.add(ariPortModel); } }).catchError((error) { log(error.toString()); }); return airPortList; } static Future> getCabVehicleType(String sectionId) async { List airPortList = []; await fireStore .collection(CollectionName.vehicleType) .where('sectionId', isEqualTo: sectionId) .where("isActive", isEqualTo: true) .get() .then((value) { for (var element in value.docs) { VehicleType ariPortModel = VehicleType.fromJson(element.data()); airPortList.add(ariPortModel); } }); return airPortList; } static Future> getRentalVehicleType(String sectionId) async { print("sectionId :: $sectionId"); List airPortList = []; await fireStore .collection(CollectionName.rentalVehicleType) .where('sectionId', isEqualTo: sectionId) .where('isActive', isEqualTo: true) .get() .then((value) { for (var element in value.docs) { VehicleType ariPortModel = VehicleType.fromJson(element.data()); airPortList.add(ariPortModel); } }); return airPortList; } static Future?> getWalletTransaction() async { List walletTransactionList = []; await fireStore .collection(CollectionName.wallet) .where('user_id', isEqualTo: FireStoreUtils.getCurrentUid()) .orderBy('date', descending: true) .get() .then((value) { for (var element in value.docs) { WalletTransactionModel walletTransactionModel = WalletTransactionModel.fromJson(element.data()); walletTransactionList.add(walletTransactionModel); } }).catchError((error) { log(error.toString()); }); return walletTransactionList; } static Future getPaymentSettingsData() async { await fireStore.collection(CollectionName.settings).doc("payFastSettings").get().then((value) async { if (value.exists) { PayFastModel payFastModel = PayFastModel.fromJson(value.data()!); await Preferences.setString(Preferences.payFastSettings, jsonEncode(payFastModel.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("MercadoPago").get().then((value) async { if (value.exists) { MercadoPagoModel mercadoPagoModel = MercadoPagoModel.fromJson(value.data()!); await Preferences.setString(Preferences.mercadoPago, jsonEncode(mercadoPagoModel.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("paypalSettings").get().then((value) async { if (value.exists) { PayPalModel payPalModel = PayPalModel.fromJson(value.data()!); await Preferences.setString(Preferences.paypalSettings, jsonEncode(payPalModel.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("stripeSettings").get().then((value) async { if (value.exists) { StripeModel stripeModel = StripeModel.fromJson(value.data()!); await Preferences.setString(Preferences.stripeSettings, jsonEncode(stripeModel.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("flutterWave").get().then((value) async { if (value.exists) { FlutterWaveModel flutterWaveModel = FlutterWaveModel.fromJson(value.data()!); await Preferences.setString(Preferences.flutterWave, jsonEncode(flutterWaveModel.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("payStack").get().then((value) async { if (value.exists) { PayStackModel payStackModel = PayStackModel.fromJson(value.data()!); await Preferences.setString(Preferences.payStack, jsonEncode(payStackModel.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("PaytmSettings").get().then((value) async { if (value.exists) { PaytmModel paytmModel = PaytmModel.fromJson(value.data()!); await Preferences.setString(Preferences.paytmSettings, jsonEncode(paytmModel.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("walletSettings").get().then((value) async { if (value.exists) { WalletSettingModel walletSettingModel = WalletSettingModel.fromJson(value.data()!); await Preferences.setString(Preferences.walletSettings, jsonEncode(walletSettingModel.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("razorpaySettings").get().then((value) async { if (value.exists) { RazorPayModel razorPayModel = RazorPayModel.fromJson(value.data()!); await Preferences.setString(Preferences.razorpaySettings, jsonEncode(razorPayModel.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("CODSettings").get().then((value) async { if (value.exists) { CodSettingModel codSettingModel = CodSettingModel.fromJson(value.data()!); await Preferences.setString(Preferences.codSettings, jsonEncode(codSettingModel.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("midtrans_settings").get().then((value) async { if (value.exists) { MidTrans midTrans = MidTrans.fromJson(value.data()!); await Preferences.setString(Preferences.midTransSettings, jsonEncode(midTrans.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("orange_money_settings").get().then((value) async { if (value.exists) { OrangeMoney orangeMoney = OrangeMoney.fromJson(value.data()!); await Preferences.setString(Preferences.orangeMoneySettings, jsonEncode(orangeMoney.toJson())); } }); await fireStore.collection(CollectionName.settings).doc("xendit_settings").get().then((value) async { if (value.exists) { Xendit xendit = Xendit.fromJson(value.data()!); await Preferences.setString(Preferences.xenditSettings, jsonEncode(xendit.toJson())); } }); } static Future getVendorById(String vendorId) async { VendorModel? vendorModel; try { await fireStore.collection(CollectionName.vendors).doc(vendorId).get().then((value) { if (value.exists) { vendorModel = VendorModel.fromJson(value.data()!); } }); } catch (e, s) { log('FireStoreUtils.firebaseCreateNewUser $e $s'); return null; } return vendorModel; } static Future getOrderById(String orderId) async { OrderModel? orderModel; try { await fireStore.collection(CollectionName.vendorOrders).doc(orderId).get().then((value) { if (value.exists) { orderModel = OrderModel.fromJson(value.data()!); } }); } catch (e, s) { log('FireStoreUtils.firebaseCreateNewUser $e $s'); return null; } return orderModel; } static Future getSectionBySectionId(String sectionId) async { SectionModel? orderModel; try { await fireStore.collection(CollectionName.sections).doc(sectionId).get().then((value) { if (value.exists) { orderModel = SectionModel.fromJson(value.data()!); } }); } catch (e, s) { log('FireStoreUtils.firebaseCreateNewUser $e $s'); return null; } return orderModel; } static Future getDeliveryCharge() async { DeliveryCharge? deliveryCharge; try { await fireStore.collection(CollectionName.settings).doc("DeliveryCharge").get().then((value) { if (value.exists) { deliveryCharge = DeliveryCharge.fromJson(value.data()!); } }); } catch (e, s) { log('FireStoreUtils.firebaseCreateNewUser $e $s'); return null; } return deliveryCharge; } static Future?> getTaxList() async { List taxList = []; List placeMarks = await placemarkFromCoordinates(Constant.selectedLocation.location!.latitude!, Constant.selectedLocation.location!.longitude!); await fireStore .collection(CollectionName.tax) .where('country', isEqualTo: placeMarks.first.country) .where('enable', isEqualTo: true) .get() .then((value) { for (var element in value.docs) { TaxModel taxModel = TaxModel.fromJson(element.data()); taxList.add(taxModel); } }).catchError((error) { log(error.toString()); }); return taxList; } static Future setOrder(OrderModel orderModel) async { bool isAdded = false; await fireStore.collection(CollectionName.vendorOrders).doc(orderModel.id).set(orderModel.toJson()).then((value) { isAdded = true; }).catchError((error) { log("Failed to update user: $error"); isAdded = false; }); return isAdded; } static Future setParcelOrder(ParcelOrderModel orderModel) async { bool isAdded = false; await fireStore.collection(CollectionName.parcelOrders).doc(orderModel.id).set(orderModel.toJson()).then((value) { isAdded = true; }).catchError((error) { log("Failed to update user: $error"); isAdded = false; }); return isAdded; } static Future setCabOrder(CabOrderModel orderModel) async { log("setCabOrder :: ${orderModel.toJson()}"); try { await fireStore.collection(CollectionName.ridesBooking).doc(orderModel.id).set(orderModel.toJson(), SetOptions(merge: true)); return true; } catch (error) { log("Failed to update cab order: $error"); return false; } } static Future getEmailTemplates(String type) async { EmailTemplateModel? emailTemplateModel; await fireStore.collection(CollectionName.emailTemplates).where('type', isEqualTo: type).get().then((value) { print("------>"); if (value.docs.isNotEmpty) { print(value.docs.first.data()); emailTemplateModel = EmailTemplateModel.fromJson(value.docs.first.data()); } }); return emailTemplateModel; } static Future updateWallateAmount(OrderModel orderModel) async { double subTotal = 0.0; double specialDiscount = 0.0; double deliveryCharge = 0.0; double taxAmount = 0.0; for (var element in orderModel.products!) { if (double.parse(element.discountPrice.toString()) <= 0) { subTotal = subTotal + double.parse(element.price.toString()) * double.parse(element.quantity.toString()) + (double.parse(element.extrasPrice.toString()) * double.parse(element.quantity.toString())); } else { subTotal = subTotal + double.parse(element.discountPrice.toString()) * double.parse(element.quantity.toString()) + (double.parse(element.extrasPrice.toString()) * double.parse(element.quantity.toString())); } } if (orderModel.specialDiscount != null && orderModel.specialDiscount!['special_discount'] != null) { specialDiscount = double.parse(orderModel.specialDiscount!['special_discount'].toString()); } if (orderModel.taxSetting != null) { for (var element in orderModel.taxSetting!) { taxAmount = taxAmount + Constant.calculateTax( amount: (subTotal - double.parse(orderModel.discount.toString()) - specialDiscount).toString(), taxModel: element); } } if (orderModel.deliveryCharge != null) { deliveryCharge = double.parse(orderModel.deliveryCharge.toString()) + double.parse(orderModel.tipAmount.toString()); } double productAmount = 0.0; productAmount = subTotal + taxAmount; if (orderModel.paymentMethod.toString() == PaymentGateway.cod.name) { WalletTransactionModel transactionModel = WalletTransactionModel( id: Constant.getUuid(), amount: productAmount, date: Timestamp.now(), paymentMethod: orderModel.paymentMethod!, transactionUser: "driver", userId: FireStoreUtils.getCurrentUid(), isTopup: false, orderId: orderModel.id, note: "Product amount debited from order #${orderModel.id}", paymentStatus: "success"); await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { if (value == true) { await FireStoreUtils.updateUserWallet(amount: "-${productAmount.toString()}", userId: FireStoreUtils.getCurrentUid()); } }); } WalletTransactionModel deliveryChargeModel = WalletTransactionModel( id: Constant.getUuid(), amount: deliveryCharge, date: Timestamp.now(), paymentMethod: orderModel.paymentMethod!, transactionUser: "driver", userId: FireStoreUtils.getCurrentUid(), isTopup: true, orderId: orderModel.id, note: "Delivery charge credited for order #${orderModel.id}", paymentStatus: "success"); await FireStoreUtils.setWalletTransaction(deliveryChargeModel).then((value) async { if (value == true) { await FireStoreUtils.updateUserWallet(amount: deliveryCharge.toString(), userId: FireStoreUtils.getCurrentUid()); } }); } static Future sendTopUpMail({required String amount, required String paymentMethod, required String tractionId}) async { EmailTemplateModel? emailTemplateModel = await FireStoreUtils.getEmailTemplates(Constant.walletTopup); String newString = emailTemplateModel!.message.toString(); newString = newString.replaceAll("{username}", Constant.userModel!.firstName.toString() + Constant.userModel!.lastName.toString()); newString = newString.replaceAll("{date}", DateFormat('yyyy-MM-dd').format(Timestamp.now().toDate())); newString = newString.replaceAll("{amount}", Constant.amountShow(amount: amount)); newString = newString.replaceAll("{paymentmethod}", paymentMethod.toString()); newString = newString.replaceAll("{transactionid}", tractionId.toString()); newString = newString.replaceAll("{newwalletbalance}.", Constant.amountShow(amount: Constant.userModel!.walletAmount.toString())); await Constant.sendMail( subject: emailTemplateModel.subject, isAdmin: emailTemplateModel.isSendToAdmin, body: newString, recipients: [Constant.userModel!.email]); } static Future getVendorCuisines(String id) async { List tagList = []; List prodTagList = []; QuerySnapshot> productsQuery = await fireStore.collection(CollectionName.vendorProducts).where('vendorID', isEqualTo: id).get(); await Future.forEach(productsQuery.docs, (QueryDocumentSnapshot> document) { if (document.data().containsKey("categoryID") && document.data()['categoryID'].toString().isNotEmpty) { prodTagList.add(document.data()['categoryID']); } }); QuerySnapshot> catQuery = await fireStore.collection(CollectionName.vendorCategories).where('publish', isEqualTo: true).get(); await Future.forEach(catQuery.docs, (QueryDocumentSnapshot> document) { Map catDoc = document.data(); if (catDoc.containsKey("id") && catDoc['id'].toString().isNotEmpty && catDoc.containsKey("title") && catDoc['title'].toString().isNotEmpty && prodTagList.contains(catDoc['id'])) { tagList.add(catDoc['title']); } }); return tagList; } static Future getNotificationContent(String type) async { NotificationModel? notificationModel; await fireStore.collection(CollectionName.dynamicNotification).where('type', isEqualTo: type).get().then((value) { print("------>"); if (value.docs.isNotEmpty) { print(value.docs.first.data()); notificationModel = NotificationModel.fromJson(value.docs.first.data()); } else { notificationModel = NotificationModel(id: "", message: "Notification setup is pending", subject: "setup notification", type: ""); } }); return notificationModel; } static Future deleteUser() async { bool? isDelete; try { await fireStore.collection(CollectionName.users).doc(FireStoreUtils.getCurrentUid()).delete(); // delete user from firebase auth await FirebaseAuth.instance.currentUser?.delete().then((value) { isDelete = true; }); } catch (e, s) { log('FireStoreUtils.firebaseCreateNewUser $e $s'); return false; } return isDelete; } static Future> getDocumentList(String type) async { List documentList = []; await fireStore .collection(CollectionName.documents) .where('type', isEqualTo: type) .where('enable', isEqualTo: true) .get() .then((value) { for (var element in value.docs) { DocumentModel documentModel = DocumentModel.fromJson(element.data()); documentList.add(documentModel); } }).catchError((error) { log(error.toString()); }); return documentList; } static Future getDocumentOfDriver() async { DriverDocumentModel? driverDocumentModel; await fireStore.collection(CollectionName.documentsVerify).doc(getCurrentUid()).get().then((value) async { if (value.exists) { driverDocumentModel = DriverDocumentModel.fromJson(value.data()!); } }); return driverDocumentModel; } static Future addDriverInbox(InboxModel inboxModel) async { return await fireStore.collection("chat_driver").doc(inboxModel.orderId).set(inboxModel.toJson()).then((document) { return inboxModel; }); } static Future addDriverChat(ConversationModel conversationModel) async { return await fireStore .collection("chat_driver") .doc(conversationModel.orderId) .collection("thread") .doc(conversationModel.id) .set(conversationModel.toJson()) .then((document) { return conversationModel; }); } static Future addRestaurantChat(ConversationModel conversationModel) async { return await fireStore .collection("chat_restaurant") .doc(conversationModel.orderId) .collection("thread") .doc(conversationModel.id) .set(conversationModel.toJson()) .then((document) { return conversationModel; }); } static Future uploadChatImageToFireStorage(File image, BuildContext context) async { ShowToastDialog.showLoader("Please wait"); var uniqueID = const Uuid().v4(); Reference upload = FirebaseStorage.instance.ref().child('images/$uniqueID.png'); UploadTask uploadTask = upload.putFile(image); var storageRef = (await uploadTask.whenComplete(() {})).ref; var downloadUrl = await storageRef.getDownloadURL(); var metaData = await storageRef.getMetadata(); ShowToastDialog.closeLoader(); return Url(mime: metaData.contentType ?? 'image', url: downloadUrl.toString()); } // static Future uploadChatVideoToFireStorage(File video, BuildContext context) async { // ShowToastDialog.showLoader("Please wait"); // var uniqueID = const Uuid().v4(); // Reference upload = FirebaseStorage.instance.ref().child('videos/$uniqueID.mp4'); // SettableMetadata metadata = SettableMetadata(contentType: 'video'); // UploadTask uploadTask = upload.putFile(video, metadata); // var storageRef = (await uploadTask.whenComplete(() {})).ref; // var downloadUrl = await storageRef.getDownloadURL(); // var metaData = await storageRef.getMetadata(); // final uint8list = await VideoThumbnail.thumbnailFile(video: downloadUrl, thumbnailPath: (await getTemporaryDirectory()).path, imageFormat: ImageFormat.PNG); // final file = File(uint8list ?? ''); // String thumbnailDownloadUrl = await uploadVideoThumbnailToFireStorage(file); // ShowToastDialog.closeLoader(); // return ChatVideoContainer(videoUrl: Url(url: downloadUrl.toString(), mime: metaData.contentType ?? 'video'), thumbnailUrl: thumbnailDownloadUrl); // } static Future uploadChatVideoToFireStorage(BuildContext context, File video) async { try { ShowToastDialog.showLoader("Uploading video..."); final String uniqueID = const Uuid().v4(); final Reference videoRef = FirebaseStorage.instance.ref('videos/$uniqueID.mp4'); final UploadTask uploadTask = videoRef.putFile( video, SettableMetadata(contentType: 'video/mp4'), ); await uploadTask; final String videoUrl = await videoRef.getDownloadURL(); ShowToastDialog.showLoader("Generating thumbnail..."); File thumbnail = await VideoCompress.getFileThumbnail( video.path, quality: 75, // 0 - 100 position: -1, // Get the first frame ); final String thumbnailID = const Uuid().v4(); final Reference thumbnailRef = FirebaseStorage.instance.ref('thumbnails/$thumbnailID.jpg'); final UploadTask thumbnailUploadTask = thumbnailRef.putData( thumbnail.readAsBytesSync(), SettableMetadata(contentType: 'image/jpeg'), ); await thumbnailUploadTask; final String thumbnailUrl = await thumbnailRef.getDownloadURL(); var metaData = await thumbnailRef.getMetadata(); ShowToastDialog.closeLoader(); return ChatVideoContainer( videoUrl: Url(url: videoUrl.toString(), mime: metaData.contentType ?? 'video', videoThumbnail: thumbnailUrl), thumbnailUrl: thumbnailUrl); } catch (e) { ShowToastDialog.closeLoader(); ShowToastDialog.showToast("Error: ${e.toString()}"); return null; } } static Future uploadVideoThumbnailToFireStorage(File file) async { var uniqueID = const Uuid().v4(); Reference upload = FirebaseStorage.instance.ref().child('thumbnails/$uniqueID.png'); UploadTask uploadTask = upload.putFile(file); var downloadUrl = await (await uploadTask.whenComplete(() {})).ref.getDownloadURL(); return downloadUrl.toString(); } static Future uploadDriverDocument(Documents documents) async { bool isAdded = false; DriverDocumentModel driverDocumentModel = DriverDocumentModel(); List documentsList = []; await fireStore.collection(CollectionName.documentsVerify).doc(getCurrentUid()).get().then((value) async { if (value.exists) { DriverDocumentModel newDriverDocumentModel = DriverDocumentModel.fromJson(value.data()!); documentsList = newDriverDocumentModel.documents!; var contain = newDriverDocumentModel.documents!.where((element) => element.documentId == documents.documentId); if (contain.isEmpty) { documentsList.add(documents); driverDocumentModel.id = getCurrentUid(); driverDocumentModel.type = "driver"; driverDocumentModel.documents = documentsList; } else { var index = newDriverDocumentModel.documents!.indexWhere((element) => element.documentId == documents.documentId); driverDocumentModel.id = getCurrentUid(); driverDocumentModel.type = "driver"; documentsList.removeAt(index); documentsList.insert(index, documents); driverDocumentModel.documents = documentsList; isAdded = false; } } else { documentsList.add(documents); driverDocumentModel.id = getCurrentUid(); driverDocumentModel.type = "driver"; driverDocumentModel.documents = documentsList; } }); await fireStore.collection(CollectionName.documentsVerify).doc(getCurrentUid()).set(driverDocumentModel.toJson()).then((value) { isAdded = true; }).catchError((error) { isAdded = false; log(error.toString()); }); return isAdded; } static Future getWithdrawMethod() async { WithdrawMethodModel? withdrawMethodModel; await fireStore.collection(CollectionName.withdrawMethod).where("userId", isEqualTo: getCurrentUid()).get().then((value) async { if (value.docs.isNotEmpty) { withdrawMethodModel = WithdrawMethodModel.fromJson(value.docs.first.data()); } }); return withdrawMethodModel; } static Future setWithdrawMethod(WithdrawMethodModel withdrawMethodModel) async { if (withdrawMethodModel.id == null) { withdrawMethodModel.id = const Uuid().v4(); withdrawMethodModel.userId = getCurrentUid(); } await fireStore .collection(CollectionName.withdrawMethod) .doc(withdrawMethodModel.id) .set(withdrawMethodModel.toJson()) .then((value) async {}); return withdrawMethodModel; } static Future?> getWithdrawHistory() async { List walletTransactionList = []; await fireStore .collection(CollectionName.driverPayouts) .where('driverID', isEqualTo: Constant.userModel!.id.toString()) .orderBy('paidDate', descending: true) .get() .then((value) { for (var element in value.docs) { WithdrawalModel walletTransactionModel = WithdrawalModel.fromJson(element.data()); walletTransactionList.add(walletTransactionModel); } }).catchError((error) { log(error.toString()); }); return walletTransactionList; } static Future sendPayoutMail({required String amount, required String payoutrequestid}) async { EmailTemplateModel? emailTemplateModel = await FireStoreUtils.getEmailTemplates(Constant.payoutRequest); String body = emailTemplateModel!.subject.toString(); body = body.replaceAll("{userid}", Constant.userModel!.id.toString()); String newString = emailTemplateModel.message.toString(); newString = newString.replaceAll("{username}", Constant.userModel!.fullName()); newString = newString.replaceAll("{userid}", Constant.userModel!.id.toString()); newString = newString.replaceAll("{amount}", Constant.amountShow(amount: amount)); newString = newString.replaceAll("{payoutrequestid}", payoutrequestid.toString()); newString = newString.replaceAll("{usercontactinfo}", "${Constant.userModel!.email}\n${Constant.userModel!.phoneNumber}"); await Constant.sendMail( subject: body, isAdmin: emailTemplateModel.isSendToAdmin, body: newString, recipients: [Constant.userModel!.email]); } static Future withdrawWalletAmount(WithdrawalModel userModel) async { bool isUpdate = false; await fireStore.collection(CollectionName.driverPayouts).doc(userModel.id).set(userModel.toJson()).whenComplete(() { isUpdate = true; }).catchError((error) { log("Failed to update user: $error"); isUpdate = false; }); return isUpdate; } static Future getFirestOrderOrNOt(OrderModel orderModel) async { bool isFirst = true; await fireStore.collection(CollectionName.vendorOrders).where('authorID', isEqualTo: orderModel.authorID).get().then((value) { if (value.size == 1) { isFirst = true; } else { isFirst = false; } }); return isFirst; } static Future updateReferralAmount(OrderModel orderModel) async { ReferralModel? referralModel; await fireStore.collection(CollectionName.referral).doc(orderModel.authorID).get().then((value) { if (value.data() != null) { referralModel = ReferralModel.fromJson(value.data()!); } else { return; } }); if (referralModel != null) { if (referralModel!.referralBy != null && referralModel!.referralBy!.isNotEmpty) { WalletTransactionModel transactionModel = WalletTransactionModel( id: Constant.getUuid(), amount: double.parse(Constant.referralAmount.toString()), date: Timestamp.now(), paymentMethod: "Referral Amount", transactionUser: "user", userId: referralModel!.referralBy, isTopup: true, note: "You referral user has complete his this order #${orderModel.id}", paymentStatus: "success"); await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { if (value == true) { await FireStoreUtils.updateUserWallet(amount: Constant.referralAmount.toString(), userId: referralModel!.referralBy.toString()) .then((value) {}); } }); } else { return; } } } static Future getFirestOrderOrNOtCabService(CabOrderModel orderModel) async { bool isFirst = true; await fireStore.collection(CollectionName.ridesBooking).where('authorID', isEqualTo: orderModel.authorID).get().then((value) { if (value.size == 1) { isFirst = true; } else { isFirst = false; } }); return isFirst; } static Future updateReferralAmountCabService(CabOrderModel orderModel) async { ReferralModel? referralModel; SectionModel? sectionModel; await getSectionBySectionId(orderModel.sectionId.toString()).then((value) { sectionModel = value; }); await fireStore.collection(CollectionName.referral).doc(orderModel.authorID).get().then((value) { if (value.data() != null) { referralModel = ReferralModel.fromJson(value.data()!); } else { return; } }); if (referralModel != null) { if (referralModel!.referralBy != null && referralModel!.referralBy!.isNotEmpty) { await fireStore.collection(CollectionName.users).doc(referralModel!.referralBy).get().then((value) async { DocumentSnapshot> userDocument = value; if (userDocument.data() != null && userDocument.exists) { try { UserModel user = UserModel.fromJson(userDocument.data()!); await fireStore.collection(CollectionName.users).doc(user.id).update( {"wallet_amount": double.parse(user.walletAmount.toString()) + double.parse(sectionModel!.referralAmount.toString())}); WalletTransactionModel transactionModel = WalletTransactionModel( id: Constant.getUuid(), amount: double.parse(sectionModel!.referralAmount.toString()), date: Timestamp.now(), paymentMethod: "Referral Amount", transactionUser: "user", userId: referralModel!.referralBy.toString(), isTopup: true, note: "Wallet Top-up", paymentStatus: "success"); await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { if (value == true) { await FireStoreUtils.updateUserWallet( amount: sectionModel!.referralAmount.toString(), userId: referralModel!.referralBy.toString()) .then((value) {}); } }); } catch (e) { log(e.toString()); } } }); } else { return; } } } static Future getParcelFirstOrderOrNOt(ParcelOrderModel orderModel) async { bool isFirst = true; await fireStore.collection(CollectionName.parcelOrders).where('authorID', isEqualTo: orderModel.authorID).get().then((value) { if (value.size == 1) { isFirst = true; } else { isFirst = false; } }); return isFirst; } static Future getRentalFirstOrderOrNOt(RentalOrderModel orderModel) async { bool isFirst = true; await fireStore.collection(CollectionName.rentalOrders).where('authorID', isEqualTo: orderModel.authorID).get().then((value) { if (value.size == 1) { isFirst = true; } else { isFirst = false; } }); return isFirst; } static Future updateParcelReferralAmount(ParcelOrderModel orderModel) async { ReferralModel? referralModel; SectionModel? sectionModel; print(orderModel.authorID); await getSectionBySectionId(orderModel.sectionId.toString()).then((value) { sectionModel = value; }); await fireStore.collection(CollectionName.referral).doc(orderModel.authorID).get().then((value) { if (value.data() != null) { referralModel = ReferralModel.fromJson(value.data()!); } else { return; } }); if (referralModel != null) { if (referralModel!.referralBy != null && referralModel!.referralBy!.isNotEmpty) { await fireStore.collection(CollectionName.users).doc(referralModel!.referralBy).get().then((value) async { DocumentSnapshot> userDocument = value; if (userDocument.data() != null && userDocument.exists) { try { UserModel user = UserModel.fromJson(userDocument.data()!); await fireStore.collection(CollectionName.users).doc(user.id).update( {"wallet_amount": double.parse(user.walletAmount.toString()) + double.parse(sectionModel!.referralAmount.toString())}); WalletTransactionModel transactionModel = WalletTransactionModel( id: Constant.getUuid(), amount: double.parse(sectionModel!.referralAmount.toString()), date: Timestamp.now(), paymentMethod: "Referral Amount", transactionUser: "user", userId: referralModel!.referralBy.toString(), isTopup: true, note: "Wallet Top-up", paymentStatus: "success"); await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { if (value == true) { await FireStoreUtils.updateUserWallet( amount: sectionModel!.referralAmount.toString(), userId: referralModel!.referralBy.toString()) .then((value) {}); } }); } catch (error) { log(error.toString()); } print("data val"); } }); } else { return; } } } static Future updateRentalReferralAmount(RentalOrderModel orderModel) async { ReferralModel? referralModel; SectionModel? sectionModel; print(orderModel.authorID); await getSectionBySectionId(orderModel.sectionId.toString()).then((value) { sectionModel = value; }); await fireStore.collection(CollectionName.referral).doc(orderModel.authorID).get().then((value) { if (value.data() != null) { referralModel = ReferralModel.fromJson(value.data()!); } else { return; } }); if (referralModel != null) { if (referralModel!.referralBy != null && referralModel!.referralBy!.isNotEmpty) { await fireStore.collection(CollectionName.users).doc(referralModel!.referralBy).get().then((value) async { DocumentSnapshot> userDocument = value; if (userDocument.data() != null && userDocument.exists) { try { UserModel user = UserModel.fromJson(userDocument.data()!); await fireStore.collection(CollectionName.users).doc(user.id).update( {"wallet_amount": double.parse(user.walletAmount.toString()) + double.parse(sectionModel!.referralAmount.toString())}); WalletTransactionModel transactionModel = WalletTransactionModel( id: Constant.getUuid(), amount: double.parse(sectionModel!.referralAmount.toString()), date: Timestamp.now(), paymentMethod: "Referral Amount", transactionUser: "user", userId: referralModel!.referralBy.toString(), isTopup: true, note: "Wallet Top-up", paymentStatus: "success"); await FireStoreUtils.setWalletTransaction(transactionModel).then((value) async { if (value == true) { await FireStoreUtils.updateUserWallet( amount: sectionModel!.referralAmount.toString(), userId: referralModel!.referralBy.toString()) .then((value) {}); } }); } catch (error) { log(error.toString()); } print("data val"); } }); } else { return; } } } static Stream> listenParcelOrders(String driverId) { return fireStore .collection(CollectionName.parcelOrders) .where('driverId', isEqualTo: driverId) .orderBy('createdAt', descending: true) .snapshots() .map(( snapshot, ) { return snapshot.docs.map((doc) { log("===>"); print(doc.data()); return ParcelOrderModel.fromJson(doc.data()); }).toList(); }); } static Future> getParcelServiceCategory() async { List parcelCategoryList = []; await fireStore .collection(CollectionName.parcelCategory) .where('publish', isEqualTo: true) .orderBy('set_order', descending: false) .get() .then((value) { for (var element in value.docs) { try { ParcelCategory category = ParcelCategory.fromJson(element.data()); parcelCategoryList.add(category); } catch (e, stackTrace) { print('getParcelServiceCategory parse error: ${element.id} $e'); print(stackTrace); } } }); return parcelCategoryList; } static Future rentalOrderPlace(RentalOrderModel orderModel) async { await fireStore.collection(CollectionName.rentalOrders).doc(orderModel.id).set(orderModel.toJson()); } static Future getRentalOrderById(String orderId) async { RentalOrderModel? orderModel; await fireStore.collection(CollectionName.rentalOrders).doc(orderId).get().then((value) { if (value.exists) { orderModel = RentalOrderModel.fromJson(value.data()!); } }); return orderModel; } static Stream> getRentalOrders(String driverId) { return fireStore .collection(CollectionName.rentalOrders) .where('driverId', isEqualTo: driverId) .orderBy('createdAt', descending: true) .snapshots() .map(( query, ) { List ordersList = []; for (var element in query.docs) { ordersList.add(RentalOrderModel.fromJson(element.data())); } return ordersList; }); } static Future getReviewsbyID(String orderId) async { RatingModel? ratingModel; await fireStore.collection(CollectionName.itemsReview).where('orderid', isEqualTo: orderId).get().then((snapshot) { if (snapshot.docs.isNotEmpty) { ratingModel = RatingModel.fromJson(snapshot.docs.first.data()); } }).catchError((error) { print('Error fetching review for provider: $error'); }); return ratingModel; } static Future updateReviewById(RatingModel ratingProduct) async { try { await fireStore.collection(CollectionName.itemsReview).doc(ratingProduct.id).set(ratingProduct.toJson()); return ratingProduct; } catch (e, stackTrace) { print('Error updating review: $e'); print(stackTrace); return null; } } static Stream> getCabDriverOrders(String driverId) { return fireStore .collection(CollectionName.ridesBooking) .where('driverId', isEqualTo: driverId) .orderBy('createdAt', descending: true) .snapshots() .map((query) { List ordersList = []; for (var element in query.docs) { ordersList.add(CabOrderModel.fromJson(element.data())); } return ordersList; }); } static Future getOrderByIdFromAllCollections(String orderId) async { final List collections = [ CollectionName.parcelOrders, CollectionName.rentalOrders, CollectionName.ridesBooking, CollectionName.vendorOrders, ]; for (String collection in collections) { try { final snapshot = await fireStore.collection(collection).where('id', isEqualTo: orderId).limit(1).get(); if (snapshot.docs.isNotEmpty) { final data = snapshot.docs.first.data(); data['collection_name'] = collection; return data; } } catch (e) { log("Error fetching from $collection => $e"); } } log("No order found with ID $orderId"); return null; } static Future> getCabDriverOrdersOnce(String driverId) async { Query query = fireStore.collection(CollectionName.ridesBooking).orderBy('createdAt', descending: true); if (driverId.isNotEmpty) { query = query.where('driverId', isEqualTo: driverId); } QuerySnapshot snapshot = await query.get(); return snapshot.docs.map((doc) => CabOrderModel.fromJson(doc.data() as Map)).toList(); } static Future> getParcelDriverOrdersOnce(String driverId) async { Query query = fireStore.collection(CollectionName.parcelOrders).orderBy('createdAt', descending: true); if (driverId.isNotEmpty) { query = query.where('driverId', isEqualTo: driverId); } QuerySnapshot snapshot = await query.get(); return snapshot.docs.map((doc) => ParcelOrderModel.fromJson(doc.data() as Map)).toList(); } static Future> getRentalDriverOrdersOnce(String driverId) async { Query query = fireStore.collection(CollectionName.rentalOrders).orderBy('createdAt', descending: true); if (driverId.isNotEmpty) { query = query.where('driverId', isEqualTo: driverId); } QuerySnapshot snapshot = await query.get(); return snapshot.docs.map((doc) => RentalOrderModel.fromJson(doc.data() as Map)).toList(); } static Future deleteDriverId(String uid) async { try { final user = FirebaseAuth.instance.currentUser; if (user == null) { print("❌ No user is logged in."); return false; } final idToken = await user.getIdToken(); final projectId = DefaultFirebaseOptions.currentPlatform.projectId; final url = Uri.parse('https://us-central1-$projectId.cloudfunctions.net/deleteUser'); final response = await http.post( url, headers: { 'Authorization': 'Bearer $idToken', 'Content-Type': 'application/json', }, body: jsonEncode({ 'data': {'uid': uid}, // 👈 matches your Cloud Function structure }), ); print("Response [${response.statusCode}]: ${response.body}"); if (response.statusCode == 200) { final decoded = jsonDecode(response.body); return decoded['result']?['success'] == true || decoded['success'] == true; } else { print("⚠️ Cloud Function failed: ${response.body}"); return false; } } catch (e) { print("❌ Error deleting driver: $e"); return false; } } }