import { describe, it, expect, vi, type Mock, beforeEach } from 'vitest';
import {
  RejectLeagueJoinRequestUseCase,
  type RejectLeagueJoinRequestResult,
} from './RejectLeagueJoinRequestUseCase';
import type { ILeagueMembershipRepository } from '../../domain/repositories/ILeagueMembershipRepository';
import type { UseCaseOutputPort } from '@core/shared/application';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';

describe('RejectLeagueJoinRequestUseCase', () => {
  let leagueMembershipRepository: {
    getJoinRequests: Mock;
    removeJoinRequest: Mock;
  };

  beforeEach(() => {
    leagueMembershipRepository = {
      getJoinRequests: vi.fn(),
      removeJoinRequest: vi.fn(),
    };
  });

  it('reject removes request only', async () => {
    const output: UseCaseOutputPort<RejectLeagueJoinRequestResult> & { present: Mock } = {
      present: vi.fn(),
    } as any;

    const useCase = new RejectLeagueJoinRequestUseCase(
      leagueMembershipRepository as unknown as ILeagueMembershipRepository,
    );

    leagueMembershipRepository.getJoinRequests.mockResolvedValue([
      { id: 'jr-1', leagueId: 'league-1', driverId: 'driver-1' },
    ]);

    const result = await useCase.execute(
      { leagueId: 'league-1', joinRequestId: 'jr-1' },
      output,
    );

    expect(result.isOk()).toBe(true);
    expect(leagueMembershipRepository.removeJoinRequest).toHaveBeenCalledWith('jr-1');
    expect(output.present).toHaveBeenCalledWith({ success: true, message: 'Join request rejected.' });
  });

  it('reject returns error when request missing', async () => {
    const output: UseCaseOutputPort<RejectLeagueJoinRequestResult> & { present: Mock } = {
      present: vi.fn(),
    } as any;

    const useCase = new RejectLeagueJoinRequestUseCase(
      leagueMembershipRepository as unknown as ILeagueMembershipRepository,
    );

    leagueMembershipRepository.getJoinRequests.mockResolvedValue([]);

    const result = await useCase.execute(
      { leagueId: 'league-1', joinRequestId: 'jr-404' },
      output,
    );

    expect(result.isErr()).toBe(true);
    const err = result.unwrapErr() as ApplicationErrorCode<'JOIN_REQUEST_NOT_FOUND'>;
    expect(err.code).toBe('JOIN_REQUEST_NOT_FOUND');
    expect(output.present).not.toHaveBeenCalled();
    expect(leagueMembershipRepository.removeJoinRequest).not.toHaveBeenCalled();
  });
});
