import { IsString, IsEnum, IsInt, IsOptional, IsUUID, IsObject, Min, IsDate } from 'class-validator'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { BatchStatus } from '@prisma/client'; import { Type } from 'class-transformer'; export class CreateBatchDto { @ApiProperty({ description: 'ID of the user creating the batch', example: '550e8400-e29b-41d4-a716-446655440000' }) @IsUUID() userId: string; @ApiPropertyOptional({ description: 'Total number of images in this batch', example: 10, minimum: 0 }) @IsOptional() @IsInt() @Min(0) totalImages?: number; @ApiPropertyOptional({ description: 'Additional metadata for the batch processing', example: { aiModel: 'gpt-4-vision', processingOptions: { includeColors: true, includeTags: true } } }) @IsOptional() @IsObject() metadata?: Record; } export class UpdateBatchDto { @ApiPropertyOptional({ description: 'Batch processing status', enum: BatchStatus }) @IsOptional() @IsEnum(BatchStatus) status?: BatchStatus; @ApiPropertyOptional({ description: 'Total number of images in this batch', minimum: 0 }) @IsOptional() @IsInt() @Min(0) totalImages?: number; @ApiPropertyOptional({ description: 'Number of processed images', minimum: 0 }) @IsOptional() @IsInt() @Min(0) processedImages?: number; @ApiPropertyOptional({ description: 'Number of failed images', minimum: 0 }) @IsOptional() @IsInt() @Min(0) failedImages?: number; @ApiPropertyOptional({ description: 'Additional metadata for the batch processing' }) @IsOptional() @IsObject() metadata?: Record; } export class BatchResponseDto { @ApiProperty({ description: 'Unique batch identifier', example: '550e8400-e29b-41d4-a716-446655440000' }) @IsUUID() id: string; @ApiProperty({ description: 'ID of the user who owns this batch', example: '550e8400-e29b-41d4-a716-446655440000' }) @IsUUID() userId: string; @ApiProperty({ description: 'Current batch processing status', enum: BatchStatus }) @IsEnum(BatchStatus) status: BatchStatus; @ApiProperty({ description: 'Total number of images in this batch', example: 10 }) @IsInt() @Min(0) totalImages: number; @ApiProperty({ description: 'Number of processed images', example: 8 }) @IsInt() @Min(0) processedImages: number; @ApiProperty({ description: 'Number of failed images', example: 1 }) @IsInt() @Min(0) failedImages: number; @ApiPropertyOptional({ description: 'Additional metadata for the batch processing' }) @IsOptional() @IsObject() metadata?: Record; @ApiProperty({ description: 'Batch creation timestamp' }) @IsDate() createdAt: Date; @ApiProperty({ description: 'Batch last update timestamp' }) @IsDate() updatedAt: Date; @ApiPropertyOptional({ description: 'Batch completion timestamp' }) @IsOptional() @IsDate() completedAt?: Date; } export class BatchStatsDto { @ApiProperty({ description: 'Processing progress percentage', example: 80 }) @IsInt() @Min(0) progressPercentage: number; @ApiProperty({ description: 'Number of pending images', example: 1 }) @IsInt() @Min(0) pendingImages: number; @ApiProperty({ description: 'Average processing time per image in seconds', example: 5.2 }) @Type(() => Number) averageProcessingTime: number; @ApiProperty({ description: 'Estimated time remaining in seconds', example: 30 }) @Type(() => Number) estimatedTimeRemaining: number; } export class BatchSummaryDto { @ApiProperty({ description: 'Batch details' }) batch: BatchResponseDto; @ApiProperty({ description: 'Processing statistics' }) stats: BatchStatsDto; @ApiProperty({ description: 'Recent images from this batch (limited to 5)' }) recentImages: Array<{ id: string; originalName: string; proposedName?: string; status: string; }>; } // Helper function to calculate progress percentage export function calculateProgressPercentage(processedImages: number, totalImages: number): number { if (totalImages === 0) return 0; return Math.round((processedImages / totalImages) * 100); } // Helper function to determine if batch is complete export function isBatchComplete(batch: { status: BatchStatus; processedImages: number; failedImages: number; totalImages: number }): boolean { return batch.status === BatchStatus.DONE || batch.status === BatchStatus.ERROR || (batch.processedImages + batch.failedImages) >= batch.totalImages; }