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<List<Expense>> 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<String, dynamic>, doc.id))
          .toList();
    }).handleError((error) {
      _errorService.logError('ExpenseRepository', 'Erreur stream expenses: $error');
      return <Expense>[];
    });
  }

  // Créer une dépense
  Future<String> 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<void> 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<void> 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<void> 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<String, dynamic>, 
          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<void> 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;
    }
  }
}