import { AdminVoteSessionRepository } from '../../domain/repositories/AdminVoteSessionRepository'; import { CastAdminVoteInput, CastAdminVoteOutput } from '../dtos/AdminVoteSessionDto'; /** * Use Case: CastAdminVoteUseCase * * Casts a vote in an active admin vote session. * Follows CQRS Light: command side operation. * * Per plans section 7.1.1 */ export class CastAdminVoteUseCase { constructor( private readonly adminVoteSessionRepository: AdminVoteSessionRepository, ) {} async execute(input: CastAdminVoteInput): Promise { try { // Validate input const errors = this.validateInput(input); if (errors.length > 0) { return { success: false, voteSessionId: input.voteSessionId, voterId: input.voterId, errors, }; } // Load the vote session const session = await this.adminVoteSessionRepository.findById(input.voteSessionId); if (!session) { return { success: false, voteSessionId: input.voteSessionId, voterId: input.voterId, errors: ['Vote session not found'], }; } // Check if session is open const voteTime = input.votedAt ? new Date(input.votedAt) : new Date(); if (!session.isVotingWindowOpen(voteTime)) { return { success: false, voteSessionId: input.voteSessionId, voterId: input.voterId, errors: ['Vote session is not open for voting'], }; } // Cast the vote session.castVote(input.voterId, input.positive, voteTime); // Save updated session await this.adminVoteSessionRepository.save(session); return { success: true, voteSessionId: input.voteSessionId, voterId: input.voterId, }; } catch (error) { const errorMsg = error instanceof Error ? error.message : 'Unknown error'; return { success: false, voteSessionId: input.voteSessionId, voterId: input.voterId, errors: [`Failed to cast vote: ${errorMsg}`], }; } } private validateInput(input: CastAdminVoteInput): string[] { const errors: string[] = []; if (!input.voteSessionId || input.voteSessionId.trim().length === 0) { errors.push('voteSessionId is required'); } if (!input.voterId || input.voterId.trim().length === 0) { errors.push('voterId is required'); } if (typeof input.positive !== 'boolean') { errors.push('positive must be a boolean value'); } if (input.votedAt) { const votedAt = new Date(input.votedAt); if (isNaN(votedAt.getTime())) { errors.push('votedAt must be a valid date if provided'); } } return errors; } }