/// Entité métier Approbation Transaction
///
/// Représente une approbation dans le workflow financier multi-niveaux
library transaction_approval;

import 'package:equatable/equatable.dart';

/// Statut de l'approbation
enum ApprovalStatus {
  /// En attente d'approbation
  pending,

  /// Approuvée (niveau 1)
  approved,

  /// Validée (niveau 2 - validation finale)
  validated,

  /// Rejetée
  rejected,

  /// Expirée (timeout)
  expired,

  /// Annulée
  cancelled,
}

/// Niveau d'approbation requis selon montant
enum ApprovalLevel {
  /// Aucune approbation requise (< seuil)
  none,

  /// Niveau 1 : Un approbateur requis
  level1,

  /// Niveau 2 : Deux approbateurs requis
  level2,

  /// Niveau 3 : Trois approbateurs requis (montants très élevés)
  level3,
}

/// Type de transaction financière
enum TransactionType {
  /// Cotisation/contribution
  contribution,

  /// Dépôt épargne
  deposit,

  /// Retrait épargne
  withdrawal,

  /// Transfert
  transfer,

  /// Dépense solidarité
  solidarity,

  /// Dépense événement
  event,

  /// Autre dépense
  other,
}

/// Entité Approbation de Transaction
class TransactionApproval extends Equatable {
  final String id;
  final String transactionId;
  final TransactionType transactionType;
  final double amount;
  final String currency;
  final String requesterId;
  final String requesterName;
  final String? organizationId;
  final ApprovalLevel requiredLevel;
  final ApprovalStatus status;
  final List<ApproverAction> approvers;
  final String? rejectionReason;
  final DateTime createdAt;
  final DateTime? expiresAt;
  final DateTime? completedAt;
  final Map<String, dynamic>? metadata;

  const TransactionApproval({
    required this.id,
    required this.transactionId,
    required this.transactionType,
    required this.amount,
    this.currency = 'XOF',
    required this.requesterId,
    required this.requesterName,
    this.organizationId,
    required this.requiredLevel,
    required this.status,
    this.approvers = const [],
    this.rejectionReason,
    required this.createdAt,
    this.expiresAt,
    this.completedAt,
    this.metadata,
  });

  /// Vérifie si l'approbation est en attente
  bool get isPending => status == ApprovalStatus.pending;

  /// Vérifie si l'approbation est complétée
  bool get isCompleted =>
      status == ApprovalStatus.validated ||
      status == ApprovalStatus.rejected ||
      status == ApprovalStatus.cancelled;

  /// Vérifie si l'approbation est expirée
  bool get isExpired {
    if (expiresAt == null) return false;
    return DateTime.now().isAfter(expiresAt!);
  }

  /// Nombre d'approbations reçues
  int get approvalCount =>
      approvers.where((a) => a.decision == ApprovalDecision.approved).length;

  /// Nombre d'approbations requises
  int get requiredApprovals {
    switch (requiredLevel) {
      case ApprovalLevel.none:
        return 0;
      case ApprovalLevel.level1:
        return 1;
      case ApprovalLevel.level2:
        return 2;
      case ApprovalLevel.level3:
        return 3;
    }
  }

  /// Vérifie si toutes les approbations sont reçues
  bool get hasAllApprovals => approvalCount >= requiredApprovals;

  /// Copie avec modifications
  TransactionApproval copyWith({
    String? id,
    String? transactionId,
    TransactionType? transactionType,
    double? amount,
    String? currency,
    String? requesterId,
    String? requesterName,
    String? organizationId,
    ApprovalLevel? requiredLevel,
    ApprovalStatus? status,
    List<ApproverAction>? approvers,
    String? rejectionReason,
    DateTime? createdAt,
    DateTime? expiresAt,
    DateTime? completedAt,
    Map<String, dynamic>? metadata,
  }) {
    return TransactionApproval(
      id: id ?? this.id,
      transactionId: transactionId ?? this.transactionId,
      transactionType: transactionType ?? this.transactionType,
      amount: amount ?? this.amount,
      currency: currency ?? this.currency,
      requesterId: requesterId ?? this.requesterId,
      requesterName: requesterName ?? this.requesterName,
      organizationId: organizationId ?? this.organizationId,
      requiredLevel: requiredLevel ?? this.requiredLevel,
      status: status ?? this.status,
      approvers: approvers ?? this.approvers,
      rejectionReason: rejectionReason ?? this.rejectionReason,
      createdAt: createdAt ?? this.createdAt,
      expiresAt: expiresAt ?? this.expiresAt,
      completedAt: completedAt ?? this.completedAt,
      metadata: metadata ?? this.metadata,
    );
  }

  @override
  List<Object?> get props => [
        id,
        transactionId,
        transactionType,
        amount,
        currency,
        requesterId,
        requesterName,
        organizationId,
        requiredLevel,
        status,
        approvers,
        rejectionReason,
        createdAt,
        expiresAt,
        completedAt,
        metadata,
      ];
}

/// Décision d'un approbateur
enum ApprovalDecision {
  /// En attente
  pending,

  /// Approuvé
  approved,

  /// Rejeté
  rejected,
}

/// Action d'un approbateur
class ApproverAction extends Equatable {
  final String approverId;
  final String approverName;
  final String approverRole;
  final ApprovalDecision decision;
  final String? comment;
  final DateTime? decidedAt;

  const ApproverAction({
    required this.approverId,
    required this.approverName,
    required this.approverRole,
    required this.decision,
    this.comment,
    this.decidedAt,
  });

  @override
  List<Object?> get props => [
        approverId,
        approverName,
        approverRole,
        decision,
        comment,
        decidedAt,
      ];
}
