"use client";

import { Button, Spinner, toast } from "@heroui/react";
import Image from "next/image";
import Link from "next/link";
import { useId, useState, useCallback } from "react";
import { useConvexAuth, useMutation } from "convex/react";
import { api } from "../../../../../convex/_generated/api";
import type { Id } from "../../../../../convex/_generated/dataModel";

/** Renders a single star (filled or half). */
function StarIcon({ filled, half, gradientId }: { filled?: boolean; half?: boolean; gradientId?: string }) {
  if (half && gradientId) {
    return (
      <svg className="size-[18px] text-[var(--warm)]" viewBox="0 0 24 24" fill="currentColor" aria-hidden>
        <defs>
          <linearGradient id={gradientId} x1="0" x2="1" y1="0" y2="0">
            <stop offset="50%" stopColor="currentColor" />
            <stop offset="50%" stopColor="transparent" />
          </linearGradient>
        </defs>
        <path fill={`url(#${gradientId})`} d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
      </svg>
    );
  }
  return (
    <svg className="size-[18px] text-[var(--warm)]" viewBox="0 0 24 24" fill={filled ? "currentColor" : "none"} stroke="currentColor" strokeWidth="1.5" aria-hidden>
      <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
    </svg>
  );
}

function HeartIcon({ className }: { className?: string }) {
  return (
    <svg
      className={className}
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
      strokeLinecap="round"
      strokeLinejoin="round"
      aria-hidden
    >
      <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
    </svg>
  );
}

export type ProductCardProps = {
  /** Brand name (e.g. "Freshpet"). */
  brand: string;
  /** Full product name (e.g. "Dognation Turkey Bacon Grain-Free Fresh Dog Treats, 3-oz bag, case of 6"). */
  name: string;
  /** Current price as display string (e.g. "$41.94"). */
  price: string;
  /** Optional compare-at / original price for sale display. */
  compareAtPrice?: string;
  /** Image URL. */
  imageSrc: string;
  /** Alt = {Product Name} – {Key Attribute}; used for accessibility and SEO. */
  imageAlt: string;
  /** Product URL; same for image link and name link. */
  url: string;
  /** Rating 0–5 (e.g. 4.5). */
  rating: number;
  /** Number of reviews for display and aria-label. */
  reviewCount: number;
  /** Optional badge: "new" (Amber Cream) or "sale" (Coral Blush). */
  badge?: "new" | "sale";
  /** Product ID for wishlist. When absent, save button uses placeholder behavior. */
  productId?: string;
  /** Variant ID for wishlist. */
  variantId?: string;
  /** When true, the wishlist action button is hidden entirely. */
  hideWishlistAction?: boolean;
};

/** Renders star row from rating (e.g. 4.5 → 4 full + 1 half). */
function StarRow({ rating }: { rating: number }) {
  const id = useId();
  const full = Math.floor(rating);
  const hasHalf = rating % 1 >= 0.25 && rating % 1 < 0.75;
  const stars = [];
  for (let i = 0; i < full; i++) stars.push(<StarIcon key={i} filled />);
  if (hasHalf) stars.push(<StarIcon key="half" half gradientId={id.replace(/:/g, "")} />);
  return <div className="flex items-center gap-0.5">{stars}</div>;
}

export function ProductCard({
  brand,
  name,
  price,
  compareAtPrice,
  imageSrc,
  imageAlt,
  url,
  rating,
  reviewCount,
  badge,
  productId,
  variantId,
  hideWishlistAction,
}: ProductCardProps) {
  const { isAuthenticated } = useConvexAuth();
  const addToWishlist = useMutation(api.wishlists.add);
  const [isSaving, setIsSaving] = useState(false);
  const ratingLabel = `Rated ${rating} out of 5${reviewCount ? ` (${reviewCount} reviews)` : ""}`;

  const handleSave = useCallback(async () => {
    if (!productId) return;
    if (!isAuthenticated) {
      toast.info("Sign in to save items to your wishlist");
      return;
    }
    setIsSaving(true);
    try {
      const result = await addToWishlist({
        productId: productId as Id<"products">,
        variantId: variantId as Id<"productVariants"> | undefined,
      });
      if (result.alreadyExisted) {
        toast.info("This item is already in your wishlist");
      } else {
        toast.success("Added to your wishlist");
      }
    } finally {
      setIsSaving(false);
    }
  }, [productId, variantId, isAuthenticated, addToWishlist]);

  return (
    <article
      className="group relative flex flex-col rounded-[var(--radius)] border border-[var(--border)] bg-[var(--surface)] p-5 shadow-[0_2px_8px_rgba(56,169,159,0.1)] transition-[transform,box-shadow] duration-[var(--transition-base)] hover:-translate-y-1 hover:shadow-[0_8px 24px_rgba(56,169,159,0.15)]"
    >
      {badge && (
        <div className="absolute right-4 top-4 z-10">
          <span
            className={
              badge === "new"
                ? "rounded-lg bg-[#fde8c8] px-3 py-1.5 text-[11px] font-bold uppercase tracking-wider text-[#b36a10]"
                : "rounded-lg bg-[#fce0da] px-3 py-1.5 text-[11px] font-bold uppercase tracking-wider text-[var(--coral)]"
            }
          >
            {badge === "new" ? "New" : "Sale"}
          </span>
        </div>
      )}

      <Link href={url} className="relative mb-6 block aspect-square overflow-hidden">
        <Image
          src={imageSrc}
          alt={imageAlt}
          fill
          sizes="(max-width: 640px) 100vw, (max-width: 768px) 50vw, (max-width: 1024px) 33vw, 25vw"
          className="object-contain mix-blend-multiply transition-transform duration-500 group-hover:scale-110"
          loading="lazy"
        />
      </Link>

      <div className="mb-2 flex items-center gap-1" role="img" aria-label={ratingLabel}>
        <StarRow rating={rating} />
        <span className="text-xs font-semibold text-[var(--muted)]">({reviewCount})</span>
      </div>

      <h3 className="mb-6 text-sm font-medium leading-snug text-[var(--foreground)]">
        <Link href={url} className="focus:outline-none focus:ring-2 focus:ring-[var(--accent)] focus:ring-offset-2 focus:ring-offset-[var(--surface)] rounded">
          <span className="font-[family-name:var(--font-fraunces)] font-bold block text-[var(--foreground)] mb-0.5">
            {brand}
          </span>
          {name}
        </Link>
      </h3>

      {compareAtPrice && (
            <s className="mr-2 text-[var(--muted)] text-sm" aria-label="Original price">
              {compareAtPrice}
            </s>
          )}

      <div className="mt-auto w-full h-px bg-[var(--separator)] mb-6" />

      <div className="flex items-center justify-between">
        <p className="text-lg font-semibold text-[var(--brand-dark)]">
          <strong>{price}</strong>
        </p>
        {!hideWishlistAction && (
          <>
            <Button
              variant="ghost"
              isIconOnly
              size="md"
              aria-label={`Save ${name} to wishlist`}
              aria-busy={isSaving}
              className="flex shrink-0 text-[var(--brand-dark)] hover:opacity-80 md:hidden"
              isPending={isSaving}
              onPress={handleSave}
            >
              {isSaving ? (
                <Spinner size="sm" color="current" />
              ) : (
                <HeartIcon className="size-5" />
              )}
            </Button>
            <Button
              variant="ghost"
              size="md"
              aria-label={`Save ${name} to wishlist`}
              aria-busy={isSaving}
              className="hidden min-w-0 font-sans text-sm font-medium text-[var(--brand-dark)] hover:opacity-80 md:flex w-full lg:w-auto"
              isPending={isSaving}
              onPress={handleSave}
            >
              {isSaving ? (
                <>
                  <Spinner size="sm" color="current" className="shrink-0" />
                  Saving
                </>
              ) : (
                <>
                  <HeartIcon className="size-5 shrink-0" />
                  Save
                </>
              )}
            </Button>
          </>
        )}
      </div>
    </article>
  );
}
