import { NextRequest, NextResponse } from "next/server"; import { prisma } from "@/lib/prisma"; import { requireAuth } from "@/lib/auth"; // GET /api/souq/orders — my orders (as buyer or seller) export async function GET(request: NextRequest) { try { const auth = await requireAuth(request); if (!auth) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const { searchParams } = new URL(request.url); const role = searchParams.get("role"); // "buyer" | "seller" | null (both) const page = parseInt(searchParams.get("page") || "1", 10); const limit = parseInt(searchParams.get("limit") || "20", 10); const skip = (page - 1) * limit; const where: Record = {}; if (role === "buyer") { where.buyerId = auth.userId; } else if (role === "seller") { where.sellerId = auth.userId; } else { where.OR = [ { buyerId: auth.userId }, { sellerId: auth.userId }, ]; } const [orders, total] = await Promise.all([ prisma.purchase.findMany({ where, include: { listing: { select: { id: true, title: true, category: true, priceFlh: true }, }, buyer: { select: { id: true, name: true, email: true, avatar: true }, }, seller: { select: { id: true, name: true, email: true, avatar: true }, }, }, orderBy: { createdAt: "desc" }, skip, take: limit, }), prisma.purchase.count({ where }), ]); // Parse messages JSON for each order const parsed = orders.map((order) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const o = order as any; return { ...o, messages: o.messages ? JSON.parse(o.messages) : null, deliveryFiles: o.deliveryFiles ? JSON.parse(o.deliveryFiles) : null, }; }); return NextResponse.json({ orders: parsed, pagination: { page, limit, total, totalPages: Math.ceil(total / limit), }, }); } catch (error) { console.error("GET /api/souq/orders error:", error); return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } } // POST /api/souq/orders — place a new order export async function POST(request: NextRequest) { try { const auth = await requireAuth(request); if (!auth) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const user = await prisma.user.findUnique({ where: { id: auth.userId } }); if (!user) { return NextResponse.json({ error: "User not found" }, { status: 404 }); } const { listingId, packageName } = await request.json(); if (!listingId) { return NextResponse.json( { error: "Missing required field: listingId" }, { status: 400 } ); } // Validate listing exists const listing = await prisma.listing.findUnique({ where: { id: listingId }, }); if (!listing) { return NextResponse.json( { error: "Listing not found" }, { status: 404 } ); } if (listing.status !== "active") { return NextResponse.json( { error: "Listing is not available for purchase" }, { status: 400 } ); } // Prevent buying own listing if (listing.sellerId === user.id) { return NextResponse.json( { error: "You cannot purchase your own listing" }, { status: 400 } ); } // Determine amount: if packageName provided, look it up in packages JSON let amountFlh = listing.priceFlh; if (packageName) { if (!listing.packages) { return NextResponse.json( { error: "This listing has no packages" }, { status: 400 } ); } const packages = JSON.parse(listing.packages) as Array<{ name: string; price?: number; }>; const selectedPackage = packages.find((p) => p.name === packageName); if (!selectedPackage) { return NextResponse.json( { error: `Package "${packageName}" not found` }, { status: 400 } ); } amountFlh = selectedPackage.price ?? listing.priceFlh; } // Check buyer balance if (user.flhBalance < amountFlh) { return NextResponse.json( { error: "Insufficient FLH balance" }, { status: 400 } ); } // Calculate fees const platformFee = Math.round(amountFlh * 0.015); const sellerPayout = amountFlh - platformFee; // Create purchase and deduct balance in a transaction const [purchase] = await prisma.$transaction([ prisma.purchase.create({ data: { listingId, buyerId: user.id, sellerId: listing.sellerId, packageName: packageName || null, amountFlh, platformFee, sellerPayout, status: "paid", }, include: { listing: { select: { id: true, title: true, category: true, priceFlh: true }, }, buyer: { select: { id: true, name: true, email: true, avatar: true }, }, seller: { select: { id: true, name: true, email: true, avatar: true }, }, }, }), prisma.user.update({ where: { id: user.id }, data: { flhBalance: { decrement: amountFlh } }, }), // Increment sales count on the listing prisma.listing.update({ where: { id: listingId }, data: { salesCount: { increment: 1 } }, }), ]); return NextResponse.json({ order: purchase }, { status: 201 }); } catch (error) { console.error("POST /api/souq/orders error:", error); return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } }