import 'package:cloud_firestore/cloud_firestore.dart'; import '../models/expense.dart'; import '../services/error_service.dart'; class ExpenseRepository { final FirebaseFirestore _firestore; final ErrorService _errorService; ExpenseRepository({ FirebaseFirestore? firestore, ErrorService? errorService, }) : _firestore = firestore ?? FirebaseFirestore.instance, _errorService = errorService ?? ErrorService(); CollectionReference get _expensesCollection => _firestore.collection('expenses'); // Stream des dépenses d'un groupe Stream> getExpensesStream(String groupId) { return _expensesCollection .where('groupId', isEqualTo: groupId) .where('isArchived', isEqualTo: false) .orderBy('createdAt', descending: true) .snapshots() .map((snapshot) { return snapshot.docs .map((doc) => Expense.fromMap(doc.data() as Map, doc.id)) .toList(); }).handleError((error) { _errorService.logError('ExpenseRepository', 'Erreur stream expenses: $error'); return []; }); } // Créer une dépense Future createExpense(Expense expense) async { try { final docRef = await _expensesCollection.add(expense.toMap()); return docRef.id; } catch (e) { _errorService.logError('ExpenseRepository', 'Erreur création expense: $e'); rethrow; } } // Mettre à jour une dépense Future updateExpense(Expense expense) async { try { final updateData = expense.toMap(); updateData['editedAt'] = FieldValue.serverTimestamp(); updateData['isEdited'] = true; await _expensesCollection.doc(expense.id).update(updateData); } catch (e) { _errorService.logError('ExpenseRepository', 'Erreur update expense: $e'); rethrow; } } // Supprimer une dépense Future deleteExpense(String expenseId) async { try { await _expensesCollection.doc(expenseId).delete(); } catch (e) { _errorService.logError('ExpenseRepository', 'Erreur delete expense: $e'); rethrow; } } // Marquer un split comme payé Future markSplitAsPaid(String expenseId, String userId) async { try { await _firestore.runTransaction((transaction) async { final expenseDoc = await transaction.get(_expensesCollection.doc(expenseId)); if (!expenseDoc.exists) { throw Exception('Dépense non trouvée'); } final expense = Expense.fromMap( expenseDoc.data() as Map, expenseDoc.id ); final updatedSplits = expense.splits.map((split) { if (split.userId == userId) { return split.copyWith(isPaid: true, paidAt: DateTime.now()); } return split; }).toList(); transaction.update(expenseDoc.reference, { 'splits': updatedSplits.map((s) => s.toMap()).toList(), }); }); } catch (e) { _errorService.logError('ExpenseRepository', 'Erreur mark split paid: $e'); rethrow; } } // Archiver une dépense Future archiveExpense(String expenseId) async { try { await _expensesCollection.doc(expenseId).update({ 'isArchived': true, 'archivedAt': FieldValue.serverTimestamp(), }); } catch (e) { _errorService.logError('ExpenseRepository', 'Erreur archive expense: $e'); rethrow; } } }