/** * Use Case: RecordEngagementUseCase * * Records an engagement event when a visitor interacts with an entity. */ import type { AsyncUseCase } from '@gridpilot/shared/application'; import type { ILogger } from '@gridpilot/shared/logging/ILogger'; import { EngagementEvent, type EngagementAction, type EngagementEntityType } from '../../domain/entities/EngagementEvent'; import type { IEngagementRepository } from '../../domain/repositories/IEngagementRepository'; export interface RecordEngagementInput { action: EngagementAction; entityType: EngagementEntityType; entityId: string; actorId?: string; actorType: 'anonymous' | 'driver' | 'sponsor'; sessionId: string; metadata?: Record; } export interface RecordEngagementOutput { eventId: string; engagementWeight: number; } export class RecordEngagementUseCase implements AsyncUseCase { constructor( private readonly engagementRepository: IEngagementRepository, private readonly logger: ILogger, ) {} async execute(input: RecordEngagementInput): Promise { this.logger.debug('Executing RecordEngagementUseCase', { input }); try { const eventId = `eng-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const baseProps: Omit[0], 'timestamp'> = { id: eventId, action: input.action, entityType: input.entityType, entityId: input.entityId, actorType: input.actorType, sessionId: input.sessionId, }; const event = EngagementEvent.create({ ...baseProps, ...(input.actorId !== undefined ? { actorId: input.actorId } : {}), ...(input.metadata !== undefined ? { metadata: input.metadata } : {}), }); await this.engagementRepository.save(event); this.logger.info('Engagement recorded successfully', { eventId, input }); return { eventId, engagementWeight: event.getEngagementWeight(), }; } catch (error) { this.logger.error('Error recording engagement', error, { input }); throw error; } } }