import { describe, expect, it, vi, type Mock } from 'vitest';
import type { MemberPaymentRepository, MembershipFeeRepository } from '../../domain/repositories/MembershipFeeRepository';
import { GetMembershipFeesUseCase, type GetMembershipFeesInput } from './GetMembershipFeesUseCase';

describe('GetMembershipFeesUseCase', () => {
  let membershipFeeRepository: {
    findByLeagueId: Mock;
  };
  let memberPaymentRepository: {
    findByLeagueIdAndDriverId: Mock;
  };
  let useCase: GetMembershipFeesUseCase;

  beforeEach(() => {
    membershipFeeRepository = {
      findByLeagueId: vi.fn(),
    };
    memberPaymentRepository = {
      findByLeagueIdAndDriverId: vi.fn(),
    };

    useCase = new GetMembershipFeesUseCase(
      membershipFeeRepository as unknown as MembershipFeeRepository,
      memberPaymentRepository as unknown as MemberPaymentRepository,
    );
  });

  it('retrieves membership fees and returns result', async () => {
    const input: GetMembershipFeesInput = {
      leagueId: 'league-1',
      driverId: 'driver-1',
    };

    const fee = {
      id: 'fee-1',
      leagueId: 'league-1',
      type: 'monthly',
      amount: 50,
      enabled: true,
      createdAt: new Date(),
      updatedAt: new Date(),
    };

    const payments = [
      {
        id: 'payment-1',
        feeId: 'fee-1',
        driverId: 'driver-1',
        amount: 50,
        platformFee: 5,
        netAmount: 45,
        status: 'paid',
        dueDate: new Date(),
        paidAt: new Date(),
      },
    ];

    membershipFeeRepository.findByLeagueId.mockResolvedValue(fee);
    memberPaymentRepository.findByLeagueIdAndDriverId.mockResolvedValue(payments);

    const result = await useCase.execute(input);

    expect(result.isOk()).toBe(true);
    expect(membershipFeeRepository.findByLeagueId).toHaveBeenCalledWith('league-1');
    expect(memberPaymentRepository.findByLeagueIdAndDriverId).toHaveBeenCalledWith('league-1', 'driver-1', membershipFeeRepository);
    
    if (result.isOk()) {
      expect(result.value).toEqual({ fee, payments });
    }
  });

  it('returns error when leagueId is missing', async () => {
    const input: GetMembershipFeesInput = {
      leagueId: '',
    };

    const result = await useCase.execute(input);

    expect(result.isErr()).toBe(true);
    if (result.isErr()) {
      expect(result.error.code).toBe('INVALID_INPUT');
    }
  });
});