import Link from "next/link";
import { notFound } from "next/navigation";
import { auth } from "@/lib/auth";
import { db } from "@/lib/db";
import { LabelCard, type LabelCardData } from "@/components/labels/LabelCard";
import { getHighestBadgesForUsers } from "@/lib/badges";
import { FollowWatchButtons } from "@/app/(public)/labels/[id]/FollowWatchButtons";
import { NewFolderForm } from "@/components/labels/NewFolderForm";
import { AVERY_SPECS } from "@/lib/avery-specs";
import { AvatarWithEdit } from "./AvatarWithEdit";
import { PrivacyToggle } from "./PrivacyToggle";
import { FolderRow } from "./FolderRow";
import { ReprintButton } from "./ReprintButton";
import { DeleteSheetButton } from "./DeleteSheetButton";
import { FolderSelectGrid } from "./FolderSelectGrid";

type Tab = "uploads" | "favorites" | "folders" | "sheets";

function labelToCard(
  label: {
    id: string;
    uploaderId: string;
    thumbsUpCount: number;
    fulfilledRequestId: string | null;
    blend: { name: string; slug: string; brand: { name: string; slug: string } };
    uploader: { username: string; avatarUrl: string | null };
    versions: { fileUrl: string }[];
    cellarChoice: unknown[];
  },
  highestBadges: Map<string, { name: string }>,
): LabelCardData | null {
  const fileUrl = label.versions[0]?.fileUrl;
  if (!fileUrl) return null;
  return {
    id: label.id,
    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,
  };
}

export default async function ProfilePage({
  params,
  searchParams,
}: {
  params: Promise<{ username: string }>;
  searchParams: Promise<{ tab?: string; folder?: string }>;
}) {
  const { username } = await params;
  const { tab: rawTab, folder: folderId } = await searchParams;

  const profileUser = await db.user.findUnique({ where: { username } });
  if (!profileUser) {
    notFound();
  }

  const session = await auth();
  const viewerId = (session?.user as { id?: string } | undefined)?.id;
  const isOwner = viewerId === profileUser.id;
  const canViewFolders = isOwner || !profileUser.isPrivate;

  const tab: Tab =
    rawTab === "favorites" || rawTab === "folders" || rawTab === "sheets"
      ? rawTab
      : "uploads";

  const [badges, followersCount, followingCount, viewerFollowRow] =
    await Promise.all([
      db.userBadge.findMany({
        where: { userId: profileUser.id, badge: { track: { not: "uploads" } } },
        include: { badge: true },
        orderBy: { badge: { threshold: "asc" } },
      }),
      db.follow.count({ where: { followingId: profileUser.id } }),
      db.follow.count({ where: { followerId: profileUser.id } }),
      viewerId && !isOwner
        ? db.follow.findUnique({
            where: {
              followerId_followingId: { followerId: viewerId, followingId: profileUser.id },
            },
          })
        : null,
    ]);

  const labelInclude = {
    blend: { include: { brand: true } },
    uploader: true,
    versions: { where: { isCurrent: true }, take: 1 },
    cellarChoice: { take: 1 },
  } as const;

  let cards: LabelCardData[] = [];
  let folders: { id: string; name: string; labelCount: number }[] = [];
  let activeFolderName: string | null = null;
  let activeFolderId: string | null = null;
  let sheets: {
    id: string;
    name: string;
    jarType: string;
    pageCount: number;
    createdAt: Date;
  }[] = [];

  if (tab === "uploads") {
    const labels = await db.label.findMany({
      where: { uploaderId: profileUser.id, status: "active" },
      orderBy: { createdAt: "desc" },
      include: labelInclude,
    });
    const highestBadges = await getHighestBadgesForUsers([profileUser.id]);
    cards = labels
      .map((l) => labelToCard(l, highestBadges))
      .filter((c): c is LabelCardData => c !== null);
  } else if (tab === "favorites" && canViewFolders) {
    const saved = await db.savedLabel.findMany({
      where: { userId: profileUser.id, folderId: null },
      orderBy: { createdAt: "desc" },
      include: { label: { include: labelInclude } },
    });
    const highestBadges = await getHighestBadgesForUsers(
      Array.from(new Set(saved.map((s) => s.label.uploaderId))),
    );
    cards = saved
      .map((s) => labelToCard(s.label, highestBadges))
      .filter((c): c is LabelCardData => c !== null);
  } else if (tab === "folders" && canViewFolders) {
    if (folderId) {
      const folder = await db.savedFolder.findUnique({ where: { id: folderId } });
      if (folder && folder.userId === profileUser.id) {
        activeFolderName = folder.name;
        activeFolderId = folder.id;
        const saved = await db.savedLabel.findMany({
          where: { userId: profileUser.id, folderId },
          orderBy: { createdAt: "desc" },
          include: { label: { include: labelInclude } },
        });
        const highestBadges = await getHighestBadgesForUsers(
          Array.from(new Set(saved.map((s) => s.label.uploaderId))),
        );
        cards = saved
          .map((s) => labelToCard(s.label, highestBadges))
          .filter((c): c is LabelCardData => c !== null);
      }
    } else {
      const rawFolders = await db.savedFolder.findMany({
        where: { userId: profileUser.id },
        orderBy: { name: "asc" },
        include: { _count: { select: { labels: true } } },
      });
      folders = rawFolders.map((f) => ({
        id: f.id,
        name: f.name,
        labelCount: f._count.labels,
      }));
    }
  } else if (tab === "sheets" && canViewFolders) {
    const rawSheets = await db.savedSheet.findMany({
      where: { userId: profileUser.id },
      orderBy: { createdAt: "desc" },
    });
    sheets = rawSheets.map((s) => ({
      id: s.id,
      name: s.name,
      jarType: s.jarType,
      pageCount: Array.isArray(s.pages) ? s.pages.length : 0,
      createdAt: s.createdAt,
    }));
  }

  const labelsHeading = isOwner
    ? "My Labels"
    : `${profileUser.username}'s Labels`;

  return (
    <div className="mx-auto max-w-5xl px-6 py-16">
      <div className="flex flex-col items-start gap-6 sm:flex-row sm:items-center sm:justify-between">
        <div className="flex items-center gap-4">
          <AvatarWithEdit
            username={profileUser.username}
            avatarUrl={profileUser.avatarUrl}
            isOwner={isOwner}
          />
          <h1 className="font-heading text-2xl font-semibold text-charcoal">
            {profileUser.username}
          </h1>
        </div>

        {viewerId && !isOwner && (
          <FollowWatchButtons
            targetUserId={profileUser.id}
            initialFollowing={Boolean(viewerFollowRow)}
            initialWatching={Boolean(viewerFollowRow?.watchUploads)}
          />
        )}
      </div>

      {badges.length > 0 && (
        <div className="mt-4 flex flex-wrap gap-2">
          {badges.map((ub) => (
            <span
              key={ub.id}
              className="rounded-full bg-gold/15 px-3 py-1 text-xs font-medium text-gold"
            >
              {ub.badge.name}
            </span>
          ))}
        </div>
      )}

      <div className="mt-4 flex flex-wrap gap-6 text-sm text-charcoal/70">
        <span>
          <strong className="text-charcoal">{profileUser.uploadCount}</strong> uploads
        </span>
        <span>
          <strong className="text-charcoal">{profileUser.thumbsUpReceived}</strong> upvotes
        </span>
        <span>
          <strong className="text-charcoal">{followersCount}</strong> followers
        </span>
        <span>
          <strong className="text-charcoal">{followingCount}</strong> following
        </span>
      </div>

      {isOwner && (
        <div className="mt-4">
          <PrivacyToggle initialIsPrivate={profileUser.isPrivate} />
        </div>
      )}

      <div className="mt-10 border-b border-charcoal/10">
        <nav className="flex gap-6">
          <Link
            href={`/profile/${username}?tab=uploads`}
            className={`border-b-2 px-1 pb-3 text-sm font-medium ${
              tab === "uploads"
                ? "border-terracotta text-terracotta"
                : "border-transparent text-charcoal/60 hover:text-charcoal"
            }`}
          >
            {labelsHeading}
          </Link>
          {canViewFolders && (
            <>
              <Link
                href={`/profile/${username}?tab=favorites`}
                className={`border-b-2 px-1 pb-3 text-sm font-medium ${
                  tab === "favorites"
                    ? "border-terracotta text-terracotta"
                    : "border-transparent text-charcoal/60 hover:text-charcoal"
                }`}
              >
                Favorites
              </Link>
              <Link
                href={`/profile/${username}?tab=folders`}
                className={`border-b-2 px-1 pb-3 text-sm font-medium ${
                  tab === "folders"
                    ? "border-terracotta text-terracotta"
                    : "border-transparent text-charcoal/60 hover:text-charcoal"
                }`}
              >
                Folders
              </Link>
              <Link
                href={`/profile/${username}?tab=sheets`}
                className={`border-b-2 px-1 pb-3 text-sm font-medium ${
                  tab === "sheets"
                    ? "border-terracotta text-terracotta"
                    : "border-transparent text-charcoal/60 hover:text-charcoal"
                }`}
              >
                Sheets
              </Link>
            </>
          )}
        </nav>
      </div>

      <div className="mt-8">
        {tab === "folders" && !folderId && (
          <>
            {isOwner && (
              <div className="mb-6">
                <NewFolderForm />
              </div>
            )}
            {folders.length === 0 ? (
              <p className="text-charcoal/60">No folders yet.</p>
            ) : (
              <div className="flex flex-col gap-2">
                {folders.map((folder) => (
                  <FolderRow
                    key={folder.id}
                    username={username}
                    folder={folder}
                    isOwner={isOwner}
                    isActive={false}
                  />
                ))}
              </div>
            )}
          </>
        )}

        {tab === "folders" && folderId && (
          <div className="mb-6 flex items-center justify-between">
            <div>
              <Link
                href={`/profile/${username}?tab=folders`}
                className="text-sm text-terracotta hover:underline"
              >
                &larr; All folders
              </Link>
              <h2 className="mt-2 font-heading text-xl font-semibold text-charcoal">
                {activeFolderName ?? "Folder"}
              </h2>
            </div>
            {isOwner && cards.length > 0 && activeFolderId && (
              <Link
                href={`/sheet-builder?folder=${activeFolderId}`}
                className="rounded-full bg-terracotta px-4 py-2 text-sm font-medium text-white hover:bg-terracotta/90"
              >
                Print this folder
              </Link>
            )}
          </div>
        )}

        {tab === "sheets" &&
          (sheets.length === 0 ? (
            <p className="text-charcoal/60">No saved sheets yet.</p>
          ) : (
            <ul className="flex flex-col gap-3">
              {sheets.map((sheet) => (
                <li
                  key={sheet.id}
                  className="flex items-center justify-between rounded-lg border border-charcoal/10 bg-warm-white p-4"
                >
                  <div>
                    <p className="font-medium text-charcoal">{sheet.name}</p>
                    <p className="text-sm text-charcoal/50">
                      {AVERY_SPECS[sheet.jarType as "wide" | "regular"]?.sku ?? sheet.jarType},{" "}
                      {sheet.pageCount} sheet{sheet.pageCount === 1 ? "" : "s"}
                    </p>
                  </div>
                  {isOwner && (
                    <div className="flex items-center gap-3">
                      <ReprintButton sheetId={sheet.id} />
                      <DeleteSheetButton sheetId={sheet.id} />
                    </div>
                  )}
                </li>
              ))}
            </ul>
          ))}

        {tab === "folders" && folderId ? (
          cards.length === 0 ? (
            <p className="text-charcoal/60">Nothing here yet.</p>
          ) : isOwner ? (
            <FolderSelectGrid cards={cards} />
          ) : (
            <ul className="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>
          )
        ) : (
          (tab === "uploads" || tab === "favorites") &&
          (cards.length === 0 ? (
            <p className="text-charcoal/60">Nothing here yet.</p>
          ) : (
            <ul className="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>
    </div>
  );
}
