/// Tests unitaires pour GetApprovalById use case
library get_approval_by_id_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/finance_workflow/domain/usecases/get_approval_by_id.dart';
import 'package:unionflow_mobile_apps/features/finance_workflow/domain/repositories/finance_workflow_repository.dart';
import 'package:unionflow_mobile_apps/features/finance_workflow/domain/entities/transaction_approval.dart';
import 'package:unionflow_mobile_apps/core/error/failures.dart';

@GenerateMocks([FinanceWorkflowRepository])
import 'get_approval_by_id_test.mocks.dart';

void main() {
  late GetApprovalById useCase;
  late MockFinanceWorkflowRepository mockRepository;

  setUp(() {
    mockRepository = MockFinanceWorkflowRepository();
    useCase = GetApprovalById(mockRepository);
  });

  group('GetApprovalById Use Case', () {
    const tApprovalId = 'approval-123';
    final tApproval = TransactionApproval(
      id: tApprovalId,
      transactionId: 'tx-456',
      transactionType: TransactionType.solidarity,
      amount: 350000.0,
      currency: 'XOF',
      requesterId: 'user-1',
      requesterName: 'Amadou Diallo',
      organizationId: 'org-123',
      requiredLevel: ApprovalLevel.level2,
      status: ApprovalStatus.pending,
      approvers: [],
      createdAt: DateTime(2024, 12, 15),
    );

    test('should return approval details by ID', () async {
      // Arrange
      when(mockRepository.getApprovalById(tApprovalId))
          .thenAnswer((_) async => Right(tApproval));

      // Act
      final result = await useCase(tApprovalId);

      // Assert
      expect(result, Right(tApproval));
      result.fold(
        (failure) => fail('Should not return failure'),
        (approval) {
          expect(approval.id, equals(tApprovalId));
          expect(approval.amount, equals(350000.0));
          expect(approval.transactionType, equals(TransactionType.solidarity));
        },
      );
      verify(mockRepository.getApprovalById(tApprovalId));
      verifyNoMoreInteractions(mockRepository);
    });

    test('should return approval with level 2 requirement', () async {
      // Arrange
      when(mockRepository.getApprovalById(tApprovalId))
          .thenAnswer((_) async => Right(tApproval));

      // Act
      final result = await useCase(tApprovalId);

      // Assert
      result.fold(
        (failure) => fail('Should not return failure'),
        (approval) {
          expect(approval.requiredLevel, equals(ApprovalLevel.level2));
        },
      );
    });

    test('should return ValidationFailure when approvalId is empty', () async {
      // Act
      final result = await useCase('');

      // Assert
      result.fold(
        (failure) {
          expect(failure, isA<ValidationFailure>());
        },
        (approval) => fail('Should not return approval'),
      );
      verifyZeroInteractions(mockRepository);
    });

    test('should return ServerFailure when approval not found', () async {
      // Arrange
      final tFailure = ServerFailure('Approbation non trouvée');
      when(mockRepository.getApprovalById(any))
          .thenAnswer((_) async => Left(tFailure));

      // Act
      final result = await useCase('nonexistent');

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