/// Entité métier Budget
///
/// Représente un budget prévisionnel (mensuel/annuel) avec suivi réalisé
library budget;

import 'package:equatable/equatable.dart';

/// Période du budget
enum BudgetPeriod {
  /// Budget mensuel
  monthly,

  /// Budget trimestriel
  quarterly,

  /// Budget semestriel
  semiannual,

  /// Budget annuel
  annual,
}

/// Statut du budget
enum BudgetStatus {
  /// Brouillon (en cours de création)
  draft,

  /// Actif
  active,

  /// Clos (période terminée)
  closed,

  /// Annulé
  cancelled,
}

/// Catégorie budgétaire
enum BudgetCategory {
  /// Cotisations/contributions
  contributions,

  /// Épargne
  savings,

  /// Solidarité
  solidarity,

  /// Événements
  events,

  /// Fonctionnement (frais généraux)
  operational,

  /// Investissements
  investments,

  /// Autres
  other,
}

/// Entité Budget
class Budget extends Equatable {
  final String id;
  final String name;
  final String? description;
  final String organizationId;
  final BudgetPeriod period;
  final int year;
  final int? month;
  final BudgetStatus status;
  final List<BudgetLine> lines;
  final double totalPlanned;
  final double totalRealized;
  final String currency;
  final String createdBy;
  final DateTime createdAt;
  final DateTime? approvedAt;
  final String? approvedBy;
  final DateTime startDate;
  final DateTime endDate;
  final Map<String, dynamic>? metadata;

  const Budget({
    required this.id,
    required this.name,
    this.description,
    required this.organizationId,
    required this.period,
    required this.year,
    this.month,
    required this.status,
    this.lines = const [],
    required this.totalPlanned,
    this.totalRealized = 0,
    this.currency = 'XOF',
    required this.createdBy,
    required this.createdAt,
    this.approvedAt,
    this.approvedBy,
    required this.startDate,
    required this.endDate,
    this.metadata,
  });

  /// Taux de réalisation (%)
  double get realizationRate {
    if (totalPlanned == 0) return 0;
    return (totalRealized / totalPlanned) * 100;
  }

  /// Écart (réalisé - prévu)
  double get variance => totalRealized - totalPlanned;

  /// Taux d'écart (%)
  double get varianceRate {
    if (totalPlanned == 0) return 0;
    return (variance / totalPlanned) * 100;
  }

  /// Vérifie si le budget est dépassé
  bool get isOverBudget => totalRealized > totalPlanned;

  /// Vérifie si le budget est actif
  bool get isActive => status == BudgetStatus.active;

  /// Vérifie si la période est en cours
  bool get isCurrentPeriod {
    final now = DateTime.now();
    return now.isAfter(startDate) && now.isBefore(endDate);
  }

  /// Copie avec modifications
  Budget copyWith({
    String? id,
    String? name,
    String? description,
    String? organizationId,
    BudgetPeriod? period,
    int? year,
    int? month,
    BudgetStatus? status,
    List<BudgetLine>? lines,
    double? totalPlanned,
    double? totalRealized,
    String? currency,
    String? createdBy,
    DateTime? createdAt,
    DateTime? approvedAt,
    String? approvedBy,
    DateTime? startDate,
    DateTime? endDate,
    Map<String, dynamic>? metadata,
  }) {
    return Budget(
      id: id ?? this.id,
      name: name ?? this.name,
      description: description ?? this.description,
      organizationId: organizationId ?? this.organizationId,
      period: period ?? this.period,
      year: year ?? this.year,
      month: month ?? this.month,
      status: status ?? this.status,
      lines: lines ?? this.lines,
      totalPlanned: totalPlanned ?? this.totalPlanned,
      totalRealized: totalRealized ?? this.totalRealized,
      currency: currency ?? this.currency,
      createdBy: createdBy ?? this.createdBy,
      createdAt: createdAt ?? this.createdAt,
      approvedAt: approvedAt ?? this.approvedAt,
      approvedBy: approvedBy ?? this.approvedBy,
      startDate: startDate ?? this.startDate,
      endDate: endDate ?? this.endDate,
      metadata: metadata ?? this.metadata,
    );
  }

  @override
  List<Object?> get props => [
        id,
        name,
        description,
        organizationId,
        period,
        year,
        month,
        status,
        lines,
        totalPlanned,
        totalRealized,
        currency,
        createdBy,
        createdAt,
        approvedAt,
        approvedBy,
        startDate,
        endDate,
        metadata,
      ];
}

/// Ligne budgétaire
class BudgetLine extends Equatable {
  final String id;
  final BudgetCategory category;
  final String name;
  final String? description;
  final double amountPlanned;
  final double amountRealized;
  final String? notes;

  const BudgetLine({
    required this.id,
    required this.category,
    required this.name,
    this.description,
    required this.amountPlanned,
    this.amountRealized = 0,
    this.notes,
  });

  /// Taux de réalisation (%)
  double get realizationRate {
    if (amountPlanned == 0) return 0;
    return (amountRealized / amountPlanned) * 100;
  }

  /// Écart
  double get variance => amountRealized - amountPlanned;

  /// Vérifie si la ligne est dépassée
  bool get isOverBudget => amountRealized > amountPlanned;

  @override
  List<Object?> get props => [
        id,
        category,
        name,
        description,
        amountPlanned,
        amountRealized,
        notes,
      ];
}
