import type { Metadata } from "next";
import { headers } from "next/headers";
import {
  db,
  recipes,
  users,
  favorites,
  userFollows,
  eq,
  desc,
  sql,
  and,
  gte,
  count,
} from "@epicure/db";
import { auth } from "@/lib/auth/server";
import { ExplorePageContent } from "@/components/search/explore-page-content";
import { attachCardExtras } from "@/lib/recipe-card-extras";

export const metadata: Metadata = {};

export type RecipeResult = {
  id: string;
  title: string;
  description: string | null;
  authorName: string | null;
  difficulty: "easy" | "medium" | "hard" | null;
  baseServings: number;
  prepMins: number | null;
  cookMins: number | null;
  visibility: "private" | "unlisted" | "public";
  tags: string[];
  isBatchCook: boolean;
  sourceUrl: string | null;
  recipeType: "dish" | "drink";
  photos: { storageKey: string; isCover: boolean }[];
  dishCount: number;
  isFavorited: boolean;
};

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

  const columns = {
    id: recipes.id,
    title: recipes.title,
    description: recipes.description,
    authorName: users.name,
    difficulty: recipes.difficulty,
    baseServings: recipes.baseServings,
    prepMins: recipes.prepMins,
    cookMins: recipes.cookMins,
    visibility: recipes.visibility,
    tags: recipes.tags,
    isBatchCook: recipes.isBatchCook,
    sourceUrl: recipes.sourceUrl,
    recipeType: recipes.recipeType,
  };

  // Trending: public recipes ordered by favorite count in last 7 days
  const trendingRows = await db
    .select({ ...columns, 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(columns)
    .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 [trending, recent] = await Promise.all([
    attachCardExtras(trendingRows.map(({ favoriteCount: _fc, ...r }) => r), session?.user.id),
    attachCardExtras(recentRows, session?.user.id),
  ]);

  // 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);

  const followedCount = session
    ? (
        await db
          .select({ followingId: userFollows.followingId })
          .from(userFollows)
          .where(eq(userFollows.followerId, session.user.id))
      ).length
    : 0;

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