import { listImages, countImages, libraryStats, libraryLetterCounts } from "@/lib/db/queries";
import { LibraryGrid } from "@/components/grid/LibraryGrid";
import { getAppSetting } from "@/lib/db/appSettings";
import { UploadCard } from "@/components/ingest/UploadCard";
import { RegisterVisible } from "@/components/select/RegisterVisible";
import { FilterBar } from "@/components/grid/FilterBar";
import { LetterBar } from "@/components/grid/LetterBar";
import type { LibraryView } from "@/components/grid/ViewToggle";
import { resolveSort } from "@/lib/sortServer";
import { parseFilterCriteria, anyActive as hasAnyCriteria, statusToFlags } from "@/lib/filters";
import { Disc3 } from "lucide-react";

export const dynamic = "force-dynamic";

export default async function Home({
  searchParams,
}: {
  searchParams: Promise<Record<string, string | string[] | undefined>>;
}) {
  const sp = await searchParams;
  const criteria = parseFilterCriteria(sp);
  const sort = await resolveSort(typeof sp.sort === "string" ? sp.sort : undefined);
  const rawLetter = (typeof sp.letter === "string" ? sp.letter : "").toUpperCase();
  const letter = rawLetter === "#" ? "#" : (/^[A-Z]$/.test(rawLetter) ? rawLetter : null);
  const search = (typeof sp.q === "string" ? sp.q.trim() : "") || undefined;
  const view: LibraryView = sp.view === "portrait" ? "portrait" : "landscape";
  const anyActive = hasAnyCriteria(criteria) || letter != null || !!search;

  // URL pagination — `page` is the anchor (1-based). Page size from
  // user settings (Settings → Appearance → Items Per Page). Negative
  // / non-numeric params clamp to 1.
  const PAGE_SIZE = Math.max(25, Math.min(500, getAppSetting("coverPageSize") ?? 100));
  const rawPage = typeof sp.page === "string" ? Number(sp.page) : NaN;
  const page = Number.isFinite(rawPage) && rawPage >= 1 ? Math.floor(rawPage) : 1;
  const offset = (page - 1) * PAGE_SIZE;

  const filterOpts = {
    sort,
    letter: letter ?? undefined,
    search,
    ...statusToFlags(criteria.status),
    marks: criteria.marks,
    actressIds: criteria.ids.actresses,
    actressMode: criteria.mode.actresses,
    studioIds: criteria.ids.studios,
    seriesIds: criteria.ids.series,
    genreIds: criteria.ids.genres,
    genreMode: criteria.mode.genres,
    collectionIds: criteria.ids.collections,
    collectionMode: criteria.mode.collections,
    tagIds: criteria.ids.tags,
    tagMode: criteria.mode.tags,
    categoryIds: criteria.ids.categories,
    categoryMode: criteria.mode.categories,
  };
  const totalCount = countImages(filterOpts);
  const totalPages = Math.max(1, Math.ceil(totalCount / PAGE_SIZE));
  // Clamp out-of-range page back to last; cheap re-fetch since we only
  // care about offset and we already have the count.
  const effectivePage = Math.min(page, totalPages);
  const effectiveOffset = (effectivePage - 1) * PAGE_SIZE;

  const items = listImages({ ...filterOpts, limit: PAGE_SIZE, offset: effectiveOffset });
  const stats = libraryStats();
  const letterCounts = libraryLetterCounts({
    ...statusToFlags(criteria.status),
    marks: criteria.marks,
    actressIds: criteria.ids.actresses,
    actressMode: criteria.mode.actresses,
    studioIds: criteria.ids.studios,
    seriesIds: criteria.ids.series,
    genreIds: criteria.ids.genres,
    genreMode: criteria.mode.genres,
    collectionIds: criteria.ids.collections,
    collectionMode: criteria.mode.collections,
    tagIds: criteria.ids.tags,
    tagMode: criteria.mode.tags,
    categoryIds: criteria.ids.categories,
    categoryMode: criteria.mode.categories,
    search,
  });

  return (
    <div className="max-w-[1600px] mx-auto px-6 py-8 fade-in">
      <section className="mb-6 grid grid-cols-1 lg:grid-cols-[1fr_minmax(280px,360px)] gap-6 items-start">
        <div>
          <h1 className="text-4xl font-semibold tracking-tight">
            Your <span className="text-gradient-accent">Cover Library</span>
          </h1>
          <p className="text-[var(--color-fg-dim)] mt-2 max-w-prose">
            Drop cover images to import. Codes are parsed from filenames; metadata can be filled in
            manually or seeded from a sibling <span className="font-mono">.nfo</span> file. Tag, collect,
            rate, and search.
          </p>
          <div className="flex flex-wrap gap-6 mt-6 text-sm">
            <Stat label="Covers" value={stats.images} />
            <Stat label="Actresses" value={stats.actresses} />
            <Stat label="Studios" value={stats.studios} />
            <Stat label="Tags" value={stats.tags} />
            <Stat label="Collections" value={stats.collections} />
          </div>
        </div>
        <UploadCard />
      </section>

      <FilterBar current={{ kind: "all" }} criteria={criteria} sort={sort} view={view} />
      <div className="my-6">
        <LetterBar active={letter} counts={letterCounts} />
      </div>

      <RegisterVisible ids={items.map((i) => i.id)} />

      {items.length === 0 ? (
        <div className="glass rounded-2xl p-card text-center">
          <Disc3 className="w-10 h-10 mx-auto text-[var(--color-cyan)] mb-label" />
          <h2 className="text-xl font-medium">
            {anyActive ? "Nothing Matches" : "Nothing Here Yet"}
          </h2>
          <p className="text-[var(--color-fg-dim)] mt-1">
            {anyActive ? "All filtered out — switch back to All." : "Drag a few covers above to get started."}
          </p>
        </div>
      ) : (
        <div key={`${view}-${letter ?? "all"}-${effectivePage}`} className="fade-in">
          <LibraryGrid
            initialItems={items}
            initialPage={effectivePage}
            totalPages={totalPages}
            totalCount={totalCount}
            view={view}
            infiniteScrollEnabled
          />
        </div>
      )}
    </div>
  );
}

function Stat({ label, value }: { label: string; value: number }) {
  return (
    <div>
      <div className="text-2xl font-mono font-semibold tabular-nums">{value}</div>
      <div className="text-xs uppercase tracking-wider text-[var(--color-fg-muted)]">{label}</div>
    </div>
  );
}
