import type { Prisma } from "@prisma/client";
import { db } from "@/lib/db";
import { LabelCard, type LabelCardData } from "@/components/labels/LabelCard";
import { getHighestBadgesForUsers } from "@/lib/badges";
import { GalleryFilters } from "./GalleryFilters";

interface GallerySearchParams {
  brand?: string;
  blend?: string;
  uploader?: string;
  badgeTier?: string;
  sort?: string;
}

export default async function GalleryPage({
  searchParams,
}: {
  searchParams: Promise<GallerySearchParams>;
}) {
  const params = await searchParams;
  const sort = params.sort === "most_downloaded" || params.sort === "trending"
    ? params.sort
    : "newest";

  const where: Prisma.LabelWhereInput = { status: "active" };

  const blendWhere: Prisma.BlendWhereInput = {};
  if (params.brand) blendWhere.brand = { slug: params.brand };
  if (params.blend?.trim()) {
    blendWhere.name = { contains: params.blend.trim(), mode: "insensitive" };
  }
  if (Object.keys(blendWhere).length > 0) where.blend = blendWhere;

  const uploaderWhere: Prisma.UserWhereInput = {};
  if (params.uploader?.trim()) {
    uploaderWhere.username = {
      contains: params.uploader.trim(),
      mode: "insensitive",
    };
  }
  const badgeTier = params.badgeTier ? Number(params.badgeTier) : undefined;
  if (badgeTier) {
    uploaderWhere.userBadges = {
      some: { badge: { threshold: { gte: badgeTier } } },
    };
  }
  if (Object.keys(uploaderWhere).length > 0) where.uploader = uploaderWhere;

  // "Trending this week" approximates trending as recently-uploaded labels
  // ranked by all-time download count -- there's no per-download event log
  // yet to compute a true rolling 7-day download count, so this is recency
  // + popularity rather than a strict weekly download window.
  if (sort === "trending") {
    // This is a Server Component computing data per-request, not a
    // re-rendering client component -- reading the current time here is
    // normal SSR data fetching.
    // eslint-disable-next-line react-hooks/purity
    const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
    where.createdAt = { gte: sevenDaysAgo };
  }

  const orderBy: Prisma.LabelOrderByWithRelationInput =
    sort === "most_downloaded" || sort === "trending"
      ? { downloadCount: "desc" }
      : { createdAt: "desc" };

  const [labels, brands, badgeTiers] = await Promise.all([
    db.label.findMany({
      where,
      orderBy,
      take: 60,
      include: {
        blend: { include: { brand: true } },
        uploader: true,
        versions: { where: { isCurrent: true }, take: 1 },
        cellarChoice: { take: 1 },
      },
    }),
    db.brand.findMany({ orderBy: { name: "asc" } }),
    db.badge.findMany({
      where: { track: "uploads" },
      orderBy: { threshold: "asc" },
    }),
  ]);

  const highestBadges = await getHighestBadgesForUsers(
    Array.from(new Set(labels.map((label) => label.uploaderId))),
  );

  const cards: LabelCardData[] = labels
    .filter((label) => label.versions[0])
    .map((label) => ({
      id: label.id,
      fileUrl: label.versions[0].fileUrl,
      brandName: label.blend.brand.name,
      brandSlug: label.blend.brand.slug,
      blendName: label.blend.name,
      blendSlug: label.blend.slug,
      uploaderUsername: label.uploader.username,
      uploaderAvatarUrl: label.uploader.avatarUrl,
      uploaderHighestBadgeName: highestBadges.get(label.uploaderId)?.name ?? null,
      thumbsUpCount: label.thumbsUpCount,
      isCellarChoice: label.cellarChoice.length > 0,
      isRequestFulfillment: label.fulfilledRequestId !== null,
    }));

  return (
    <div className="mx-auto max-w-6xl px-6 py-16">
      <h1 className="font-heading text-4xl font-semibold text-terracotta">
        Label Gallery
      </h1>
      <p className="mt-2 text-charcoal/60">
        Browse labels shared by the community.
      </p>

      <div className="mt-8">
        <GalleryFilters
          brands={brands}
          badgeTiers={badgeTiers}
          current={params}
        />
      </div>

      {cards.length === 0 ? (
        <p className="mt-16 text-center text-charcoal/60">
          No labels match those filters yet.
        </p>
      ) : (
        <ul className="mt-10 grid grid-cols-2 gap-8 sm:grid-cols-3 lg:grid-cols-5">
          {cards.map((card) => (
            <li key={card.id}>
              <LabelCard label={card} />
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}
