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 { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository'; import type { ITeamRepository } from '../../domain/repositories/ITeamRepository'; export type RejectTeamJoinRequestInput = { teamId: string; managerId: string; requestId: string; reason?: string; }; export type RejectTeamJoinRequestResult = { teamId: string; requestId: string; status: 'rejected'; }; export type RejectTeamJoinRequestErrorCode = | 'TEAM_NOT_FOUND' | 'REQUEST_NOT_FOUND' | 'UNAUTHORIZED' | 'INVALID_REQUEST_STATE' | 'REPOSITORY_ERROR'; export class RejectTeamJoinRequestUseCase { constructor( private readonly teamRepository: ITeamRepository, private readonly membershipRepository: ITeamMembershipRepository, private readonly logger: Logger, private readonly output: UseCaseOutputPort, ) {} async execute( input: RejectTeamJoinRequestInput, ): Promise>> { const { teamId, managerId, requestId, reason } = input; try { const team = await this.teamRepository.findById(teamId); if (!team) { this.logger.warn('Team not found when rejecting join request', { teamId, managerId, requestId }); return Result.err({ code: 'TEAM_NOT_FOUND', details: { message: 'Team not found' }, }); } const managerMembership = await this.membershipRepository.getMembership(teamId, managerId); if (!managerMembership || managerMembership.status !== 'active' || !['owner', 'manager'].includes(managerMembership.role)) { this.logger.warn('User is not authorized to reject team join requests', { teamId, managerId, requestId, }); return Result.err({ code: 'UNAUTHORIZED', details: { message: 'User is not authorized to reject team join requests' }, }); } const joinRequests = await this.membershipRepository.getJoinRequests(teamId); const joinRequest = joinRequests.find(r => r.id === requestId); if (!joinRequest) { this.logger.warn('Join request not found when rejecting', { teamId, managerId, requestId }); return Result.err({ code: 'REQUEST_NOT_FOUND', details: { message: 'Join request not found' }, }); } const currentStatus = (joinRequest as any).status ?? 'pending'; if (currentStatus !== 'pending') { this.logger.warn('Join request is in invalid state for rejection', { teamId, managerId, requestId, currentStatus, }); return Result.err({ code: 'INVALID_REQUEST_STATE', details: { message: 'Join request is not in a pending state' }, }); } await this.membershipRepository.removeJoinRequest(requestId); const result: RejectTeamJoinRequestResult = { teamId, requestId, status: 'rejected', }; this.output.present(result); this.logger.info('Team join request rejected successfully', { teamId, managerId, requestId, reason, }); return Result.ok(undefined); } catch (error) { const err = error instanceof Error ? error : new Error('Unknown error'); this.logger.error('Failed to reject team join request', err, { teamId, managerId, requestId, }); return Result.err({ code: 'REPOSITORY_ERROR', details: { message: err.message ?? 'Failed to reject team join request', }, }); } } }