/// Tests unitaires pour GetMembers use case
library get_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/get_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 'get_members_test.mocks.dart';

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

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

  group('GetMembers Use Case', () {
    final tMembersList = [
      MembreCompletModel(
        id: '1',
        nom: 'Diallo',
        prenom: 'Amadou',
        email: 'amadou.diallo@example.com',
        genre: Genre.homme,
        statut: StatutMembre.actif,
      ),
      MembreCompletModel(
        id: '2',
        nom: 'Ndiaye',
        prenom: 'Fatou',
        email: 'fatou.ndiaye@example.com',
        genre: Genre.femme,
        statut: StatutMembre.actif,
      ),
    ];

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

    test('should return paginated list of all members', () async {
      // Arrange
      when(mockRepository.getMembres(
        page: anyNamed('page'),
        size: anyNamed('size'),
        recherche: anyNamed('recherche'),
      )).thenAnswer((_) async => tSearchResult);

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

      // Assert
      expect(result, equals(tSearchResult));
      expect(result.membres.length, equals(2));
      expect(result.totalElements, equals(2));
      expect(result.membres[0].nom, equals('Diallo'));
      verify(mockRepository.getMembres(
        page: 0,
        size: 50,
        recherche: null,
      ));
      verifyNoMoreInteractions(mockRepository);
    });

    test('should return members with custom page size', () async {
      // Arrange
      final smallResult = MembreSearchResult(
        membres: [tMembersList[0]],
        totalElements: 2,
        totalPages: 2,
        currentPage: 0,
        pageSize: 1,
        numberOfElements: 1,
        hasNext: true,
        hasPrevious: false,
        isFirst: true,
        isLast: false,
        criteria: MembreSearchCriteria(),
        executionTimeMs: 30,
      );
      when(mockRepository.getMembres(
        page: 0,
        size: 1,
        recherche: null,
      )).thenAnswer((_) async => smallResult);

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

      // Assert
      expect(result.membres.length, equals(1));
      expect(result.pageSize, equals(1));
      expect(result.hasNext, isTrue);
    });

    test('should return empty result when no members exist', () async {
      // Arrange
      final emptyResult = MembreSearchResult(
        membres: [],
        totalElements: 0,
        totalPages: 0,
        currentPage: 0,
        pageSize: 50,
        numberOfElements: 0,
        hasNext: false,
        hasPrevious: false,
        isFirst: true,
        isLast: true,
        criteria: MembreSearchCriteria(),
        executionTimeMs: 20,
      );
      when(mockRepository.getMembres(
        page: anyNamed('page'),
        size: anyNamed('size'),
        recherche: anyNamed('recherche'),
      )).thenAnswer((_) async => emptyResult);

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

      // Assert
      expect(result.membres, isEmpty);
      expect(result.totalElements, equals(0));
    });

    test('should throw exception when repository fails', () async {
      // Arrange
      when(mockRepository.getMembres(
        page: anyNamed('page'),
        size: anyNamed('size'),
        recherche: anyNamed('recherche'),
      )).thenThrow(Exception('Erreur serveur'));

      // Act & Assert
      expect(() => useCase(page: 0, size: 50), throwsException);
    });
  });
}
