import type { Logger, UseCaseOutputPort } from '@core/shared/application'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository'; import type { ILeagueMembershipRepository } from '../../domain/repositories/ILeagueMembershipRepository'; export type RejectLeagueJoinRequestInput = { leagueId: string; adminId: string; requestId: string; reason?: string; }; export type RejectLeagueJoinRequestResult = { leagueId: string; requestId: string; status: 'rejected'; }; export type RejectLeagueJoinRequestErrorCode = | 'LEAGUE_NOT_FOUND' | 'REQUEST_NOT_FOUND' | 'UNAUTHORIZED' | 'INVALID_REQUEST_STATE' | 'REPOSITORY_ERROR'; export class RejectLeagueJoinRequestUseCase { constructor( private readonly leagueRepository: ILeagueRepository, private readonly leagueMembershipRepository: ILeagueMembershipRepository, private readonly logger: Logger, private readonly output: UseCaseOutputPort, ) {} async execute( input: RejectLeagueJoinRequestInput, ): Promise>> { const { leagueId, adminId, requestId, reason } = input; try { const league = await this.leagueRepository.findById(leagueId); if (!league) { this.logger.warn('League not found when rejecting join request', { leagueId, adminId, requestId }); return Result.err({ code: 'LEAGUE_NOT_FOUND', details: { message: 'League not found' }, }); } const adminMembership = await this.leagueMembershipRepository.getMembership(leagueId, adminId); if ( !adminMembership || adminMembership.status.toString() !== 'active' || (adminMembership.role.toString() !== 'owner' && adminMembership.role.toString() !== 'admin') ) { this.logger.warn('User is not authorized to reject league join requests', { leagueId, adminId, requestId, }); return Result.err({ code: 'UNAUTHORIZED', details: { message: 'User is not authorized to reject league join requests' }, }); } const joinRequests = await this.leagueMembershipRepository.getJoinRequests(leagueId); const joinRequest = joinRequests.find(r => r.id === requestId); if (!joinRequest) { this.logger.warn('Join request not found when rejecting', { leagueId, adminId, requestId }); return Result.err({ code: 'REQUEST_NOT_FOUND', details: { message: 'Join request not found' }, }); } const currentStatus = (() => { const rawStatus = (joinRequest as unknown as { status?: unknown }).status; return rawStatus === 'pending' || rawStatus === 'approved' || rawStatus === 'rejected' ? rawStatus : 'pending'; })(); if (currentStatus !== 'pending') { this.logger.warn('Join request is in invalid state for rejection', { leagueId, adminId, requestId, currentStatus, }); return Result.err({ code: 'INVALID_REQUEST_STATE', details: { message: 'Join request is not in a pending state' }, }); } await this.leagueMembershipRepository.removeJoinRequest(requestId); const result: RejectLeagueJoinRequestResult = { leagueId, requestId, status: 'rejected', }; this.output.present(result); this.logger.info('League join request rejected successfully', { leagueId, adminId, requestId, reason, }); return Result.ok(undefined); } catch (error) { const err = error instanceof Error ? error : new Error('Unknown error'); this.logger.error('Failed to reject league join request', err, { leagueId, adminId, requestId, }); return Result.err({ code: 'REPOSITORY_ERROR', details: { message: err.message ?? 'Failed to reject league join request', }, }); } } }