import { NextRequest, NextResponse } from "next/server";
import prisma from "@/lib/db";

export async function GET(request: NextRequest) {
  try {
    const searchParams = request.nextUrl.searchParams;

    // Extract query parameters
    const city = searchParams.get("city");
    const q = searchParams.get("q"); // search query
    const tags = searchParams.get("tags")?.split(",").filter(Boolean);
    const minPrice = searchParams.get("minPrice");
    const maxPrice = searchParams.get("maxPrice");
    const page = parseInt(searchParams.get("page") || "1");
    const limit = parseInt(searchParams.get("limit") || "12");
    const sortBy = searchParams.get("sortBy") || "createdAt"; // createdAt, price, rating
    const sortOrder = searchParams.get("sortOrder") || "desc"; // asc, desc

    // Calculate pagination
    const skip = (page - 1) * limit;

    // Build where clause
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const where: any = {
      published: true,
      archived: false,
    };

    // City filter
    if (city) {
      where.city = {
        contains: city,
        mode: "insensitive",
      };
    }

    // Search query (title or description)
    if (q) {
      where.OR = [
        {
          title: {
            contains: q,
            mode: "insensitive",
          },
        },
        {
          description: {
            contains: q,
            mode: "insensitive",
          },
        },
      ];
    }

    // Tag filter (tour tags should contain all specified tags)
    if (tags && tags.length > 0) {
      where.tags = {
        hasEvery: tags,
      };
    }

    // Price range filter
    if (minPrice || maxPrice) {
      where.priceCents = {};
      if (minPrice) {
        where.priceCents.gte = parseInt(minPrice);
      }
      if (maxPrice) {
        where.priceCents.lte = parseInt(maxPrice);
      }
    }

    // Build orderBy clause
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const orderBy: any = {};
    switch (sortBy) {
      case "price":
        orderBy.priceCents = sortOrder as "asc" | "desc";
        break;
      case "rating":
        orderBy.avgRating = sortOrder as "asc" | "desc";
        break;
      case "createdAt":
      default:
        orderBy.createdAt = sortOrder as "asc" | "desc";
        break;
    }

    // Fetch tours with pagination
    const [tours, totalCount] = await Promise.all([
      prisma.tour.findMany({
        where,
        include: {
          images: {
            orderBy: { order: "asc" },
            take: 1, // Only take first image for listing
          },
          createdBy: {
            select: {
              id: true,
              name: true,
              image: true,
            },
          },
          _count: {
            select: {
              reviews: true,
            },
          },
        },
        orderBy,
        skip,
        take: limit,
      }),
      prisma.tour.count({ where }),
    ]);

    // Calculate total pages
    const totalPages = Math.ceil(totalCount / limit);

    // Format response
    const formattedTours = tours.map((tour) => ({
      id: tour.id,
      title: tour.title,
      slug: tour.slug,
      description: tour.description,
      city: tour.city,
      durationMin: tour.durationMin,
      priceCents: tour.priceCents,
      tags: tour.tags,
      avgRating: tour.avgRating,
      reviewCount: tour._count.reviews,
      image: tour.images[0]?.url || null,
      guide: {
        id: tour.createdBy.id,
        name: tour.createdBy.name,
        avatarPath: tour.createdBy.image,
      },
      createdAt: tour.createdAt,
    }));

    return NextResponse.json({
      tours: formattedTours,
      pagination: {
        page,
        limit,
        totalCount,
        totalPages,
        hasNextPage: page < totalPages,
        hasPreviousPage: page > 1,
      },
    }, {
      headers: {
        // Cache for 1 minute, serve stale for up to 5 minutes while revalidating
        'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
      },
    });
  } catch (error) {
    console.error("Error fetching tours:", error);
    return NextResponse.json(
      { error: "Failed to fetch tours" },
      { status: 500 }
    );
  }
}
