import { NextRequest, NextResponse } from "next/server"; import { prisma } from "@/lib/prisma"; import { requireAuth } from "@/lib/auth"; export async function GET(request: NextRequest) { try { const { searchParams } = new URL(request.url); const category = searchParams.get("category"); const search = searchParams.get("search"); const featured = searchParams.get("featured"); const sellerId = searchParams.get("sellerId"); const minPrice = searchParams.get("minPrice"); const maxPrice = searchParams.get("maxPrice"); const sortBy = searchParams.get("sortBy"); const deliveryDays = searchParams.get("deliveryDays"); const page = parseInt(searchParams.get("page") || "1", 10); const limit = parseInt(searchParams.get("limit") || "20", 10); const skip = (page - 1) * limit; const where: Record = {}; // Only return active listings by default where.status = "active"; if (category) { where.category = category; } if (search) { where.OR = [ { title: { contains: search } }, { description: { contains: search } }, ]; } if (featured === "true") { where.featured = true; } if (sellerId) { where.sellerId = sellerId; } // Price range filter if (minPrice || maxPrice) { const priceFilter: Record = {}; if (minPrice) priceFilter.gte = parseInt(minPrice, 10); if (maxPrice) priceFilter.lte = parseInt(maxPrice, 10); where.priceFlh = priceFilter; } // Delivery days filter if (deliveryDays) { where.deliveryDays = { lte: parseInt(deliveryDays, 10) }; } // Build orderBy based on sortBy let orderBy: Record[]; switch (sortBy) { case "price_asc": orderBy = [{ priceFlh: "asc" }, { featured: "desc" }, { createdAt: "desc" }]; break; case "price_desc": orderBy = [{ priceFlh: "desc" }, { featured: "desc" }, { createdAt: "desc" }]; break; case "rating": orderBy = [{ rating: "desc" }, { featured: "desc" }, { createdAt: "desc" }]; break; case "popular": orderBy = [{ salesCount: "desc" }, { featured: "desc" }, { createdAt: "desc" }]; break; case "newest": orderBy = [{ createdAt: "desc" }, { featured: "desc" }]; break; default: orderBy = [{ featured: "desc" }, { createdAt: "desc" }]; break; } const [listings, total] = await Promise.all([ prisma.listing.findMany({ where, include: { seller: { select: { id: true, name: true, email: true, avatar: true }, }, }, orderBy, skip, take: limit, }), prisma.listing.count({ where }), ]); return NextResponse.json({ listings, pagination: { page, limit, total, totalPages: Math.ceil(total / limit), }, }); } catch (error) { console.error("GET /api/souq/listings error:", error); return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } } 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 { title, description, category, subcategory, priceFlh, packages, tags, images, deliveryDays, fileType, } = await request.json(); if (!title || !description || !category || !priceFlh) { return NextResponse.json( { error: "Missing required fields: title, description, category, priceFlh" }, { status: 400 } ); } if (typeof priceFlh !== "number" || priceFlh < 0) { return NextResponse.json( { error: "priceFlh must be a non-negative number" }, { status: 400 } ); } const listing = await prisma.listing.create({ data: { title, description, category, subcategory: subcategory || null, priceFlh, packages: packages ? JSON.stringify(packages) : null, tags: tags ? JSON.stringify(tags) : null, images: images ? JSON.stringify(images) : null, deliveryDays: deliveryDays || null, fileType: fileType || null, sellerId: user.id, status: "active", }, include: { seller: { select: { id: true, name: true, email: true, avatar: true }, }, }, }); return NextResponse.json({ listing }, { status: 201 }); } catch (error) { console.error("POST /api/souq/listings error:", error); return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } }