import 'dart:async'; import 'dart:developer'; import 'package:e_porter/_core/service/preferences_service.dart'; import 'package:e_porter/_core/utils/snackbar/snackbar_helper.dart'; import 'package:e_porter/domain/models/porter_queue_model.dart'; import 'package:e_porter/presentation/controllers/porter_queue_controller.dart'; import 'package:get/get.dart'; import '../../domain/models/transaction_porter_model.dart'; import '../../domain/usecases/transaction_porter_usecase.dart'; class TransactionPorterController extends GetxController { final TransactionPorterUsecase _useCase; TransactionPorterController(this._useCase); final RxList transactions = [].obs; final Rx currentTransaction = Rx(null); final Map> _transactionWatchers = {}; final RxString currentPorterId = ''.obs; final RxBool isLoading = false.obs; final RxString error = ''.obs; StreamSubscription>? _subscription; StreamSubscription? _porterSubscription; @override void onInit() { super.onInit(); _loadPorterData(); } Future _loadPorterData() async { try { final userData = await PreferencesService.getUserData(); if (userData == null || userData.uid.isEmpty) { error.value = 'Data user tidak tersedia'; return; } // Set userId untuk digunakan nanti String userId = userData.uid; final porterCtrl = Get.find(); // Simpan user ID untuk memastikan bisa mengakses history jika porter tidak ditemukan String userIdForHistory = userId; // Coba mendapatkan porter aktif _porterSubscription = porterCtrl.watchPorter(userId).listen((porter) { if (porter != null && porter.id != null) { log('Porter aktif ditemukan: ${porter.id}'); currentPorterId.value = porter.id!; // Gunakan userId untuk memastikan semua transaksi bisa diakses loadTransactionsWithBothIDs(porter.id!, userIdForHistory); } else { // Porter tidak aktif, coba ambil riwayat dari userId log('Porter aktif tidak ditemukan, mencoba ambil riwayat dari userId: $userId'); loadTransactionsFromUserId(userId); } }, onError: (e) { log('Error memantau data porter: $e'); // Jika error, coba ambil riwayat dari userId loadTransactionsFromUserId(userId); }); } catch (e) { error.value = 'Error inisialisasi: $e'; } } void loadTransactionsWithBothIDs(String porterId, String userId) { isLoading.value = true; error.value = ''; _subscription?.cancel(); _subscription = _useCase.watchPorterTransactions(porterId).listen((transactionList) { log('Menerima ${transactionList.length} transaksi dari porterId'); // Jika tidak ada transaksi dari porterId, coba dari userId if (transactionList.isEmpty && userId != porterId) { log('Tidak ada transaksi dari porterId, mencoba dari userId: $userId'); loadTransactionsFromUserId(userId); } else { transactions.assignAll(transactionList); isLoading.value = false; } }, onError: (e) { log('Error streaming transaksi: $e'); // Jika terjadi error, coba dari userId sebagai fallback if (userId != porterId) { log('Error dengan porterId, mencoba dari userId: $userId'); loadTransactionsFromUserId(userId); } else { error.value = 'Gagal memuat transaksi: $e'; isLoading.value = false; } }); } void loadTransactionsFromUserId(String userId) { isLoading.value = true; error.value = ''; log('[TransactionPorterController] Memuat transaksi untuk userId: $userId'); // Gunakan userId sebagai porterId di porterHistory _useCase.getPorterTransactionIds(userId).then((transactionIds) { log('[TransactionPorterController] Ditemukan ${transactionIds.length} ID transaksi untuk userId: $userId'); if (transactionIds.isEmpty) { transactions.clear(); isLoading.value = false; return; } // Ambil dan proses data transaksi _processTransactionData(transactionIds); }).catchError((e) { log('[TransactionPorterController] Error mendapatkan ID transaksi: $e'); error.value = 'Gagal memuat riwayat transaksi'; isLoading.value = false; }); } void watchTransaction(String transactionId) { // Batalkan subscription yang ada jika ada _transactionWatchers[transactionId]?.cancel(); // Mulai subscription baru _transactionWatchers[transactionId] = _useCase.watchTransactionById(transactionId).listen( (updatedTransaction) { if (updatedTransaction != null) { // Update current transaction jika itu transaksi yang sedang aktif if (currentTransaction.value?.id == transactionId) { currentTransaction.value = updatedTransaction; } // Update transaksi di daftar final index = transactions.indexWhere((tx) => tx.id == transactionId); if (index >= 0) { transactions[index] = updatedTransaction; log('Transaksi diperbarui secara real-time: $transactionId, status: ${updatedTransaction.status}'); } } }, onError: (error) { log('Error memantau transaksi: $error'); }, ); } void _processTransactionData(List transactionIds) async { try { List txList = []; for (var id in transactionIds) { final txData = await _useCase.getPorterTransactionById(id); if (txData != null) { txList.add(PorterTransactionModel.fromJson(txData, id)); } } // Urutkan berdasarkan tanggal terbaru txList.sort((a, b) => b.createdAt.compareTo(a.createdAt)); // Update transactions list transactions.assignAll(txList); isLoading.value = false; } catch (e) { log('Error memproses data transaksi: $e'); error.value = 'Gagal memproses data transaksi'; isLoading.value = false; } } void loadTransactionsFromPorterId(String porterId) { if (porterId.isEmpty) { error.value = 'Porter ID tidak boleh kosong'; return; } isLoading.value = true; error.value = ''; _subscription?.cancel(); _subscription = _useCase.watchPorterTransactions(porterId).listen((transactionList) { log('Menerima ${transactionList.length} transaksi'); transactions.assignAll(transactionList); // Mulai memantau setiap transaksi individual untuk real-time updates for (var transaction in transactionList) { watchTransaction(transaction.id); } isLoading.value = false; }, onError: (e) { log('Error streaming transaksi: $e'); error.value = 'Gagal memuat transaksi: $e'; isLoading.value = false; }); } Future?> getPorterTransactionById(String transactionId) async { try { isLoading.value = true; error.value = ''; return await _useCase.getPorterTransactionById(transactionId); } catch (e) { log('Error getting transaction data: $e'); error.value = 'Gagal mendapatkan data transaksi: $e'; return null; } finally { isLoading.value = false; } } Future getTransactionById(String transactionId) async { try { log('Getting transaction by ID: $transactionId'); isLoading.value = true; error.value = ''; // Reset dulu current transaction agar UI bisa merespons ke loading state currentTransaction.value = null; final transaction = await _useCase.getTransactionById(transactionId); if (transaction != null) { log('Transaction found and set to current: ${transaction.id}'); currentTransaction.value = transaction; // Mulai memantau transaksi ini watchTransaction(transactionId); } else { log('Transaction not found with ID: $transactionId'); error.value = 'Transaksi tidak ditemukan'; } return transaction; } catch (e) { log('Error getting transaction by ID: $e'); error.value = 'Gagal mendapatkan detail transaksi: $e'; return null; } finally { isLoading.value = false; } } Future updateTransactionStatus({ required String transactionId, required String status, }) async { try { isLoading.value = true; error.value = ''; log('Memperbarui status transaksi: $transactionId menjadi $status'); await _useCase.updateTransactionStatus( transactionId: transactionId, status: status, ); // Dapatkan transaksi yang diperbarui final updatedTransaction = await getTransactionById(transactionId); // Update list transaksi yang ada dengan yang baru if (updatedTransaction != null) { // Cari indeks transaksi dalam list yang ada final index = transactions.indexWhere((tx) => tx.id == transactionId); if (index >= 0) { // Update transaksi pada indeks yang ditemukan transactions[index] = updatedTransaction; log('Transaksi di daftar utama diperbarui: $transactionId dengan status: $status'); } else { // Jika tidak ditemukan, perbarui seluruh list log('Transaksi tidak ditemukan di daftar, menyegarkan seluruh daftar'); refreshTransactions(); } } SnackbarHelper.showSuccess('Berhasil', 'Status transaksi berhasil diperbarui'); } catch (e) { log('Error memperbarui status: $e'); error.value = 'Gagal memperbarui status transaksi: $e'; SnackbarHelper.showError('Terjadi Kesalahan', 'Status transaksi gagal diperbarui'); } finally { isLoading.value = false; } } // Metode serupa untuk completePorterTransaction Future completePorterTransaction({ required String transactionId, }) async { try { isLoading.value = true; error.value = ''; final transaction = currentTransaction.value; if (transaction == null) { throw Exception('Tidak dapat menemukan data transaksi'); } final porterOnlineId = transaction.porterOnlineId; if (porterOnlineId.isEmpty) { throw Exception('ID Porter Online tidak ditemukan'); } log('Menyelesaikan transaksi: $transactionId dengan porter: $porterOnlineId'); await _useCase.completePorterTransaction( transactionId: transactionId, porterOnlineId: porterOnlineId, ); // Dapatkan transaksi yang diperbarui final updatedTransaction = await getTransactionById(transactionId); // Update list transaksi if (updatedTransaction != null) { final index = transactions.indexWhere((tx) => tx.id == transactionId); if (index >= 0) { transactions[index] = updatedTransaction; log('Transaksi di daftar utama diperbarui menjadi selesai: $transactionId'); } else { refreshTransactions(); } } SnackbarHelper.showSuccess('Transaksi Selesai', 'Transaksi porter berhasil diselesaikan'); } catch (e) { log('Error menyelesaikan transaksi: $e'); error.value = 'Gagal menyelesaikan transaksi: $e'; SnackbarHelper.showError('Terjadi Kesalahan', 'Gagal menyelesaikan transaksi'); } finally { isLoading.value = false; } } Future refreshTransactions() async { final id = currentPorterId.value; if (id.isEmpty) { try { final userData = await PreferencesService.getUserData(); if (userData != null && userData.uid.isNotEmpty) { currentPorterId.value = userData.uid; log('Retrieved porter ID from preferences during refresh: ${userData.uid}'); } else { error.value = 'ID porter tidak tersedia'; return; } } catch (e) { log('Error getting user data for refresh: $e'); error.value = 'Gagal memperoleh ID porter: $e'; return; } } log('Refreshing transactions for porter: ${currentPorterId.value}'); isLoading.value = true; loadTransactionsFromPorterId(currentPorterId.value); } @override void onClose() { _porterSubscription?.cancel(); _subscription?.cancel(); for (var subscription in _transactionWatchers.values) { subscription.cancel(); } _transactionWatchers.clear(); super.onClose(); } }