import { getUserIdFromSession } from '../../utils/auth'; import { CROP_HARVEST_REWARD, isCropGrown } from '../../utils/village'; import { CropType } from '@prisma/client'; // --- Handler --- export default defineEventHandler(async (event) => { const userId = await getUserIdFromSession(event); const { fieldId } = await readBody(event); // 1. --- Validation --- if (typeof fieldId !== 'number') { throw createError({ statusCode: 400, statusMessage: 'Invalid request body. "fieldId" is required.' }); } // 2. --- Find the target field and validate its state --- const field = await prisma.villageObject.findFirst({ where: { id: fieldId, type: 'FIELD', village: { userId: userId }, // Ensures ownership }, }); if (!field) { throw createError({ statusCode: 404, statusMessage: 'Field not found or you do not own it.' }); } if (!field.cropType || !field.plantedAt) { throw createError({ statusCode: 400, statusMessage: 'Nothing is planted in this field.' }); } if (!isCropGrown(field.plantedAt, field.cropType)) { throw createError({ statusCode: 400, statusMessage: 'Crop is not yet fully grown.' }); } // 3. --- Grant rewards and clear field in a transaction --- const reward = CROP_HARVEST_REWARD[field.cropType]; const [, , updatedField] = await prisma.$transaction([ // Grant EXP and Coins prisma.user.update({ where: { id: userId }, data: { exp: { increment: reward.exp }, coins: { increment: reward.coins }, }, }), // Clear the crop from the field prisma.villageObject.update({ where: { id: fieldId }, data: { cropType: null, plantedAt: null, }, }), // Re-fetch the field to return its cleared state prisma.villageObject.findUniqueOrThrow({ where: { id: fieldId } }), ]); return { message: `${field.cropType} harvested successfully!`, reward: reward, updatedField: { id: updatedField.id, type: updatedField.type, x: updatedField.x, y: updatedField.y, cropType: updatedField.cropType, isGrown: false, } }; });