import { describe, expect, it, vi, type Mock } from 'vitest';
import { MembershipFeeType } from '../../domain/entities/MembershipFee';
import type { MembershipFeeRepository } from '../../domain/repositories/MembershipFeeRepository';
import { UpsertMembershipFeeUseCase, type UpsertMembershipFeeInput } from './UpsertMembershipFeeUseCase';

describe('UpsertMembershipFeeUseCase', () => {
  let membershipFeeRepository: {
    findByLeagueId: Mock;
    update: Mock;
    create: Mock;
  };
  let useCase: UpsertMembershipFeeUseCase;

  beforeEach(() => {
    membershipFeeRepository = {
      findByLeagueId: vi.fn(),
      update: vi.fn(),
      create: vi.fn(),
    };

    useCase = new UpsertMembershipFeeUseCase(
      membershipFeeRepository as unknown as MembershipFeeRepository,
    );
  });

  it('updates existing membership fee and returns result', async () => {
    const input: UpsertMembershipFeeInput = {
      leagueId: 'league-1',
      seasonId: 'season-1',
      type: MembershipFeeType.MONTHLY,
      amount: 50,
    };

    const existingFee = {
      id: 'fee-1',
      leagueId: 'league-1',
      type: MembershipFeeType.YEARLY,
      amount: 100,
      enabled: true,
      createdAt: new Date(),
      updatedAt: new Date(),
    };

    const updatedFee = {
      ...existingFee,
      type: MembershipFeeType.MONTHLY,
      amount: 50,
      seasonId: 'season-1',
      enabled: true,
      updatedAt: new Date(),
    };

    membershipFeeRepository.findByLeagueId.mockResolvedValue(existingFee);
    membershipFeeRepository.update.mockResolvedValue(updatedFee);

    const result = await useCase.execute(input);

    expect(result.isOk()).toBe(true);
    expect(membershipFeeRepository.findByLeagueId).toHaveBeenCalledWith('league-1');
    expect(membershipFeeRepository.update).toHaveBeenCalled();
    
    if (result.isOk()) {
      expect(result.value.fee).toEqual(updatedFee);
    }
  });

  it('creates new membership fee and returns result', async () => {
    const input: UpsertMembershipFeeInput = {
      leagueId: 'league-1',
      type: MembershipFeeType.MONTHLY,
      amount: 50,
    };

    membershipFeeRepository.findByLeagueId.mockResolvedValue(null);

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

    membershipFeeRepository.create.mockResolvedValue(createdFee);

    const result = await useCase.execute(input);

    expect(result.isOk()).toBe(true);
    expect(membershipFeeRepository.findByLeagueId).toHaveBeenCalledWith('league-1');
    expect(membershipFeeRepository.create).toHaveBeenCalled();
    
    if (result.isOk()) {
      expect(result.value.fee).toEqual(createdFee);
    }
  });
});