import type { Logger } from '@core/shared/domain/Logger'; import { Result } from '@core/shared/domain/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository'; import { TeamRepository } from '../../domain/repositories/TeamRepository'; import type { TeamJoinRequest } from '../../domain/types/TeamMembership'; export interface 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: TeamRepository, private readonly membershipRepository: TeamMembershipRepository, private readonly logger: Logger, ) {} async execute( input: RejectTeamJoinRequestInput, ): Promise< Result< RejectTeamJoinRequestResult, ApplicationErrorCode > > { 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: TeamJoinRequest) => 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 = (() => { 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', { 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.logger.info('Team join request rejected successfully', { teamId, managerId, requestId, reason, }); return Result.ok(result); } 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', }, }); } } }