import type { Metadata } from "next";
import Link from "next/link";
import Image from "next/image";
import { Reveal, RevealGroup, RevealItem } from "../components/Reveal";
import { Newsletter } from "../components/Newsletter";
import { Footer } from "../components/Footer";
import { BlogCategoryFilter } from "../components/BlogCategoryFilter";
import { getBlogPosts, getBlogFilterEnabled } from "../lib/payload";
import { formatDate } from "../lib/format";

export const metadata: Metadata = {
  title: "Blog",
  description: "Gedanken, Methoden und Impulse für einen leichteren und klareren Alltag.",
  alternates: { canonical: "/blog" },
  openGraph: {
    title: "Blog | einfach produktiv.",
    description: "Gedanken, Methoden und Impulse für einen leichteren und klareren Alltag.",
    url: "/blog",
    type: "website",
    images: ["/blog-featured.jpg"],
  },
};

// Every distinct category name in DOM order — Payload's `categories` field
// stores related docs, no separate slug on this side, but since this page
// already fetches every published post (limit 100, no pagination), a
// plain client-agnostic array filter is enough; no separate Payload query
// per category needed.
function distinctCategories(posts: { categories: string[] }[]): string[] {
  const seen = new Set<string>();
  for (const post of posts) for (const c of post.categories) seen.add(c);
  return Array.from(seen);
}

export default async function BlogOverviewPage({
  searchParams,
}: {
  searchParams: Promise<{ categories?: string }>;
}) {
  const [allPosts, blogFilterEnabled] = await Promise.all([getBlogPosts(100), getBlogFilterEnabled()]);
  const { categories: categoriesParam } = await searchParams;
  const activeCategories = blogFilterEnabled && categoriesParam ? categoriesParam.split(",").filter(Boolean) : [];
  const allCategories = blogFilterEnabled ? distinctCategories(allPosts) : [];
  const posts =
    activeCategories.length === 0 ? allPosts : allPosts.filter((post) => post.categories.some((c) => activeCategories.includes(c)));
  // getBlogPosts sorts "-featured,-publishedAt", so index 0 IS the actual
  // featured post when the unfiltered list is shown — but a category
  // filter can (and often will) exclude it entirely, in which case index 0
  // is just the newest matching post, not an editorially featured one. It
  // still doesn't deserve the big hero-card treatment (implies "the
  // featured post", not "whatever sorted first"), so that layout is gated
  // on the post's own `featured` flag, not on array position.
  const [first, ...restAll] = posts;
  const featured = first?.featured ? first : undefined;
  const rest = featured ? restAll : posts;

  return (
    <>
      <main className="flex flex-col flex-1 bg-bg-base">
        {/* Header — copy left, photo bleeds to the viewport edge on the
            right with a left-edge fade into bg-base, matching Figma's
            hero-fade-left/hero-fade-bottom overlays (node 4577:330). */}
        <Reveal className="relative flex flex-col sm:flex-row items-center w-full min-h-[20rem] sm:min-h-[27.5rem] border-b border-border overflow-hidden">
          <div className="relative z-10 flex flex-col gap-4 items-start px-[var(--layout-padding-x)] py-10 sm:py-0 w-full sm:w-auto sm:max-w-[26rem]">
            {/* Breadcrumb + text-h-feature heading — same treatment as
                /shop's ShopHeader.tsx and every legal page, this hero was
                the one page missing both (its own bespoke photo-bleed
                layout predates that convention being established
                elsewhere). */}
            <p className="flex items-center gap-2 text-body-sm text-text-muted">
              <Link href="/" className="hover:text-brand transition-colors">Startseite</Link>
              <span>›</span>
              <span className="text-text-primary">Blog</span>
            </p>
            <p
              className="font-semibold text-display text-text-primary"
              style={{ fontFamily: "var(--font-lora)" }}
            >
              Blog
            </p>
            <p className="text-body text-text-muted">
              Gedanken, Methoden und Impulse für einen leichteren und klareren Alltag.
            </p>
            {/* Moved into the hero's own text column (was a separate full-
                width bar below the entire hero, including the photo) — on
                mobile especially (text stacks above the photo here), that
                pushed the filters below a full extra screen's worth of
                hero image before they were even visible. Living right
                under the description keeps them in view immediately, on
                every width, no scrolling past the photo needed. */}
            {allCategories.length > 1 && (
              <BlogCategoryFilter allCategories={allCategories} activeCategories={activeCategories} />
            )}
          </div>
          <div className="relative w-full sm:absolute sm:inset-y-0 sm:right-0 sm:w-[68%] h-56 sm:h-full">
            <Image alt="" src="/hero.png" fill sizes="(min-width: 640px) 68vw, 100vw" className="object-cover object-top" />
            <div className="hidden sm:block absolute inset-y-0 left-0 w-72 bg-gradient-to-r from-bg-base to-transparent" />
            <div className="absolute inset-x-0 bottom-0 h-16 bg-gradient-to-t from-bg-base to-transparent" />
          </div>
        </Reveal>

        {posts.length === 0 && (
          <p className="text-body text-text-muted w-full max-w-[80rem] mx-auto px-[var(--layout-padding-x)] pt-10">
            Keine Beiträge in dieser Kategorie gefunden.
          </p>
        )}

        {featured && (
          // -mt-8, not pt-10 — pulls the card up to slightly overlap the
          // hero section's bottom edge instead of sitting flush below it.
          // relative z-10 keeps it stacked above the hero's own photo.
          // key'd for the same reason as RevealGroup below — guards against
          // the same stuck-at-opacity-0 failure mode if a future filter
          // combination ever swaps in a *different* featured post without
          // an intervening moment where `featured` was falsy.
          <Reveal key={featured.id} delay={0.1} className="relative z-10 w-full px-[var(--layout-padding-x)] -mt-8 pb-4">
            <Link
              href={`/blog/${featured.slug}`}
              className="group grid grid-cols-1 sm:grid-cols-2 w-full max-w-[80rem] mx-auto rounded-md overflow-hidden bg-bg-muted transition-transform duration-300 hover:-translate-y-1"
            >
              <div className="relative w-full aspect-video sm:aspect-auto sm:h-full bg-bg-muted">
                {featured.thumbnail && (
                  <Image alt="" src={featured.thumbnail} fill sizes="(min-width: 640px) 40rem, 100vw" className="object-cover" />
                )}
              </div>
              <div className="flex flex-col justify-center gap-3 p-8 sm:p-12 min-w-0">
                <div className="flex flex-wrap items-center gap-x-2 gap-y-1 font-semibold text-text-muted text-body-sm uppercase tracking-wide">
                  <span className="whitespace-nowrap">{featured.categories.join(", ")}</span>
                  <span>•</span>
                  <span className="whitespace-nowrap">{featured.readTime} Min</span>
                  <span>•</span>
                  <span className="uppercase whitespace-nowrap">{formatDate(featured.publishedAt)}</span>
                </div>
                <p
                  className="font-semibold text-h-section text-text-primary"
                  style={{ fontFamily: "var(--font-lora)" }}
                >
                  {featured.title}
                </p>
                <p className="text-body text-text-muted line-clamp-3">{featured.excerpt}</p>
                <span className="flex items-center gap-1.5 font-bold text-body text-text-primary mt-1">
                  Zum Beitrag
                  <svg
                    viewBox="0 0 20 20"
                    className="size-4 transition-transform duration-200 group-hover:translate-x-1"
                    fill="none"
                    aria-hidden="true"
                  >
                    <path d="M4 10h12m0 0-5-5m5 5-5 5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                </span>
              </div>
            </Link>
          </Reveal>
        )}

        {rest.length > 0 && (
          // key'd on the rendered post set — RevealGroup's `whileInView`
          // only fires once per component instance (viewport.once=true),
          // and a category-filter change re-renders this same page
          // component in place (only `searchParams` differs, no full
          // remount). Since `rest.length > 0` stays true across most
          // filter transitions, RevealGroup itself never naturally
          // unmounts, so once it has already fired "show" for one
          // filter's list, freshly swapped-in RevealItems (new post ids)
          // mount into an already-settled parent that has no reason to
          // re-fire the reveal trigger — they were stuck at opacity 0
          // forever, reported as the list appearing blank after refiltering.
          // Forcing a remount on every distinct post set restarts
          // RevealGroup's viewport tracking from scratch each time.
          <RevealGroup
            key={rest.map((post) => post.id).join(",")}
            className="flex flex-col w-full max-w-[80rem] mx-auto px-[var(--layout-padding-x)] py-6 divide-y divide-border"
          >
            {rest.map((post) => (
              <RevealItem key={post.id} className="py-8 first:pt-0 last:pb-0">
                <Link href={`/blog/${post.slug}`} className="group flex flex-col sm:flex-row gap-6 items-start">
                  <div className="relative w-full sm:w-[18.75rem] aspect-video sm:aspect-[300/192] shrink-0 rounded-md overflow-hidden bg-bg-muted">
                    {post.thumbnail && (
                      <Image alt="" src={post.thumbnail} fill sizes="(min-width: 640px) 18.75rem, 100vw" className="object-cover" />
                    )}
                  </div>
                  <div className="flex flex-col gap-2 min-w-0 flex-1">
                    <div className="flex flex-wrap items-center gap-x-2 gap-y-1 font-semibold text-text-muted text-body-sm uppercase tracking-wide">
                      <span className="whitespace-nowrap">{post.categories.join(", ")}</span>
                      <span>•</span>
                      <span className="whitespace-nowrap">{post.readTime} Min</span>
                      <span>•</span>
                      <span className="uppercase whitespace-nowrap">{formatDate(post.publishedAt)}</span>
                    </div>
                    <p
                      className="font-semibold text-h-small text-text-primary"
                      style={{ fontFamily: "var(--font-lora)" }}
                    >
                      {post.title}
                    </p>
                    <p className="text-body text-text-muted">{post.excerpt}</p>
                    <span className="flex items-center gap-1.5 font-bold text-body-sm text-text-primary mt-1">
                      Zum Beitrag
                      <svg
                        viewBox="0 0 20 20"
                        className="size-3.5 transition-transform duration-200 group-hover:translate-x-1"
                        fill="none"
                        aria-hidden="true"
                      >
                        <path d="M4 10h12m0 0-5-5m5 5-5 5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                      </svg>
                    </span>
                  </div>
                </Link>
              </RevealItem>
            ))}
          </RevealGroup>
        )}

        <Newsletter
          title="Neue Impulse im richtigen Moment."
          description="Melde dich zum Newsletter an und erhalte regelmäßig Gedanken, Methoden und praktische Tipps."
        />
      </main>
      <Footer />
    </>
  );
}
