/**
 * CompareContext
 * --------------
 * Lightweight, app-scoped store for the storefront "Compare" feature.
 *
 * Shoppers can click a compare toggle on any product card to add that
 * product to a floating CompareDrawer. The drawer lets them view a
 * side-by-side specs table and request a quote for the selected items.
 *
 * Design notes:
 *   - State is kept in React context rather than URL / localStorage to keep
 *     the MVP simple. Selections persist for the current session only.
 *   - We cap the list at 4 items — that's as many as the comparison table
 *     can render comfortably on desktop without horizontal scroll pain.
 *   - We intentionally store only the lightweight ProductCardData shape so
 *     any listing (shop grid, category page, search results) can push into
 *     the same store without re-fetching the heavier detail payload. The
 *     drawer will lazy-load full specs on demand.
 */

import {
  createContext,
  useCallback,
  useContext,
  useMemo,
  useState,
  ReactNode,
} from "react";
import type { ProductCardData } from "@/components/shop/ProductCard";

export const COMPARE_LIMIT = 4;

interface CompareContextValue {
  items: ProductCardData[];
  isOpen: boolean;
  toggle: (product: ProductCardData) => void;
  add: (product: ProductCardData) => { ok: boolean; reason?: string };
  remove: (productId: number) => void;
  clear: () => void;
  has: (productId: number) => boolean;
  openDrawer: () => void;
  closeDrawer: () => void;
}

const CompareContext = createContext<CompareContextValue | null>(null);

export function CompareProvider({ children }: { children: ReactNode }) {
  const [items, setItems] = useState<ProductCardData[]>([]);
  const [isOpen, setIsOpen] = useState(false);

  const has = useCallback(
    (productId: number) => items.some((p) => p.id === productId),
    [items],
  );

  const add = useCallback(
    (product: ProductCardData) => {
      if (items.some((p) => p.id === product.id)) {
        return { ok: false, reason: "already_added" as const };
      }
      if (items.length >= COMPARE_LIMIT) {
        return { ok: false, reason: "limit_reached" as const };
      }
      setItems((prev) => [...prev, product]);
      return { ok: true };
    },
    [items],
  );

  const remove = useCallback((productId: number) => {
    setItems((prev) => prev.filter((p) => p.id !== productId));
  }, []);

  const toggle = useCallback(
    (product: ProductCardData) => {
      if (items.some((p) => p.id === product.id)) {
        remove(product.id);
      } else {
        add(product);
      }
    },
    [items, add, remove],
  );

  const clear = useCallback(() => setItems([]), []);
  const openDrawer = useCallback(() => setIsOpen(true), []);
  const closeDrawer = useCallback(() => setIsOpen(false), []);

  const value = useMemo<CompareContextValue>(
    () => ({
      items,
      isOpen,
      toggle,
      add,
      remove,
      clear,
      has,
      openDrawer,
      closeDrawer,
    }),
    [items, isOpen, toggle, add, remove, clear, has, openDrawer, closeDrawer],
  );

  return <CompareContext.Provider value={value}>{children}</CompareContext.Provider>;
}

export function useCompare(): CompareContextValue {
  const ctx = useContext(CompareContext);
  if (!ctx) {
    throw new Error("useCompare must be used within a CompareProvider");
  }
  return ctx;
}