/**
 * useCartTracking - React hook for cart analytics
 *
 * Integrates with your cart state to automatically track cart events.
 */

import { useCallback, useEffect, useRef } from 'react';

import { useAnalytics } from '../react-spa/analytics-setup';

import {
  trackCartAdd,
  trackCartRemove,
  trackCartUpdate,
  trackCartView,
  trackCheckoutStart,
  trackCartAbandonment,
  trackPromoCodeApply,
  type Cart,
} from './cart-analytics';
import type { Product } from './product-analytics';

// ─────────────────────────────────────────────────────────────────────────────
// Hook
// ─────────────────────────────────────────────────────────────────────────────

interface UseCartTrackingOptions {
  /** Track cart view automatically when cart changes */
  trackViewOnChange?: boolean;
  /** Track abandonment on page unload */
  trackAbandonmentOnUnload?: boolean;
}

export function useCartTracking(cart: Cart, options: UseCartTrackingOptions = {}) {
  const { trackViewOnChange = false, trackAbandonmentOnUnload = true } = options;
  const { client } = useAnalytics();
  const previousCartRef = useRef<Cart | null>(null);

  // Track cart view when cart contents change
  useEffect(() => {
    if (!trackViewOnChange) return;

    const prevItemCount = previousCartRef.current?.items.length ?? 0;
    const currItemCount = cart.items.length;

    // Only track if items actually changed
    if (prevItemCount !== currItemCount) {
      trackCartView(client, cart);
    }

    previousCartRef.current = cart;
  }, [client, cart, trackViewOnChange]);

  // Track abandonment on page unload
  useEffect(() => {
    if (!trackAbandonmentOnUnload) return;
    if (cart.items.length === 0) return;

    const handleUnload = () => {
      trackCartAbandonment(client, cart, 'browser_close');
    };

    window.addEventListener('beforeunload', handleUnload);
    return () => window.removeEventListener('beforeunload', handleUnload);
  }, [client, cart, trackAbandonmentOnUnload]);

  /**
   * Track item added to cart.
   */
  const trackAdd = useCallback(
    (product: Product, quantity: number) => {
      trackCartAdd(client, product, quantity, cart);
    },
    [client, cart],
  );

  /**
   * Track item removed from cart.
   */
  const trackRemove = useCallback(
    (product: Product, quantity: number) => {
      trackCartRemove(client, product, quantity, cart);
    },
    [client, cart],
  );

  /**
   * Track item quantity update.
   */
  const trackUpdate = useCallback(
    (product: Product, previousQuantity: number, newQuantity: number) => {
      trackCartUpdate(client, product, previousQuantity, newQuantity, cart);
    },
    [client, cart],
  );

  /**
   * Track cart page view.
   */
  const trackView = useCallback(() => {
    trackCartView(client, cart);
  }, [client, cart]);

  /**
   * Track checkout initiation.
   */
  const trackCheckout = useCallback(() => {
    trackCheckoutStart(client, cart);
  }, [client, cart]);

  /**
   * Track cart abandonment.
   */
  const trackAbandonment = useCallback(
    (reason?: 'navigation' | 'timeout' | 'browser_close') => {
      trackCartAbandonment(client, cart, reason);
    },
    [client, cart],
  );

  /**
   * Track promo code application.
   */
  const trackPromoCode = useCallback(
    (code: string, success: boolean, discount?: number, errorMessage?: string) => {
      trackPromoCodeApply(client, code, success, discount, errorMessage);
    },
    [client],
  );

  return {
    trackAdd,
    trackRemove,
    trackUpdate,
    trackView,
    trackCheckout,
    trackAbandonment,
    trackPromoCode,
  };
}

// ─────────────────────────────────────────────────────────────────────────────
// Cart Provider Integration Example
// ─────────────────────────────────────────────────────────────────────────────

/**
 * @example
 * ```tsx
 * // CartProvider.tsx - Integrate tracking with your cart state
 *
 * import { createContext, useContext, useState, useMemo } from 'react';
 * import { useCartTracking } from './use-cart-tracking';
 *
 * const CartContext = createContext(null);
 *
 * export function CartProvider({ children }) {
 *   const [cart, setCart] = useState({ items: [], subtotal: 0, currency: 'USD' });
 *   const tracking = useCartTracking(cart, {
 *     trackAbandonmentOnUnload: true,
 *   });
 *
 *   const addItem = (product, quantity) => {
 *     setCart(prev => {
 *       const newCart = addToCart(prev, product, quantity);
 *       // Track after state update
 *       tracking.trackAdd(product, quantity);
 *       return newCart;
 *     });
 *   };
 *
 *   const removeItem = (product) => {
 *     const item = cart.items.find(i => i.id === product.id);
 *     if (!item) return;
 *
 *     setCart(prev => {
 *       const newCart = removeFromCart(prev, product.id);
 *       tracking.trackRemove(product, item.quantity);
 *       return newCart;
 *     });
 *   };
 *
 *   const updateQuantity = (product, newQuantity) => {
 *     const item = cart.items.find(i => i.id === product.id);
 *     if (!item) return;
 *
 *     const previousQuantity = item.quantity;
 *
 *     setCart(prev => {
 *       const newCart = updateCartItem(prev, product.id, newQuantity);
 *       tracking.trackUpdate(product, previousQuantity, newQuantity);
 *       return newCart;
 *     });
 *   };
 *
 *   const startCheckout = () => {
 *     tracking.trackCheckout();
 *     // Navigate to checkout...
 *   };
 *
 *   const applyPromoCode = async (code) => {
 *     try {
 *       const result = await validatePromoCode(code);
 *       setCart(prev => applyDiscount(prev, result.discount));
 *       tracking.trackPromoCode(code, true, result.discount);
 *     } catch (error) {
 *       tracking.trackPromoCode(code, false, undefined, error.message);
 *     }
 *   };
 *
 *   const value = useMemo(() => ({
 *     cart,
 *     addItem,
 *     removeItem,
 *     updateQuantity,
 *     startCheckout,
 *     applyPromoCode,
 *   }), [cart]);
 *
 *   return (
 *     <CartContext.Provider value={value}>
 *       {children}
 *     </CartContext.Provider>
 *   );
 * }
 *
 * export const useCart = () => useContext(CartContext);
 * ```
 */
