import { Result } from "@repo/rdx-utils"; import { z } from "zod/v4"; import { PERSON_PHOTO_LIMITS } from "../../common/person-photo"; import { PersonPhotoError } from "../domain/person-photo-error"; export type PersonPhoto = Readonly<{ data: Uint8Array; version: string }>; export interface IPersonPhotoRepository { exists(companyId: string, personId: string): Promise; get(personId: string): Promise; replace(companyId: string, personId: string, photo: PersonPhoto | null): Promise; } export interface IPersonPhotoProcessor { optimize(data: Uint8Array): Promise>; } export class PersonPhotoUseCases { constructor( private readonly repository: IPersonPhotoRepository, private readonly processor: IPersonPhotoProcessor ) {} async get(personId: string) { if (!z.uuid().safeParse(personId).success) return Result.fail(new PersonPhotoError("INVALID_REQUEST")); const photo = await this.repository.get(personId); return photo ? Result.ok(photo) : Result.fail(new PersonPhotoError("PHOTO_NOT_FOUND")); } async save(companyId: string, personId: string, data: Uint8Array) { if (!z.uuid().safeParse(companyId).success || !z.uuid().safeParse(personId).success) return Result.fail(new PersonPhotoError("INVALID_REQUEST")); if (data.length > PERSON_PHOTO_LIMITS.inputBytes) return Result.fail(new PersonPhotoError("PHOTO_TOO_LARGE")); if (!(await this.repository.exists(companyId, personId))) return Result.fail(new PersonPhotoError("PERSON_NOT_FOUND")); const processed = await this.processor.optimize(data); if (!processed.isSuccess) return Result.fail(processed.error); return (await this.repository.replace(companyId, personId, processed.data)) ? Result.ok(processed.data.version) : Result.fail(new PersonPhotoError("PERSON_NOT_FOUND")); } async remove(companyId: string, personId: string) { if (!z.uuid().safeParse(companyId).success || !z.uuid().safeParse(personId).success) return Result.fail(new PersonPhotoError("INVALID_REQUEST")); return (await this.repository.replace(companyId, personId, null)) ? Result.ok(null) : Result.fail(new PersonPhotoError("PERSON_NOT_FOUND")); } }