"use client";
import { useEffect, useRef, useState, useCallback } from "react";
import ProductThumb from "@/app/components/cards/product-thumb";

const LIMIT = 10;

export default function ProductGrid({ initialProducts = [], query = {} }: any) {
  const [products, setProducts] = useState<any[]>(initialProducts);
  const [loading, setLoading] = useState(false);
  const [hasMore, setHasMore] = useState(true);

  const pageRef = useRef(1);
  const loaderRef = useRef<HTMLDivElement | null>(null);
  const requestLock = useRef(false);
  const abortRef = useRef<AbortController | null>(null);

  // stable reference for loadMore (fixes eslint + safari observer)
  const loadMoreRef = useRef<() => void>(() => {});

  // Reset when filters change
  useEffect(() => {
    setProducts(initialProducts ?? []);
    setHasMore(true);
    pageRef.current = 1;
  }, [initialProducts, query]);

  const loadMore = useCallback(async () => {
    if (requestLock.current || !hasMore) return;

    requestLock.current = true;
    setLoading(true);

    abortRef.current?.abort();
    abortRef.current = new AbortController();

    try {
      const nextPage = pageRef.current + 1;

      const params = new URLSearchParams({
        ...query,
        page: String(nextPage),
        limit: String(LIMIT),
      });

      const res = await fetch(`/api/products?${params}`, {
        signal: abortRef.current.signal,
        cache: "no-store", // Safari caching fix
      });

      if (!res.ok) throw new Error("Failed to fetch");

      const data = await res.json();
      const newProducts = Array.isArray(data?.products) ? data.products : [];

      if (newProducts.length === 0) {
        setHasMore(false);
        return;
      }

      setProducts((prev) => {
        const merged = [...prev, ...newProducts];

        // remove duplicates
        return Array.from(new Map(merged.map((p) => [p.id, p])).values());
      });

      pageRef.current = nextPage;

      if (newProducts.length < LIMIT) {
        setHasMore(false);
      }
    } catch (err: any) {
      if (err.name !== "AbortError") {
        console.error("Load more error:", err);
      }
    } finally {
      requestLock.current = false;
      setLoading(false);
    }
  }, [query, hasMore]);

  // keep loadMoreRef updated
  useEffect(() => {
    loadMoreRef.current = loadMore;
  }, [loadMore]);

  // Safari-safe IntersectionObserver
  useEffect(() => {
    const loader = loaderRef.current;
    if (!loader) return;

    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          loadMoreRef.current();
        }
      },
      {
        rootMargin: "600px",
        threshold: 0.1,
      },
    );

    observer.observe(loader);

    // Safari fallback if observer doesn't trigger
    const rect = loader.getBoundingClientRect();
    if (rect.top < window.innerHeight) {
      loadMoreRef.current();
    }

    return () => observer.disconnect();
  }, []);

  return (
    <>
      <div className="grid grid-cols-2 gap-4 md:gap-16 lg:grid-cols-3 xl:gap-24">
        {products?.length ? (
          products.map((product: any, index: number) => (
            <ProductThumb
              key={product.id}
              image={product.image}
              hoverImg={product.hover_image}
              title={product.product_name}
              price={product.price}
              url={`/product/${product.slug}`}
              designHouse={product?.design_house?.name}
              pid={product.id}
              showLikeBtn
              priority={index < 6}
            />
          ))
        ) : (
          <div className="col-span-full">
            <div className="mx-auto flex pt-20 pb-8 w-full flex-col items-center justify-center gap-2 md:w-1/2">
              <h1 className="headingh4 text-center">
                More products are waiting!
              </h1>
              <p className="text-sm">
                Try different filters or search terms to discover more products.
              </p>
            </div>
          </div>
        )}
      </div>

      <div ref={loaderRef} className="flex justify-center py-10">
        {loading && (
          <p className="text-sm text-gray-500">Loading more products...</p>
        )}

        {!hasMore && products?.length >=0 && (
          <p className="text-sm text-gray-900 hidden">
            Discover more by exploring other filters.
          </p>
        )}
      </div>
    </>
  );
}
