import { Injectable, NotFoundException } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { PaginationDto } from '../common/dto/pagination.dto'; import { CreatePetDto } from './dto/create-pet.dto'; import { UpdatePetDto } from './dto/update-pet.dto'; @Injectable() export class PetsService { constructor(private prisma: PrismaService) {} async create(userId: string, createPetDto: CreatePetDto) { const { name, type, breed, weight, age, activityLevel, medicalConditions } = createPetDto; return this.prisma.pet.create({ data: { name, type, breed: breed || '', activityLevel: activityLevel || 'متوسط', age: age || 1, weight: weight || 0, userId, medicalConditions: medicalConditions?.length ? { create: medicalConditions.map(condition => ({ condition })) } : undefined, }, include: { medicalConditions: true, reminders: true, healthLogs: true }, }); } async findAllByUser(userId: string, filters: PaginationDto) { const { search, page = 1, limit = 10, sortBy = 'createdAt', sortOrder = 'desc' } = filters; const whereClause: any = { userId }; if (search) { whereClause.OR = [ { name: { contains: search, mode: 'insensitive' } }, { breed: { contains: search, mode: 'insensitive' } }, ]; } const skip = (page - 1) * limit; const [data, total] = await Promise.all([ this.prisma.pet.findMany({ where: whereClause, skip, take: limit, orderBy: { [sortBy]: sortOrder }, }), this.prisma.pet.count({ where: whereClause }) ]); return { data, meta: { total, page, lastPage: Math.ceil(total / limit), limit, } }; } async findOne(id: string, userId: string) { const pet = await this.prisma.pet.findFirst({ where: { id, userId }, include: { medicalConditions: true, reminders: true, healthLogs: true }, }); if (!pet) { throw new NotFoundException('حیوان خانگی یافت نشد'); } return pet; } async update(id: string, userId: string, updatePetDto: UpdatePetDto) { await this.findOne(id, userId); // Ensure it exists and belongs to user if (updatePetDto.medicalConditions) { await this.prisma.petMedicalCondition.deleteMany({ where: { petId: id } }); } return this.prisma.pet.update({ where: { id }, data: { name: updatePetDto.name, type: updatePetDto.type, breed: updatePetDto.breed, weight: updatePetDto.weight, age: updatePetDto.age, activityLevel: updatePetDto.activityLevel, medicalConditions: updatePetDto.medicalConditions ? { create: updatePetDto.medicalConditions.map(condition => ({ condition })) } : undefined, }, include: { medicalConditions: true, reminders: true, healthLogs: true }, }); } async remove(id: string, userId: string) { await this.findOne(id, userId); return this.prisma.pet.delete({ where: { id }, }); } async addReminder(userId: string, petId: string, data: any) { await this.findOne(petId, userId); return this.prisma.reminder.create({ data: { petId, productId: data.productId || null, title: data.title, time: data.time, frequency: data.frequency, }, }); } async toggleReminder(userId: string, petId: string, reminderId: string, dateStr: string) { await this.findOne(petId, userId); const reminder = await this.prisma.reminder.findUnique({ where: { id: reminderId }, }); if (!reminder || reminder.petId !== petId) { throw new NotFoundException('یادآور یافت نشد'); } const dateParts = dateStr.split('-'); const completedDate = new Date(Date.UTC(Number(dateParts[0]), Number(dateParts[1]) - 1, Number(dateParts[2]))); const existingCompletion = await this.prisma.reminderCompletion.findUnique({ where: { reminderId_completedDate: { reminderId, completedDate, }, }, }); if (existingCompletion) { await this.prisma.reminderCompletion.delete({ where: { id: existingCompletion.id }, }); return { completed: false }; } else { await this.prisma.reminderCompletion.create({ data: { reminderId, completedDate, }, }); return { completed: true }; } } async addHealthLog(userId: string, petId: string, data: any) { await this.findOne(petId, userId); return this.prisma.healthLog.create({ data: { petId, appetite: data.appetite, energy: data.energy, digestion: data.digestion, note: data.note || null, loggedDate: new Date(), }, }); } }