import type { Metadata } from "next";
import Link from "next/link";
import { ilike, or, sql } from "drizzle-orm";
import {
  Search,
  Users,
  FileText,
  GraduationCap,
  FlaskConical,
  ShoppingBag,
  BookOpen,
  ClipboardList,
  BookOpenCheck,
} from "lucide-react";
import { requireAdmin } from "@/lib/auth/admin-guard";
import { db } from "@/lib/db/client";
import {
  users,
  blogPosts,
  courses,
  researchStudiesTable,
  storeProducts,
  atlasConditions,
  consentiqProcedures,
  orthoprepQuestions,
} from "@/lib/db/schema";
import {
  AdminHeading,
  FormSection,
  EmptyState,
  SearchInput,
} from "@/components/admin";

export const metadata: Metadata = { title: "Search" };
export const dynamic = "force-dynamic";

const PER_TYPE_LIMIT = 10;

type SearchResult = {
  id: string;
  title: string;
  subtitle?: string;
  href: string;
};

async function searchType<T>(
  q: string,
  runner: (pattern: string) => Promise<SearchResult[]>,
): Promise<SearchResult[]> {
  if (!q) return [];
  try {
    return await runner(`%${q}%`);
  } catch (err) {
    console.error("[admin-search] type failed", err);
    return [];
  }
}

export default async function AdminSearchPage({
  searchParams,
}: {
  searchParams: Promise<{ q?: string }>;
}) {
  await requireAdmin();
  const params = await searchParams;
  const q = (params.q ?? "").trim();

  const [
    userHits,
    blogHits,
    courseHits,
    studyHits,
    productHits,
    atlasHits,
    consentHits,
    questionHits,
  ] = await Promise.all([
    searchType(q, async (p) =>
      (
        await db
          .select({ id: users.id, name: users.name, email: users.email })
          .from(users)
          .where(or(ilike(users.name, p), ilike(users.email, p)))
          .limit(PER_TYPE_LIMIT)
      ).map((r) => ({
        id: r.id,
        title: r.name,
        subtitle: r.email,
        href: `/admin/members#${r.id}`,
      })),
    ),
    searchType(q, async (p) =>
      (
        await db
          .select({ id: blogPosts.id, title: blogPosts.title, slug: blogPosts.slug })
          .from(blogPosts)
          .where(or(ilike(blogPosts.title, p), ilike(blogPosts.content, p)))
          .limit(PER_TYPE_LIMIT)
      ).map((r) => ({
        id: r.id,
        title: r.title,
        subtitle: r.slug,
        href: `/admin/blog/${r.id}`,
      })),
    ),
    searchType(q, async (p) =>
      (
        await db
          .select({
            id: courses.id,
            title: courses.title,
            slug: courses.slug,
          })
          .from(courses)
          .where(or(ilike(courses.title, p), ilike(courses.description, p)))
          .limit(PER_TYPE_LIMIT)
      ).map((r) => ({
        id: r.id,
        title: r.title,
        subtitle: r.slug,
        href: `/admin/academy/${r.id}`,
      })),
    ),
    searchType(q, async (p) =>
      (
        await db
          .select({
            id: researchStudiesTable.id,
            title: researchStudiesTable.title,
            slug: researchStudiesTable.slug,
          })
          .from(researchStudiesTable)
          .where(
            or(
              ilike(researchStudiesTable.title, p),
              ilike(researchStudiesTable.background, p),
            ),
          )
          .limit(PER_TYPE_LIMIT)
      ).map((r) => ({
        id: r.id,
        title: r.title,
        subtitle: r.slug,
        href: `/admin/research/${r.id}`,
      })),
    ),
    searchType(q, async (p) =>
      (
        await db
          .select({
            id: storeProducts.id,
            title: storeProducts.title,
            slug: storeProducts.slug,
          })
          .from(storeProducts)
          .where(
            or(ilike(storeProducts.title, p), ilike(storeProducts.description, p)),
          )
          .limit(PER_TYPE_LIMIT)
      ).map((r) => ({
        id: r.id,
        title: r.title,
        subtitle: r.slug,
        href: `/admin/store/${r.id}`,
      })),
    ),
    searchType(q, async (p) =>
      (
        await db
          .select({
            id: atlasConditions.id,
            name: atlasConditions.name,
            slug: atlasConditions.slug,
          })
          .from(atlasConditions)
          .where(
            or(ilike(atlasConditions.name, p), ilike(atlasConditions.summary, p)),
          )
          .limit(PER_TYPE_LIMIT)
      ).map((r) => ({
        id: r.id,
        title: r.name,
        subtitle: r.slug,
        href: `/admin/atlas/conditions/${r.id}`,
      })),
    ),
    searchType(q, async (p) =>
      (
        await db
          .select({
            id: consentiqProcedures.id,
            name: consentiqProcedures.name,
            slug: consentiqProcedures.slug,
          })
          .from(consentiqProcedures)
          .where(
            or(
              ilike(consentiqProcedures.name, p),
              ilike(consentiqProcedures.summary, p),
            ),
          )
          .limit(PER_TYPE_LIMIT)
      ).map((r) => ({
        id: r.id,
        title: r.name,
        subtitle: r.slug,
        href: `/admin/consentiq/${r.id}`,
      })),
    ),
    searchType(q, async (p) =>
      (
        await db
          .select({
            id: orthoprepQuestions.id,
            number: orthoprepQuestions.number,
            stem: orthoprepQuestions.stem,
            chapter: orthoprepQuestions.chapter,
          })
          .from(orthoprepQuestions)
          .where(
            or(
              ilike(orthoprepQuestions.stem, p),
              ilike(orthoprepQuestions.explanation, p),
            ),
          )
          .limit(PER_TYPE_LIMIT)
      ).map((r) => ({
        id: r.id,
        title: `#${r.number} ${r.stem.slice(0, 80)}`,
        subtitle: r.chapter,
        href: `/admin/orthoprep/${r.id}`,
      })),
    ),
  ]);

  const groups = [
    { label: "Members", Icon: Users, hits: userHits },
    { label: "Blog posts", Icon: FileText, hits: blogHits },
    { label: "Courses", Icon: GraduationCap, hits: courseHits },
    { label: "Research studies", Icon: FlaskConical, hits: studyHits },
    { label: "Store products", Icon: ShoppingBag, hits: productHits },
    { label: "Atlas conditions", Icon: BookOpen, hits: atlasHits },
    { label: "ConsentIQ procedures", Icon: ClipboardList, hits: consentHits },
    { label: "OrthoPrep questions", Icon: BookOpenCheck, hits: questionHits },
  ];
  const totalHits = groups.reduce((a, g) => a + g.hits.length, 0);

  return (
    <>
      <AdminHeading
        eyebrow="System"
        title="Search"
        lede="Find members, content, and questions across every admin section in one place."
      />

      <div className="mb-6 max-w-xl">
        <form method="GET" action="/admin/search">
          <SearchInput
            name="q"
            defaultValue={q}
            placeholder="Search members, blog posts, courses, studies, products, atlas conditions, questions…"
          />
        </form>
      </div>

      {!q ? (
        <EmptyState
          Icon={Search}
          title="Start typing"
          description="Results appear as you search. Matching looks at titles, names, and primary body content for each type."
        />
      ) : totalHits === 0 ? (
        <EmptyState
          Icon={Search}
          title={`No matches for "${q}"`}
          description="Try shorter keywords or a different section."
        />
      ) : (
        <div className="grid gap-4 md:grid-cols-2">
          {groups.map(({ label, Icon, hits }) =>
            hits.length === 0 ? null : (
              <FormSection
                key={label}
                title={
                  <span className="inline-flex items-center gap-2">
                    <Icon className="h-4 w-4 text-[var(--color-blue)]" aria-hidden />
                    {label}
                    <span className="rounded-full bg-[var(--color-mist)] px-2 py-0.5 text-[11px] font-bold text-[var(--color-blue)]">
                      {hits.length}
                    </span>
                  </span>
                }
                padded={false}
              >
                <ul className="divide-y divide-[var(--color-line)]">
                  {hits.map((h) => (
                    <li key={`${label}-${h.id}`}>
                      <Link
                        href={h.href}
                        className="flex items-center justify-between gap-3 px-5 py-3 text-[13px] transition-colors hover:bg-[var(--color-mist)]/30"
                      >
                        <div className="min-w-0">
                          <div className="truncate font-semibold text-[var(--color-ink)]">
                            {h.title}
                          </div>
                          {h.subtitle && (
                            <div className="truncate text-[12px] text-[var(--color-slate)]">
                              {h.subtitle}
                            </div>
                          )}
                        </div>
                        <span className="shrink-0 text-[11px] font-semibold text-[var(--color-blue)]">
                          Open →
                        </span>
                      </Link>
                    </li>
                  ))}
                </ul>
              </FormSection>
            ),
          )}
        </div>
      )}
    </>
  );
}
