import 'dart:io';
import '../models/expense.dart';
import '../repositories/expense_repository.dart';
import 'error_service.dart';
import 'storage_service.dart';

/// Service for managing expense operations with business logic validation.
/// 
/// This service provides high-level expense management functionality including
/// validation, receipt image uploading, and coordination with the expense repository.
/// It acts as a business logic layer between the UI and data persistence.
class ExpenseService {
  /// Repository for expense data operations.
  final ExpenseRepository _expenseRepository;
  
  /// Service for error handling and logging.
  final ErrorService _errorService;
  
  /// Service for handling file uploads (receipts).
  final StorageService _storageService;

  /// Creates a new [ExpenseService] with required dependencies.
  /// 
  /// [expenseRepository] is required for data operations.
  /// [errorService] and [storageService] have default implementations if not provided.
  ExpenseService({
    required ExpenseRepository expenseRepository,
    ErrorService? errorService,
    StorageService? storageService,
  }) : _expenseRepository = expenseRepository,
       _errorService = errorService ?? ErrorService(),
       _storageService = storageService ?? StorageService();

  /// Creates an expense with validation and optional receipt image upload.
  /// 
  /// Validates the expense data, uploads receipt image if provided, and
  /// creates the expense record in the database.
  /// 
  /// [expense] - The expense data to create
  /// [receiptImage] - Optional receipt image file to upload
  /// 
  /// Returns the ID of the created expense.
  /// Throws exceptions if validation fails or creation errors occur.
  Future<String> createExpenseWithValidation(Expense expense, File? receiptImage) async {
    try {
      // Business logic validation
      _validateExpenseData(expense);
      
      // Upload receipt image if provided
      String? receiptUrl;
      if (receiptImage != null) {
        receiptUrl = await _storageService.uploadReceiptImage(
          expense.groupId,
          receiptImage,
        );
      }
      
      // Créer l'expense avec l'URL du reçu
      final expenseWithReceipt = expense.copyWith(receiptUrl: receiptUrl);
      
      return await _expenseRepository.createExpense(expenseWithReceipt);
    } catch (e) {
      _errorService.logError('ExpenseService', 'Erreur création expense: $e');
      rethrow;
    }
  }

  // Mise à jour avec validation
  Future<void> updateExpenseWithValidation(Expense expense, File? newReceiptImage) async {
    try {
      _validateExpenseData(expense);
      
      // Gérer le nouvel upload si nécessaire
      String? receiptUrl = expense.receiptUrl;
      if (newReceiptImage != null) {
        receiptUrl = await _storageService.uploadReceiptImage(
          expense.groupId,
          newReceiptImage,
        );
      }
      
      final expenseWithReceipt = expense.copyWith(
        receiptUrl: receiptUrl,
        editedAt: DateTime.now(),
        isEdited: true,
      );
      
      await _expenseRepository.updateExpense(expenseWithReceipt);
    } catch (e) {
      _errorService.logError('ExpenseService', 'Erreur update expense: $e');
      rethrow;
    }
  }

  // Validation des données
  void _validateExpenseData(Expense expense) {
    if (expense.description.trim().isEmpty) {
      throw Exception('La description est requise');
    }

    if (expense.amount <= 0) {
      throw Exception('Le montant doit être positif');
    }

    if (expense.splits.isEmpty) {
      throw Exception('Au moins un participant est requis');
    }

    final totalSplits = expense.splits.fold(0.0, (sum, split) => sum + split.amount);
    if ((totalSplits - expense.amountInEur).abs() > 0.01) {
      throw Exception('La somme des répartitions ne correspond pas au montant total');
    }
  }
}