import { NextRequest, NextResponse } from "next/server"; import { auth } from "@clerk/nextjs/server"; import { getDatabase } from "@/lib/database"; import log from "@/lib/logger"; import { legacyRecommendationSchema, recommendationUpdateRequestSchema, } from "@/lib/validation/schemas"; import { validateRequestBody, validationErrorResponse, } from "@/lib/validation/helpers"; import { successResponse, unauthorizedResponse, forbiddenResponse, badRequestResponse, internalErrorResponse, } from "@/lib/api/responses"; export async function GET(request: NextRequest) { try { const { userId: currentUserId } = await auth(); if (!currentUserId) { return unauthorizedResponse(); } const { searchParams } = new URL(request.url); const targetUserId = searchParams.get("userId"); const db = await getDatabase(); // If no userId provided, check if staff and return all recommendations if (!targetUserId) { const currentUser = await db.getUserById(currentUserId); const isStaff = currentUser?.role === "admin" || currentUser?.role === "superAdmin" || currentUser?.role === "trainer"; if (!isStaff) { return badRequestResponse("User ID is required"); } const recommendations = await db.getAllRecommendations(); return successResponse({ recommendations }); } // Check permissions: Users can view their own, Admins/Trainers can view anyone's const currentUser = await db.getUserById(currentUserId); const isStaff = currentUser?.role === "admin" || currentUser?.role === "superAdmin" || currentUser?.role === "trainer"; if (currentUserId !== targetUserId) { if (!isStaff) { return forbiddenResponse(); } } let recommendations = await db.getRecommendationsByUserId(targetUserId); // Non-staff users should only see approved recommendations if (!isStaff) { recommendations = recommendations.filter( (rec: any) => rec.status === "approved", ); } return successResponse(recommendations); } catch (error) { console.error("Error fetching recommendations:", error); return internalErrorResponse(); } } export async function POST(request: NextRequest) { try { const { userId: currentUserId } = await auth(); if (!currentUserId) { return unauthorizedResponse(); } const db = await getDatabase(); const currentUser = await db.getUserById(currentUserId); const isStaff = currentUser?.role === "admin" || currentUser?.role === "superAdmin" || currentUser?.role === "trainer"; if (!isStaff) { return forbiddenResponse(); } // Validate request body const validation = await validateRequestBody( request, legacyRecommendationSchema, ); if (!validation.success) { log.warn("Recommendation creation validation failed", { errors: validation.errors, }); return validationErrorResponse(validation.errors); } const { userId, fitnessProfileId, recommendationText, activityPlan, dietPlan, status, type, content, } = validation.data; // Handle AI Plan (Legacy/Specific) if (recommendationText && activityPlan && dietPlan && fitnessProfileId) { const recommendation = await db.createRecommendation({ id: crypto.randomUUID(), userId, fitnessProfileId, type: "ai_plan", recommendationText: recommendationText, activityPlan, dietPlan, status: status || "pending", } as any); return successResponse(recommendation); } // Handle User Goal (Generic) if (type && content) { const recommendation = await db.createRecommendation({ id: crypto.randomUUID(), userId, type, recommendationText: content, status: status || "pending", } as any); return successResponse(recommendation); } return badRequestResponse("Missing required fields"); } catch (error) { log.error("Failed to create recommendation", error); return internalErrorResponse(); } } export async function PUT(request: NextRequest) { try { const { userId: currentUserId } = await auth(); if (!currentUserId) { return unauthorizedResponse(); } // Validate request body const validation = await validateRequestBody( request, recommendationUpdateRequestSchema, ); if (!validation.success) { log.warn("Recommendation update validation failed", { errors: validation.errors, }); return validationErrorResponse(validation.errors); } const { id, status, recommendationText, activityPlan, dietPlan, content } = validation.data; const db = await getDatabase(); const updated = await db.updateRecommendation(id, { ...(status && { status }), ...(recommendationText && { recommendationText }), ...(content && { recommendationText: content }), ...(activityPlan && { activityPlan }), ...(dietPlan && { dietPlan }), } as any); return successResponse(updated); } catch (error) { log.error("Failed to update recommendation", error); return internalErrorResponse(); } }