/// Tests unitaires pour GetDashboardData use case
library get_dashboard_data_test;

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:dartz/dartz.dart';
import 'package:unionflow_mobile_apps/features/dashboard/domain/usecases/get_dashboard_data.dart';
import 'package:unionflow_mobile_apps/features/dashboard/domain/repositories/dashboard_repository.dart';
import 'package:unionflow_mobile_apps/features/dashboard/domain/entities/dashboard_entity.dart';
import 'package:unionflow_mobile_apps/core/error/failures.dart';

@GenerateMocks([DashboardRepository])
import 'get_dashboard_data_test.mocks.dart';

void main() {
  late GetDashboardData useCase;
  late MockDashboardRepository mockRepository;

  setUp(() {
    mockRepository = MockDashboardRepository();
    useCase = GetDashboardData(mockRepository);
  });

  group('GetDashboardData Use Case', () {
    const tOrgId = 'org-123';
    const tUserId = 'user-456';
    final tParams = GetDashboardDataParams(
      organizationId: tOrgId,
      userId: tUserId,
    );

    final tDashboardStats = DashboardStatsEntity(
      totalMembers: 250,
      activeMembers: 180,
      totalEvents: 45,
      upcomingEvents: 12,
      totalContributions: 1200,
      totalContributionAmount: 5750000.0,
      contributionsAmountOnly: 3250000.0,
      pendingRequests: 8,
      completedProjects: 23,
      monthlyGrowth: 0.15,
      engagementRate: 0.72,
      lastUpdated: DateTime(2024, 12, 15, 10, 30),
      totalOrganizations: 5,
      organizationTypeDistribution: {
        'association': 3,
        'cooperative': 2,
      },
    );

    test('should return dashboard stats successfully', () async {
      // Arrange
      when(mockRepository.getDashboardStats(tOrgId, tUserId))
          .thenAnswer((_) async => Right(tDashboardStats));

      // Act
      final result = await GetDashboardStats(mockRepository)(
        GetDashboardStatsParams(organizationId: tOrgId, userId: tUserId),
      );

      // Assert
      expect(result, Right(tDashboardStats));
      result.fold(
        (failure) => fail('Should not return failure'),
        (stats) {
          expect(stats.totalMembers, equals(250));
          expect(stats.activeMembers, equals(180));
          expect(stats.totalContributionAmount, equals(5750000.0));
          expect(stats.monthlyGrowth, equals(0.15));
          expect(stats.hasGrowth, isTrue);
        },
      );
      verify(mockRepository.getDashboardStats(tOrgId, tUserId));
      verifyNoMoreInteractions(mockRepository);
    });

    test('should return stats with high engagement rate', () async {
      // Arrange
      when(mockRepository.getDashboardStats(tOrgId, tUserId))
          .thenAnswer((_) async => Right(tDashboardStats));

      // Act
      final result = await GetDashboardStats(mockRepository)(
        GetDashboardStatsParams(organizationId: tOrgId, userId: tUserId),
      );

      // Assert
      result.fold(
        (failure) => fail('Should not return failure'),
        (stats) {
          expect(stats.engagementRate, equals(0.72));
          expect(stats.isHighEngagement, isTrue);
          expect(stats.memberActivityRate, closeTo(0.72, 0.01));
        },
      );
    });

    test('should format contribution amount correctly', () async {
      // Arrange
      when(mockRepository.getDashboardStats(tOrgId, tUserId))
          .thenAnswer((_) async => Right(tDashboardStats));

      // Act
      final result = await GetDashboardStats(mockRepository)(
        GetDashboardStatsParams(organizationId: tOrgId, userId: tUserId),
      );

      // Assert
      result.fold(
        (failure) => fail('Should not return failure'),
        (stats) {
          expect(stats.formattedContributionAmount, equals('5.8M'));
        },
      );
    });

    test('should return ServerFailure when repository fails', () async {
      // Arrange
      final tFailure = ServerFailure('Erreur serveur');
      when(mockRepository.getDashboardStats(any, any))
          .thenAnswer((_) async => Left(tFailure));

      // Act
      final result = await GetDashboardStats(mockRepository)(
        GetDashboardStatsParams(organizationId: tOrgId, userId: tUserId),
      );

      // Assert
      expect(result, Left(tFailure));
      result.fold(
        (failure) => expect(failure, isA<ServerFailure>()),
        (stats) => fail('Should not return stats'),
      );
    });
  });
}
