/// Tests unitaires pour GetContributionHistory use case
library get_contribution_history_test;

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:unionflow_mobile_apps/features/contributions/domain/repositories/contribution_repository.dart';
import 'package:unionflow_mobile_apps/features/contributions/domain/usecases/get_contribution_history.dart';
import 'package:unionflow_mobile_apps/features/contributions/data/models/contribution_model.dart';
import 'package:unionflow_mobile_apps/features/contributions/data/repositories/contribution_repository.dart';

@GenerateMocks([IContributionRepository])
import 'get_contribution_history_test.mocks.dart';

void main() {
  late GetContributionHistory useCase;
  late MockIContributionRepository mockRepository;

  setUp(() {
    mockRepository = MockIContributionRepository();
    useCase = GetContributionHistory(mockRepository);
  });

  group('GetContributionHistory Use Case', () {
    final tHistoryList = [
      ContributionModel(
        id: 'cont1',
        membreId: 'membre1',
        montant: 5000.0,
        montantPaye: 5000.0,
        dateEcheance: DateTime(2024, 1, 31),
        datePaiement: DateTime(2024, 1, 15),
        annee: 2024,
        mois: 1,
        type: ContributionType.mensuelle,
        statut: ContributionStatus.payee,
      ),
      ContributionModel(
        id: 'cont2',
        membreId: 'membre1',
        montant: 5000.0,
        dateEcheance: DateTime(2024, 2, 28),
        annee: 2024,
        mois: 2,
        type: ContributionType.mensuelle,
        statut: ContributionStatus.enAttente,
      ),
    ];

    final tPageResult = ContributionPageResult(
      contributions: tHistoryList,
      total: 2,
      totalPages: 1,
      page: 0,
      size: 50,
    );

    test('should return contribution history', () async {
      // Arrange
      when(mockRepository.getMesCotisations(page: anyNamed('page'), size: anyNamed('size')))
          .thenAnswer((_) async => tPageResult);

      // Act
      final result = await useCase(page: 0, size: 50);

      // Assert
      expect(result, equals(tPageResult));
      expect(result.contributions.length, equals(2));
      expect(result.contributions[0].statut, equals(ContributionStatus.payee));
      expect(result.contributions[1].statut, equals(ContributionStatus.enAttente));
      verify(mockRepository.getMesCotisations(page: 0, size: 50));
      verifyNoMoreInteractions(mockRepository);
    });

    test('should return history for specific year', () async {
      // Arrange
      final year2023List = [
        ContributionModel(
          id: 'cont3',
          membreId: 'membre1',
          montant: 60000.0,
          montantPaye: 60000.0,
          dateEcheance: DateTime(2023, 12, 31),
          datePaiement: DateTime(2023, 12, 15),
          annee: 2023,
          type: ContributionType.annuelle,
          statut: ContributionStatus.payee,
        ),
      ];
      final yearPageResult = ContributionPageResult(
        contributions: year2023List,
        total: 1,
        totalPages: 1,
        page: 0,
        size: 50,
      );
      when(mockRepository.getMesCotisations(page: 0, size: 50))
          .thenAnswer((_) async => yearPageResult);

      // Act
      final result = await useCase(page: 0, size: 50, annee: 2023);

      // Assert
      expect(result.contributions.length, equals(1));
      expect(result.contributions.first.annee, equals(2023));
    });

    test('should return history filtered by status', () async {
      // Arrange
      final paidOnly = [tHistoryList[0]];
      final paidPageResult = ContributionPageResult(
        contributions: paidOnly,
        total: 1,
        totalPages: 1,
        page: 0,
        size: 50,
      );
      when(mockRepository.getMesCotisations(page: 0, size: 50))
          .thenAnswer((_) async => paidPageResult);

      // Act
      final result = await useCase(
        page: 0,
        size: 50,
        statut: ContributionStatus.payee,
      );

      // Assert
      expect(result.contributions.length, equals(1));
      expect(result.contributions.first.statut, equals(ContributionStatus.payee));
    });

    test('should return empty history when no contributions', () async {
      // Arrange
      final emptyResult = ContributionPageResult(
        contributions: [],
        total: 0,
        totalPages: 0,
        page: 0,
        size: 50,
      );
      when(mockRepository.getMesCotisations(page: anyNamed('page'), size: anyNamed('size')))
          .thenAnswer((_) async => emptyResult);

      // Act
      final result = await useCase();

      // Assert
      expect(result.contributions, isEmpty);
      expect(result.total, equals(0));
    });
  });
}
