import Link from "next/link";
import Image from "next/image";
import type { ReactNode } from "react";
import { formatPrice, discountPercent } from "../lib/format";
import { effectiveTaxRate } from "../lib/cartTotals";
import { AddToCartInlineButton } from "./AddToCartInlineButton";
import { WishlistButton } from "./WishlistButton";
import { ProductName } from "./ProductName";
import type { Product } from "../lib/payload";

// Single shared card markup for every product grid (ProductGrid,
// RelatedProducts, MerklisteGrid) — these three used to each duplicate
// this JSX independently and had drifted (different image aspect ratios,
// a "Mehr erfahren" link present on some but not others, purchased/
// out-of-stock badges only on some). The title itself is now the card's
// only link (product.href, when set) — no separate "Mehr erfahren" CTA
// line, which is also what makes the card more compact than before.
// No "use client" — plain enough (no hooks/browser APIs of its own) to
// render from both ProductGrid's Server Component and RelatedProducts'/
// MerklisteGrid's Client Components.
export function ProductCard({
  product,
  defaultTaxRate,
  kleinunternehmer,
  wishlistEnabled,
  wishlistRevealOnHover = false,
  topLeftBadge,
  belowPrice,
  className = "",
}: {
  product: Product;
  defaultTaxRate: number;
  kleinunternehmer: boolean;
  wishlistEnabled: boolean;
  /** See WishlistButton's own doc: true for any grid where an unprompted
   * heart on every card would read as noise (ProductGrid, RelatedProducts);
   * false (default) for /konto/merkliste, where every card is already
   * wishlisted. */
  wishlistRevealOnHover?: boolean;
  /** Overrides the default Ausverkauft/discount pill — used by
   * MerklisteGrid for its "Gekauft am ..." badge. Pass `null` to render
   * no badge at all. */
  topLeftBadge?: ReactNode;
  /** Rendered directly under the price — e.g. ProductGrid's delivery-time
   * line. Omitted entirely by grids that don't have anything to say there
   * (RelatedProducts, MerklisteGrid), rather than every card carrying a
   * fixed slot for content only one of the three actually has. */
  belowPrice?: ReactNode;
  className?: string;
}) {
  const discount = discountPercent(product.price, product.compareAtPrice);
  const taxRate = effectiveTaxRate(product, defaultTaxRate);
  const fullyOutOfStock = product.variants.length > 0 ? product.variants.every((v) => v.outOfStock) : product.outOfStock;
  const anyLowStock = product.variants.length > 0 ? product.variants.some((v) => v.lowStock) : product.lowStock;

  return (
    // 6 direct grid rows (image / header / price / belowPrice / lowstock /
    // button) instead of the old flex column — a plain flex-1 spacer only
    // pins the button to the bottom of THIS card, it can't make the price
    // row start at the same Y as a row sibling whose header block is a
    // different height (e.g. a 2-line vs 1-line subline). grid-template-
    // rows: subgrid pulls in the row-tracks each caller's grid container
    // already declares (see ProductGrid.tsx's own comment) so every row is
    // genuinely shared/max'd across the row of cards — dynamic, no
    // line-clamp/truncation needed on the subline. gap-3 is used for every
    // row gap including after the image (was pt-4/1rem there before —
    // 0.25rem less, accepted for one consistent grid gap instead of mixed
    // margin/gap spacing).
    <div
      className={`group bg-bg-base border border-border rounded-md overflow-hidden grid [grid-template-rows:subgrid] [grid-row:span_6] gap-3 transition-transform duration-300 hover:-translate-y-1 ${className}`}
    >
      <div className="relative w-full aspect-[276/210] overflow-hidden">
        {/* Link wraps only the image, not the whole header — WishlistButton
            below is its own interactive element and sits as a sibling, not
            nested inside this Link (nested interactive elements are both
            invalid HTML and would fire navigation on a wishlist click). */}
        {product.href ? (
          <Link href={product.href} aria-label={product.name} className="absolute inset-0 z-0">
            <Image
              src={product.image}
              alt={product.name}
              fill
              sizes="(min-width: 1024px) 30vw, (min-width: 640px) 50vw, 100vw"
              className={`object-cover transition-transform duration-500 group-hover:scale-105 ${fullyOutOfStock ? "opacity-60" : ""}`}
            />
          </Link>
        ) : (
          <Image
            src={product.image}
            alt={product.name}
            fill
            sizes="(min-width: 1024px) 30vw, (min-width: 640px) 50vw, 100vw"
            className={`object-cover transition-transform duration-500 group-hover:scale-105 ${fullyOutOfStock ? "opacity-60" : ""}`}
          />
        )}
        {topLeftBadge !== undefined ? (
          topLeftBadge
        ) : fullyOutOfStock ? (
          <span className="absolute top-3 left-3 rounded-full bg-text-muted px-2.5 py-1 text-label font-bold text-bg-base">
            Ausverkauft
          </span>
        ) : (
          discount !== null && (
            <span className="absolute top-3 left-3 rounded-full bg-brand px-2.5 py-1 text-label font-bold text-text-primary">
              -{discount}%
            </span>
          )
        )}
        {wishlistEnabled && (
          <WishlistButton productId={product.numericId} className="absolute top-3 right-3" revealOnHover={wishlistRevealOnHover} />
        )}
      </div>

      <div className="flex flex-col gap-1 items-start w-full px-5">
        {product.categories.length > 0 && (
          <p className="text-label font-semibold text-text-muted uppercase tracking-wide">{product.categories.join(", ")}</p>
        )}
        {product.href ? (
          <Link
            href={product.href}
            className="font-semibold text-h4 text-text-primary w-full hover:text-brand transition-colors"
            style={{ fontFamily: "var(--font-lora)" }}
          >
            <ProductName name={product.name} />
          </Link>
        ) : (
          <p className="font-semibold text-h4 text-text-primary w-full" style={{ fontFamily: "var(--font-lora)" }}>
            <ProductName name={product.name} />
          </p>
        )}
        {product.subline && <p className="text-body-sm text-text-muted w-full">{product.subline}</p>}
      </div>

      <p className="flex items-baseline gap-1.5 px-5">
        {discount !== null && (
          <span className="text-label text-text-muted line-through">{formatPrice(product.compareAtPrice!)}</span>
        )}
        <span className="font-bold text-h4 text-text-primary">{formatPrice(product.price)}</span>
        {!kleinunternehmer && <span className="text-label text-text-muted">inkl. {taxRate}% MwSt.</span>}
      </p>

      <div className="px-5">{belowPrice}</div>

      {/* Always rendered, text conditional — an empty row still occupies
          its shared track (0-height unless a row sibling needs it), same
          reasoning as the price/header rows above. */}
      <p className="text-label font-bold text-warning px-5">{anyLowStock ? "Nur noch wenige verfügbar" : null}</p>

      {/* self-end pins the button to the bottom of this row even though
          the row itself is minmax(0,1fr) (see grid-auto-rows) and can be
          taller than the button — replaces the old flex-1 spacer. */}
      <div className="self-end px-5 pb-5 w-full">
        <AddToCartInlineButton
          id={product.id}
          numericId={product.numericId}
          outOfStock={product.outOfStock}
          maxQty={product.maxQty}
          variants={product.variants}
        />
      </div>
    </div>
  );
}
