import React, { useEffect, useState } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';
import toast from 'react-hot-toast';
import { useAuth } from '../context/AuthContext';
import { isVariantAvailable, type VariantKind } from '../lib/variantStock';
import ProductImage from './ProductImage';

export interface CatalogProductVariant {
  id: number;
  name: string;
  volume: string;
  volumeMl: number;
  currentPrice: number;
  kind?: VariantKind;
  stock?: number;
}

export interface CatalogProductBadge {
  name: string;
  color?: string | null;
}

export interface CatalogProduct {
  id: number;
  slug: string;
  name: string;
  description?: string;
  brandName: string;
  primaryImage: string;
  stock: number;
  sortOrder?: number;
  badges?: CatalogProductBadge[];
  variants: CatalogProductVariant[];
}

interface WishlistItem {
  id: number;
  productId: number;
}

interface CatalogProductCardProps {
  product: CatalogProduct;
  variants?: CatalogProductVariant[];
  availableCount?: number;
  wishlistActive: boolean;
  wishlistLoading?: boolean;
  onWishlist: () => void;
}

interface CatalogProductGridProps {
  products: CatalogProduct[];
  variantsForProduct?: (product: CatalogProduct) => CatalogProductVariant[];
  className?: string;
  containerRef?: React.Ref<HTMLDivElement>;
}

export type CatalogSortMode = 'sort_id' | 'newest' | 'cheapest' | 'most_expensive';

export const CATALOG_PRODUCT_GRID_CLASS = 'grid grid-cols-2 gap-x-2.5 gap-y-9 sm:grid-cols-3 sm:gap-x-4 lg:grid-cols-4 xl:grid-cols-5 xl:gap-x-[18px] xl:gap-y-11';

export const formatProductCount = (count: number) => `${count} ${count === 1 ? 'produkt' : count >= 2 && count <= 4 ? 'produkty' : 'produktů'}`;

const money = (price: number) => new Intl.NumberFormat('cs-CZ', {
  style: 'currency',
  currency: 'CZK',
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
}).format(price);

const lowestPrice = (product: CatalogProduct) => {
  const availableVariants = product.variants.filter((variant) => isVariantAvailable(variant, product.stock));
  const pricePool = availableVariants.length ? availableVariants : product.variants;
  return pricePool.length
    ? Math.min(...pricePool.map((variant) => Number(variant.currentPrice)))
    : Number.POSITIVE_INFINITY;
};

export const sortCatalogProducts = (products: CatalogProduct[], sortBy: CatalogSortMode) => [...products].sort((a, b) => {
  if (sortBy === 'newest') return b.id - a.id;
  if (sortBy === 'cheapest') return lowestPrice(a) - lowestPrice(b);
  if (sortBy === 'most_expensive') return lowestPrice(b) - lowestPrice(a);
  return (a.sortOrder ?? a.id) - (b.sortOrder ?? b.id);
});

export function CatalogToolbar({ count, sortBy, onSortChange }: { count: number; sortBy: CatalogSortMode; onSortChange: (sortBy: CatalogSortMode) => void }) {
  return (
    <div className="mb-7 flex items-center justify-between gap-3 border-t border-luxury-light/15 pt-5 text-xs text-luxury-light/45">
      <span>{formatProductCount(count)}</span>
      <label className="flex items-center gap-2">
        <span className="hidden sm:inline">Řazení</span>
        <select
          value={sortBy}
          onChange={(event) => onSortChange(event.target.value as CatalogSortMode)}
          className="h-10 rounded-none border border-luxury-light/15 bg-luxury-dark px-3 pr-8 text-xs text-luxury-light outline-none focus:border-luxury-gold"
        >
          <option value="sort_id">Výchozí</option>
          <option value="newest">Nejnovější</option>
          <option value="cheapest">Nejlevnější</option>
          <option value="most_expensive">Nejdražší</option>
        </select>
      </label>
    </div>
  );
}

export function CatalogProductCard({
  product,
  variants = product.variants,
  availableCount,
  wishlistActive,
  wishlistLoading = false,
  onWishlist,
}: CatalogProductCardProps) {
  const availableVariants = variants.filter((variant) => isVariantAvailable(variant, product.stock));
  const resolvedAvailableCount = availableCount ?? availableVariants.length;
  const pricePool = availableVariants.length ? availableVariants : variants;
  const fromPrice = pricePool.length ? Math.min(...pricePool.map((variant) => Number(variant.currentPrice))) : 0;
  const variantLabel = resolvedAvailableCount === 1
    ? 'dostupná varianta'
    : resolvedAvailableCount >= 2 && resolvedAvailableCount <= 4
      ? 'dostupné varianty'
      : 'dostupných variant';

  return (
    <article className="group relative min-w-0">
      <button
        type="button"
        onClick={onWishlist}
        disabled={wishlistLoading}
        aria-label={wishlistActive ? `${product.name} je v oblíbených` : `Přidat ${product.name} do oblíbených`}
        className={`absolute right-3 top-3 z-20 grid h-10 w-10 place-items-center rounded-full border shadow-lg backdrop-blur-sm transition-all hover:-translate-y-0.5 ${wishlistActive ? 'border-luxury-gold/70 bg-luxury-gold/15 text-luxury-gold' : 'border-white/15 bg-black/55 text-white hover:border-luxury-gold/60 hover:text-luxury-gold'}`}
      >
        <HeartIcon filled={wishlistActive} />
      </button>

      <div className="relative overflow-hidden bg-[#0d0d0d]">
        <Link href={`/product/${product.slug}`} className="relative block aspect-[2/3] overflow-hidden" aria-label={`Zobrazit ${product.name}`}>
          {product.badges && product.badges.length > 0 && (
            <span className="absolute left-3 top-3 z-10 flex max-w-[calc(100%-68px)] flex-wrap gap-1.5">
              {product.badges.map((badge, index) => (
                <span
                  key={`${badge.name}-${index}`}
                  className="px-2.5 py-1.5 text-[9px] font-bold uppercase tracking-[0.09em]"
                  style={{ backgroundColor: badge.color || 'rgba(255,255,255,.92)', color: badge.color ? '#fff' : '#141414' }}
                >
                  {badge.name}
                </span>
              ))}
            </span>
          )}
          <ProductImage src={product.primaryImage} alt={product.name} className="h-full w-full object-cover transition-transform duration-700 ease-out group-hover:scale-[1.025]" />
        </Link>
        <Link href={`/product/${product.slug}`} className="absolute bottom-3 left-3 right-3 hidden min-h-12 translate-y-16 items-center justify-between bg-white/95 px-4 text-xs font-bold text-[#151515] transition-all duration-300 hover:bg-luxury-gold group-hover:translate-y-0 md:flex">
          <span>Zobrazit produkt</span>
          <ProductArrowIcon />
        </Link>
      </div>

      <div className="px-px pt-4">
        <p className="text-[10px] font-semibold uppercase tracking-[0.12em] text-luxury-light/45">{product.brandName}</p>
        <h3 className="my-1.5 min-h-[2.5em] text-sm font-semibold leading-[1.25] text-luxury-light sm:text-[15px]">
          <Link href={`/product/${product.slug}`} className="hover:text-luxury-gold">{product.name}</Link>
        </h3>
        <div className="flex items-baseline justify-between gap-2">
          <p className="whitespace-nowrap text-[13px] font-bold text-luxury-gold sm:text-sm">od {money(fromPrice)}</p>
          <p className="text-right text-[10px] text-luxury-light/45 sm:text-[11px]">{resolvedAvailableCount} {variantLabel}</p>
        </div>
      </div>
    </article>
  );
}

export function CatalogProductGrid({ products, variantsForProduct, className = CATALOG_PRODUCT_GRID_CLASS, containerRef }: CatalogProductGridProps) {
  const [wishlistItems, setWishlistItems] = useState<Record<number, number>>({});
  const [wishlistLoading, setWishlistLoading] = useState<Record<number, boolean>>({});
  const { isAuthenticated } = useAuth();
  const router = useRouter();

  useEffect(() => {
    if (!isAuthenticated) {
      setWishlistItems({});
      return;
    }

    const loadWishlist = async () => {
      try {
        const response = await fetch('/api/wishlist', { credentials: 'include' });
        if (!response.ok) return;
        const items = await response.json() as WishlistItem[];
        setWishlistItems(Object.fromEntries(items.map((item) => [item.productId, item.id])));
      } catch {
        // Product browsing remains available if wishlist synchronization fails.
      }
    };

    void loadWishlist();
  }, [isAuthenticated]);

  const handleWishlist = async (product: CatalogProduct, variant: CatalogProductVariant | undefined) => {
    if (!isAuthenticated) {
      toast.error('Přihlaste se pro přidání do oblíbených');
      void router.push('/login');
      return;
    }
    if (!variant || wishlistLoading[product.id]) return;
    if (wishlistItems[product.id]) {
      toast('Produkt už máte v oblíbených');
      return;
    }

    try {
      setWishlistLoading((current) => ({ ...current, [product.id]: true }));
      const response = await fetch('/api/wishlist', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({ productId: product.id, variantId: variant.id }),
      });
      if (response.ok || response.status === 409) {
        setWishlistItems((current) => ({ ...current, [product.id]: current[product.id] || -1 }));
        toast.success(response.status === 409 ? 'Produkt už máte v oblíbených' : 'Přidáno do oblíbených');
      } else {
        toast.error('Produkt se nepodařilo přidat do oblíbených');
      }
    } finally {
      setWishlistLoading((current) => ({ ...current, [product.id]: false }));
    }
  };

  return (
    <div className={className} ref={containerRef}>
      {products.map((product) => {
        const variants = variantsForProduct?.(product) ?? product.variants;
        const availableVariants = variants.filter((variant) => isVariantAvailable(variant, product.stock));
        const wishlistVariant = [...availableVariants]
          .sort((a, b) => Number(a.currentPrice) - Number(b.currentPrice))[0] || variants[0];

        return (
          <CatalogProductCard
            key={product.id}
            product={product}
            variants={variants}
            availableCount={availableVariants.length}
            wishlistActive={Boolean(wishlistItems[product.id])}
            wishlistLoading={Boolean(wishlistLoading[product.id])}
            onWishlist={() => handleWishlist(product, wishlistVariant)}
          />
        );
      })}
    </div>
  );
}

function HeartIcon({ filled }: { filled: boolean }) {
  return <svg className={`h-5 w-5 ${filled ? 'fill-current' : ''}`} fill={filled ? 'currentColor' : 'none'} stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.7} 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.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78Z" /></svg>;
}

function ProductArrowIcon() {
  return <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.8} d="M5 12h14m-5-5 5 5-5 5" /></svg>;
}
