import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import 'expense_split.dart'; enum ExpenseCurrency { eur('€', 'EUR'), usd('\$', 'USD'), gbp('£', 'GBP'); const ExpenseCurrency(this.symbol, this.code); final String symbol; final String code; } enum ExpenseCategory { restaurant('Restaurant', Icons.restaurant), transport('Transport', Icons.directions_car), accommodation('Hébergement', Icons.hotel), entertainment('Loisirs', Icons.local_activity), shopping('Shopping', Icons.shopping_bag), other('Autre', Icons.category); const ExpenseCategory(this.displayName, this.icon); final String displayName; final IconData icon; } class Expense extends Equatable { final String id; final String groupId; final String description; final double amount; final ExpenseCurrency currency; final double amountInEur; // Montant converti en EUR final ExpenseCategory category; final String paidById; final String paidByName; final DateTime date; final DateTime createdAt; final DateTime? editedAt; final bool isEdited; final bool isArchived; final String? receiptUrl; final List splits; const Expense({ required this.id, required this.groupId, required this.description, required this.amount, required this.currency, required this.amountInEur, required this.category, required this.paidById, required this.paidByName, required this.date, required this.createdAt, this.editedAt, this.isEdited = false, this.isArchived = false, this.receiptUrl, required this.splits, }); factory Expense.fromMap(Map map, String id) { return Expense( id: id, groupId: map['groupId'] ?? '', description: map['description'] ?? '', amount: (map['amount'] as num?)?.toDouble() ?? 0.0, currency: ExpenseCurrency.values.firstWhere( (c) => c.code == map['currency'], orElse: () => ExpenseCurrency.eur, ), amountInEur: (map['amountInEur'] as num?)?.toDouble() ?? 0.0, category: ExpenseCategory.values.firstWhere( (c) => c.name == map['category'], orElse: () => ExpenseCategory.other, ), paidById: map['paidById'] ?? '', paidByName: map['paidByName'] ?? '', date: _parseDateTime(map['date']), createdAt: _parseDateTime(map['createdAt']), editedAt: map['editedAt'] != null ? _parseDateTime(map['editedAt']) : null, isEdited: map['isEdited'] ?? false, isArchived: map['isArchived'] ?? false, receiptUrl: map['receiptUrl'], splits: (map['splits'] as List?) ?.map((s) => ExpenseSplit.fromMap(s)) .toList() ?? [], ); } Map toMap() { return { 'groupId': groupId, 'description': description, 'amount': amount, 'currency': currency.code, 'amountInEur': amountInEur, 'category': category.name, 'paidById': paidById, 'paidByName': paidByName, 'date': Timestamp.fromDate(date), 'createdAt': Timestamp.fromDate(createdAt), 'editedAt': editedAt != null ? Timestamp.fromDate(editedAt!) : null, 'isEdited': isEdited, 'isArchived': isArchived, 'receiptUrl': receiptUrl, 'splits': splits.map((s) => s.toMap()).toList(), }; } static DateTime _parseDateTime(dynamic value) { if (value is Timestamp) return value.toDate(); if (value is String) return DateTime.parse(value); if (value is DateTime) return value; return DateTime.now(); } Expense copyWith({ String? id, String? groupId, String? description, double? amount, ExpenseCurrency? currency, double? amountInEur, ExpenseCategory? category, String? paidById, String? paidByName, DateTime? date, DateTime? createdAt, DateTime? editedAt, bool? isEdited, bool? isArchived, String? receiptUrl, List? splits, }) { return Expense( id: id ?? this.id, groupId: groupId ?? this.groupId, description: description ?? this.description, amount: amount ?? this.amount, currency: currency ?? this.currency, amountInEur: amountInEur ?? this.amountInEur, category: category ?? this.category, paidById: paidById ?? this.paidById, paidByName: paidByName ?? this.paidByName, date: date ?? this.date, createdAt: createdAt ?? this.createdAt, editedAt: editedAt ?? this.editedAt, isEdited: isEdited ?? this.isEdited, isArchived: isArchived ?? this.isArchived, receiptUrl: receiptUrl ?? this.receiptUrl, splits: splits ?? this.splits, ); } Expense copyWithEdit({ String? description, double? amount, ExpenseCurrency? currency, double? amountInEur, ExpenseCategory? category, List? splits, String? receiptUrl, }) { return copyWith( description: description, amount: amount, currency: currency, amountInEur: amountInEur, category: category, splits: splits, receiptUrl: receiptUrl, editedAt: DateTime.now(), isEdited: true, ); } // Marquer comme archivé Expense copyWithArchived() { return copyWith( isArchived: true, ); } // Ajouter/mettre à jour l'URL du reçu Expense copyWithReceipt(String receiptUrl) { return copyWith( receiptUrl: receiptUrl, ); } // Mettre à jour les splits Expense copyWithSplits(List newSplits) { return copyWith( splits: newSplits, ); } @override List get props => [id]; }