/// Tests unitaires pour GetEvents use case
library get_events_test;

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:unionflow_mobile_apps/features/events/domain/repositories/evenement_repository.dart';
import 'package:unionflow_mobile_apps/features/events/domain/usecases/get_events.dart';
import 'package:unionflow_mobile_apps/features/events/data/models/evenement_model.dart';
import 'package:unionflow_mobile_apps/features/events/data/repositories/evenement_repository_impl.dart';

@GenerateMocks([IEvenementRepository])
import 'get_events_test.mocks.dart';

void main() {
  late GetEvents useCase;
  late MockIEvenementRepository mockRepository;

  setUp(() {
    mockRepository = MockIEvenementRepository();
    useCase = GetEvents(mockRepository);
  });

  group('GetEvents Use Case', () {
    final tEventsList = [
      EvenementModel(
        id: 1,
        titre: 'Assemblée Générale 2024',
        description: 'Assemblée générale annuelle',
        dateDebut: DateTime(2024, 12, 15, 14, 0),
        dateFin: DateTime(2024, 12, 15, 18, 0),
        lieu: 'Salle des Congrès',
        type: TypeEvenement.assembleeGenerale,
        statut: StatutEvenement.confirme,
        priorite: PrioriteEvenement.haute,
        participantsActuels: 45,
        maxParticipants: 100,
      ),
      EvenementModel(
        id: 2,
        titre: 'Formation Leadership',
        description: 'Formation sur le leadership',
        dateDebut: DateTime(2024, 12, 20, 9, 0),
        dateFin: DateTime(2024, 12, 20, 17, 0),
        lieu: 'Centre de Formation',
        type: TypeEvenement.formation,
        statut: StatutEvenement.planifie,
        participantsActuels: 15,
        maxParticipants: 30,
      ),
    ];

    final tSearchResult = EvenementSearchResult(
      evenements: tEventsList,
      total: 2,
      page: 0,
      size: 20,
      totalPages: 1,
    );

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

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

      // Assert
      expect(result, equals(tSearchResult));
      expect(result.evenements.length, equals(2));
      expect(result.total, equals(2));
      verify(mockRepository.getEvenements(page: 0, size: 20));
      verifyNoMoreInteractions(mockRepository);
    });

    test('should filter events by search query', () async {
      // Arrange
      final filteredResult = EvenementSearchResult(
        evenements: [tEventsList[0]],
        total: 1,
        page: 0,
        size: 20,
        totalPages: 1,
      );
      when(mockRepository.getEvenements(
        page: 0,
        size: 20,
        recherche: 'Assemblée',
      )).thenAnswer((_) async => filteredResult);

      // Act
      final result = await useCase(page: 0, size: 20, recherche: 'Assemblée');

      // Assert
      expect(result.evenements.length, equals(1));
      expect(result.evenements.first.titre, contains('Assemblée'));
    });

    test('should return empty result when no events exist', () async {
      // Arrange
      final emptyResult = EvenementSearchResult(
        evenements: [],
        total: 0,
        page: 0,
        size: 20,
        totalPages: 0,
      );
      when(mockRepository.getEvenements(
        page: anyNamed('page'),
        size: anyNamed('size'),
        recherche: anyNamed('recherche'),
      )).thenAnswer((_) async => emptyResult);

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

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

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

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