'use client';

import React, { createContext, useContext, useEffect, useState, useCallback } from 'react';
import { Product } from '@/types/woocommerce';
import {
  fetchStoreCart,
  addStoreCartItem,
  updateStoreCartItem,
  removeStoreCartItem,
} from '@/lib/store-api';
import { trackAddToCart, trackRemoveFromCart } from '@/lib/tracking';
import { normalizeVariationLabel } from '@/lib/format';

export interface CartItemOptions {
  size?: string;
  variationId?: number;
  attributes?: Record<string, string>;
  price?: number;
  regularPrice?: number;
  image?: string;
}

export interface PickProductState {
  product: Product;
  buyNow: boolean;
}

export interface LocalCartItem {
  id: number;
  key: string;
  name: string;
  brand: string;
  price: number;
  regularPrice: number;
  image: string;
  quantity: number;
  slug: string;
  size?: string;
  variationId?: number;
  attributes?: Record<string, string>;
}

interface CartContextType {
  cart: LocalCartItem[];
  itemCount: number;
  subtotal: number;
  savings: number;
  isCartOpen: boolean;
  toastMessage: string | null;
  pickProduct: PickProductState | null;
  openCart: () => void;
  closeCart: () => void;
  openPickSize: (product: Product, buyNow?: boolean) => void;
  closePickSize: () => void;
  quickAdd: (product: Product, buyNow?: boolean, preferredSize?: string | null) => void;
  pickSize: (size: string) => void;
  addToCart: (
    product: Product,
    quantity?: number,
    skipDrawer?: boolean,
    options?: CartItemOptions
  ) => Promise<void>;
  setQuantity: (id: number, quantity: number) => Promise<void>;
  removeItem: (id: number) => Promise<void>;
  clearCart: () => void;
  showToast: (message: string) => void;
}

const CartContext = createContext<CartContextType | undefined>(undefined);

const LOCAL_STORAGE_KEY = 'rb_local_cart_items';

export function CartProvider({ children }: { children: React.ReactNode }) {
  const [cart, setCart] = useState<LocalCartItem[]>([]);
  const [isCartOpen, setIsCartOpen] = useState<boolean>(false);
  const [toastMessage, setToastMessage] = useState<string | null>(null);
  const [isLoaded, setIsLoaded] = useState<boolean>(false);

  // Load cart from LocalStorage on mount
  useEffect(() => {
    try {
      const stored = localStorage.getItem(LOCAL_STORAGE_KEY);
      if (stored) {
        setCart(JSON.parse(stored));
      }
    } catch (e) {}
    setIsLoaded(true);
  }, []);

  // Save to LocalStorage whenever cart changes
  useEffect(() => {
    if (!isLoaded) return;
    try {
      localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(cart));
    } catch (e) {}
  }, [cart, isLoaded]);

  // Lock body scroll when cart drawer is open
  useEffect(() => {
    if (isCartOpen) {
      document.body.classList.add('cd-lock');
    } else {
      document.body.classList.remove('cd-lock');
    }
  }, [isCartOpen]);

  const showToast = useCallback((msg: string) => {
    setToastMessage(msg);
    setTimeout(() => {
      setToastMessage((current) => (current === msg ? null : current));
    }, 2800);
  }, []);

  const [pickProduct, setPickProduct] = useState<PickProductState | null>(null);

  const openCart = useCallback(() => setIsCartOpen(true), []);
  const closeCart = useCallback(() => {
    setIsCartOpen(false);
    setPickProduct(null);
  }, []);

  const openPickSize = useCallback((product: Product, buyNow = false) => {
    setPickProduct({ product, buyNow });
    setIsCartOpen(true);
  }, []);

  const closePickSize = useCallback(() => {
    setPickProduct(null);
  }, []);

  const addToCart = useCallback(
    async (
      product: Product,
      quantity = 1,
      skipDrawer = false,
      options?: CartItemOptions
    ) => {
      const selectedSize = options?.size;
      const variationId = options?.variationId;
      const selectedAttrs = options?.attributes;

      const normalizedAttrs: Record<string, string> | undefined =
        selectedAttrs && typeof selectedAttrs === 'object'
          ? Object.entries(selectedAttrs).reduce<Record<string, string>>((acc, [k, v]) => {
              if (v && String(v).toLowerCase() !== 'one') {
                acc[normalizeVariationLabel(k)] = String(v).trim();
              }
              return acc;
            }, {})
          : undefined;

      const attrKey = normalizedAttrs ? JSON.stringify(normalizedAttrs) : '';

      const matchedVar =
        options?.variationId
          ? product.variations?.find((v) => v.id === options.variationId)
          : selectedSize && product.variations
          ? product.variations.find((v) =>
              v.attributes?.some((a) => {
                const opt = String(a.option || '').toLowerCase();
                const sel = String(selectedSize).toLowerCase();
                return opt === sel || opt.includes(sel) || sel.includes(opt);
              })
            )
          : null;

      const effectiveVariationId = variationId ?? matchedVar?.id;
      const effectivePrice = options?.price ?? matchedVar?.price ?? product.price;
      const effectiveRegularPrice = options?.regularPrice ?? matchedVar?.regularPrice ?? product.regularPrice;
      const effectiveImage = options?.image ?? matchedVar?.image ?? product.image;

      setCart((prev) => {
        const existingIndex = prev.findIndex(
          (i) =>
            i.id === product.id &&
            i.size === selectedSize &&
            i.variationId === effectiveVariationId &&
            JSON.stringify(i.attributes || {}) === attrKey
        );
        if (existingIndex > -1) {
          const updated = [...prev];
          updated[existingIndex].quantity += quantity;
          return updated;
        } else {
          const newItem: LocalCartItem = {
            id: product.id,
            key: `cart_${product.id}_${effectiveVariationId || '0'}_${selectedSize || 'def'}_${attrKey}_${Date.now()}`,
            name: product.name,
            brand: product.brand,
            price: effectivePrice,
            regularPrice: effectiveRegularPrice,
            image: effectiveImage,
            quantity: quantity,
            slug: product.slug,
            size: selectedSize,
            variationId: effectiveVariationId,
            attributes: normalizedAttrs,
          };
          return [...prev, newItem];
        }
      });

      showToast(`Added ${quantity}× “${product.name.slice(0, 24)}…” to cart`);

      trackAddToCart({ ...product, price: effectivePrice }, quantity);

      if (!skipDrawer) {
        setIsCartOpen(true);
      }

      // Background Store API sync
      addStoreCartItem(product.id, quantity).catch(() => {});
    },
    [showToast]
  );

  const setQuantity = useCallback(async (id: number, quantity: number) => {
    let itemKey = '';
    setCart((prev) => {
      if (quantity <= 0) {
        return prev.filter((i) => i.id !== id);
      }
      return prev.map((i) => {
        if (i.id === id) {
          itemKey = i.key;
          return { ...i, quantity };
        }
        return i;
      });
    });

    if (itemKey) {
      if (quantity <= 0) {
        removeStoreCartItem(itemKey).catch(() => {});
      } else {
        updateStoreCartItem(itemKey, quantity).catch(() => {});
      }
    }
  }, []);

  const removeItem = useCallback(async (id: number) => {
    let itemKey = '';
    setCart((prev) => {
      const item = prev.find((i) => i.id === id);
      if (item) {
        itemKey = item.key;
        // 🎯 Dispatch GTM GA4 remove_from_cart
        trackRemoveFromCart(item);
      }
      return prev.filter((i) => i.id !== id);
    });

    if (itemKey) {
      removeStoreCartItem(itemKey).catch(() => {});
    }
  }, []);

  const clearCart = useCallback(() => {
    setCart([]);
    try {
      localStorage.removeItem(LOCAL_STORAGE_KEY);
    } catch (e) {}
  }, []);

  const quickAdd = useCallback(
    (product: Product, buyNow = false, preferredSize?: string | null) => {
      if (product.stockStatus === 'OUT_OF_STOCK') return;

      const isEyewear = product.categories?.some((c) => c.toLowerCase().includes('eyewear'));
      const productSizes =
        product.availableSizes && product.availableSizes.length > 0
          ? product.availableSizes
          : [];

      // Simple product with no sizes at all: directly add without opening size picker
      if (!isEyewear && productSizes.length === 0) {
        addToCart(product, 1, buyNow, {});
        if (buyNow && typeof window !== 'undefined') {
          window.location.href = '/checkout';
        }
        return;
      }

      const sizeMatched =
        preferredSize &&
        (productSizes.find((s) => s === preferredSize) ||
          productSizes.find((s) => String(s).match(/\d+/)?.[0] === preferredSize) ||
          (productSizes.length === 0 ? preferredSize : null));

      const chosen = isEyewear
        ? 'one'
        : sizeMatched
        ? sizeMatched
        : null;

      if (!chosen) {
        setPickProduct({ product, buyNow });
        setIsCartOpen(true);
        return;
      }

      addToCart(product, 1, buyNow, { size: chosen });
      if (buyNow && typeof window !== 'undefined') {
        window.location.href = '/checkout';
      }
    },
    [addToCart]
  );

  const pickSize = useCallback(
    (size: string) => {
      if (!pickProduct) return;
      const { product, buyNow } = pickProduct;
      setPickProduct(null);
      addToCart(product, 1, buyNow, { size });
      if (buyNow && typeof window !== 'undefined') {
        window.location.href = '/checkout';
      }
    },
    [pickProduct, addToCart]
  );

  const itemCount = cart.reduce((sum, item) => sum + item.quantity, 0);
  const subtotal = cart.reduce((sum, item) => sum + item.price * item.quantity, 0);
  const regularTotal = cart.reduce((sum, item) => sum + item.regularPrice * item.quantity, 0);
  const savings = Math.max(0, regularTotal - subtotal);

  return (
    <CartContext.Provider
      value={{
        cart,
        itemCount,
        subtotal,
        savings,
        isCartOpen,
        toastMessage,
        pickProduct,
        openCart,
        closeCart,
        openPickSize,
        closePickSize,
        quickAdd,
        pickSize,
        addToCart,
        setQuantity,
        removeItem,
        clearCart,
        showToast,
      }}
    >
      {children}
    </CartContext.Provider>
  );
}

export function useCart() {
  const context = useContext(CartContext);
  if (!context) {
    throw new Error('useCart must be used within a CartProvider');
  }
  return context;
}
