import { Injectable, NotFoundException, BadRequestException, Logger, Inject } from '@nestjs/common'; import { PRISMA_CLIENT, type PrismaClientInstance } from '@app/common/prisma/prisma.service'; import { isUuid } from '@app/common/utils/string.utils'; import { Queue } from 'bullmq'; import { StorageService } from '@app/common/storage/storage.service'; import { InjectQueue } from '@nestjs/bullmq'; import { CaseStatus } from '../generated/prisma/client.js'; @Injectable() export class CasesService { private readonly logger = new Logger(CasesService.name); constructor( @Inject(PRISMA_CLIENT) private prisma: PrismaClientInstance, private storage: StorageService, @InjectQueue('case-processing') private caseQueue: Queue, ) {} async processAndSave(buffer: Buffer, mimetype: string, filename: string) { this.logger.log(`Upload received: ${filename} (${mimetype}, ${(buffer.length / 1024).toFixed(1)} KB)`); const storageKey = await this.storage.upload(buffer, filename, mimetype); const fileType = mimetype === 'application/pdf' ? 'PDF' : 'HTML'; const caseLaw = await this.prisma.caseLaw.create({ data: { title: `Processing: ${filename}`, fileType, storageKey, status: CaseStatus.PENDING, }, }); const workerDownloadUrl = await this.storage.getPresignedUrl(storageKey); await this.caseQueue.add('parse-case', { caseId: caseLaw.id, downloadUrl: workerDownloadUrl, mimetype, }); return caseLaw; } async findOne(id?: string, caseNumber?: string) { if (!id && !caseNumber) throw new BadRequestException('Provide ID or Case Number'); const caseLaw = await this.prisma.caseLaw.findFirst({ where: { OR: [ id && isUuid(id) ? { id } : undefined, caseNumber ? { caseNumber } : undefined, ].filter(Boolean) as any, }, }); if (!caseLaw) throw new NotFoundException('Case not found'); return caseLaw; } async findAll(status?: CaseStatus, take = 20, skip = 0) { return this.prisma.caseLaw.findMany({ where: status ? { status } : undefined, orderBy: { createdAt: 'desc' }, take: Math.min(take, 100), skip, }); } }