import type { Metadata } from "next";
import {
  db,
  recipes,
  users,
  favorites,
  eq,
  desc,
  sql,
  and,
  gte,
  count,
} from "@epicure/db";
import { ExplorePageContent } from "@/components/search/explore-page-content";
import { getAvgRatingsByRecipeId } from "@/lib/recipe-ratings";

export const metadata: Metadata = {};

export type RecipeResult = {
  id: string;
  title: string;
  authorName: string | null;
  difficulty: string | null;
  prepMins: number | null;
  cookMins: number | null;
  avgRating: number | null;
  ratingCount: number;
};

export default async function ExplorePage({
  searchParams,
}: {
  searchParams: Promise<{ q?: string }>;
}) {
  const { q } = await searchParams;
  const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);

  // Trending: public recipes ordered by favorite count in last 7 days
  const trendingRows = await db
    .select({
      id: recipes.id,
      title: recipes.title,
      authorName: users.name,
      difficulty: recipes.difficulty,
      prepMins: recipes.prepMins,
      cookMins: recipes.cookMins,
      favoriteCount: count(favorites.recipeId),
    })
    .from(recipes)
    .innerJoin(users, eq(recipes.authorId, users.id))
    .leftJoin(
      favorites,
      and(
        eq(favorites.recipeId, recipes.id),
        gte(favorites.createdAt, sevenDaysAgo)
      )
    )
    .where(and(eq(recipes.visibility, "public"), eq(users.isPrivate, false)))
    .groupBy(recipes.id, users.id)
    .orderBy(desc(sql`count(${favorites.recipeId})`))
    .limit(12);

  // Recent: public recipes ordered by createdAt desc
  const recentRows = await db
    .select({
      id: recipes.id,
      title: recipes.title,
      authorName: users.name,
      difficulty: recipes.difficulty,
      prepMins: recipes.prepMins,
      cookMins: recipes.cookMins,
    })
    .from(recipes)
    .innerJoin(users, eq(recipes.authorId, users.id))
    .where(and(eq(recipes.visibility, "public"), eq(users.isPrivate, false)))
    .orderBy(desc(recipes.createdAt))
    .limit(12);

  const ratingByRecipe = await getAvgRatingsByRecipeId([
    ...trendingRows.map((r) => r.id),
    ...recentRows.map((r) => r.id),
  ]);
  const withRating = (r: { id: string }) => ({
    avgRating: ratingByRecipe.get(r.id)?.avgRating ?? null,
    ratingCount: ratingByRecipe.get(r.id)?.ratingCount ?? 0,
  });

  const trending: RecipeResult[] = trendingRows.map(({ favoriteCount: _fc, ...r }) => ({ ...r, ...withRating(r) }));
  const recent: RecipeResult[] = recentRows.map((r) => ({ ...r, ...withRating(r) }));

  // Most-used tags across public recipes — shown as filter chips on the
  // search bar so browsing by tag doesn't require typing the exact word.
  const popularTagsResult = await db.execute<{ tag: string }>(sql`
    select tag, count(*) as usage_count
    from recipes r
    inner join users u on r.author_id = u.id
    cross join lateral unnest(r.tags) as tag
    where r.visibility = 'public' and u.is_private = false
    group by tag
    order by usage_count desc
    limit 12
  `);
  const popularTags = popularTagsResult.map((r) => r.tag);

  return (
    <ExplorePageContent
      trending={trending}
      recent={recent}
      initialQuery={q ?? ""}
      popularTags={popularTags}
    />
  );
}
