/// Tests unitaires pour ExportMembers use case
library export_members_test;

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:unionflow_mobile_apps/features/members/domain/repositories/membre_repository.dart';
import 'package:unionflow_mobile_apps/features/members/domain/usecases/export_members.dart';
import 'package:unionflow_mobile_apps/features/members/data/models/membre_complete_model.dart';
import 'package:unionflow_mobile_apps/shared/models/membre_search_result.dart';
import 'package:unionflow_mobile_apps/shared/models/membre_search_criteria.dart';

@GenerateMocks([IMembreRepository])
import 'export_members_test.mocks.dart';

void main() {
  late ExportMembers useCase;
  late MockIMembreRepository mockRepository;

  setUp(() {
    mockRepository = MockIMembreRepository();
    useCase = ExportMembers(mockRepository);
  });

  group('ExportMembers Use Case', () {
    const tFormat = 'csv';
    final tCriteria = MembreSearchCriteria(
      statut: 'ACTIF',
    );

    final tMembers = [
      MembreCompletModel(
        id: '1',
        nom: 'Diallo',
        prenom: 'Amadou',
        email: 'amadou@example.com',
        genre: Genre.homme,
        statut: StatutMembre.actif,
      ),
      MembreCompletModel(
        id: '2',
        nom: 'Ndiaye',
        prenom: 'Fatou',
        email: 'fatou@example.com',
        genre: Genre.femme,
        statut: StatutMembre.actif,
      ),
    ];

    final tSearchResult = MembreSearchResult(
      membres: tMembers,
      totalElements: 2,
      totalPages: 1,
      currentPage: 0,
      pageSize: 10000,
      numberOfElements: 2,
      hasNext: false,
      hasPrevious: false,
      isFirst: true,
      isLast: true,
      criteria: tCriteria,
      executionTimeMs: 50,
    );

    test('should export members to CSV format successfully', () async {
      // Arrange
      when(mockRepository.searchMembres(
        criteria: anyNamed('criteria'),
        page: anyNamed('page'),
        size: anyNamed('size'),
      )).thenAnswer((_) async => tSearchResult);

      // Act
      final result = await useCase(criteria: tCriteria, format: tFormat);

      // Assert
      expect(result, isA<List<Map<String, dynamic>>>());
      expect(result.length, equals(2));
      expect(result[0]['nom'], equals('Diallo'));
      expect(result[0]['email'], equals('amadou@example.com'));
      verify(mockRepository.searchMembres(
        criteria: anyNamed('criteria'),
        page: anyNamed('page'),
        size: anyNamed('size'),
      ));
      verifyNoMoreInteractions(mockRepository);
    });

    test('should export members to PDF format', () async {
      // Arrange
      const pdfFormat = 'pdf';
      when(mockRepository.searchMembres(
        criteria: anyNamed('criteria'),
        page: anyNamed('page'),
        size: anyNamed('size'),
      )).thenAnswer((_) async => tSearchResult);

      // Act
      final result = await useCase(criteria: tCriteria, format: pdfFormat);

      // Assert
      expect(result.length, equals(2));
      expect(result[1]['prenom'], equals('Fatou'));
    });

    test('should export all members when no criteria provided', () async {
      // Arrange
      when(mockRepository.searchMembres(
        criteria: anyNamed('criteria'),
        page: anyNamed('page'),
        size: anyNamed('size'),
      )).thenAnswer((_) async => tSearchResult);

      // Act
      final result = await useCase(criteria: null, format: tFormat);

      // Assert
      expect(result, isNotNull);
      expect(result.length, equals(2));
    });

    test('should throw exception when export fails', () async {
      // Arrange
      when(mockRepository.searchMembres(
        criteria: anyNamed('criteria'),
        page: anyNamed('page'),
        size: anyNamed('size'),
      )).thenThrow(Exception('Échec de l\'export'));

      // Act & Assert
      expect(() => useCase(criteria: tCriteria, format: tFormat), throwsException);
    });
  });
}
