"use client";

import { createContext, useCallback, useContext, useEffect, useState } from "react";
import {
  addCartItem,
  getOrCreateCart,
  removeCartItem,
  setCartItemQuantity,
  type Cart
} from "@/lib/store-api";

interface CartContextValue {
  cart: Cart | null;
  loading: boolean;
  itemCount: number;
  isDrawerOpen: boolean;
  openDrawer: () => void;
  closeDrawer: () => void;
  addItem: (variantId: number, quantity?: number) => Promise<void>;
  removeItem: (variantId: number) => Promise<void>;
  setQuantity: (variantId: number, quantity: number) => Promise<void>;
  refresh: () => Promise<void>;
}

const CartContext = createContext<CartContextValue | null>(null);

export function CartProvider({ children }: { children: React.ReactNode }) {
  const [cart, setCart] = useState<Cart | null>(null);
  const [loading, setLoading] = useState(true);
  const [isDrawerOpen, setDrawerOpen] = useState(false);

  const refresh = useCallback(async () => {
    const next = await getOrCreateCart();
    setCart(next);
  }, []);

  useEffect(() => {
    // Runs unprompted on every page mount (not a user action), so a down/unreachable
    // API must not surface as an uncaught rejection — fail soft to an empty cart and
    // let the user retry an add-to-cart click, which does surface its own error state.
    refresh()
      .catch((err) => console.error("[cart] failed to load cart on mount:", err))
      .finally(() => setLoading(false));
  }, [refresh]);

  const addItem = useCallback(async (variantId: number, quantity = 1) => {
    const next = await addCartItem(variantId, quantity);
    setCart(next);
    setDrawerOpen(true);
  }, []);

  // removeItem/setQuantity are wired to bare onClick={() => removeItem(...)} handlers in
  // CartDrawer/cart page with no per-call try/catch (unlike addItem, which ProductDetail
  // already wraps to show its own error state) — catch here so a failed request just leaves
  // the displayed cart stale instead of an uncaught rejection.
  const removeItem = useCallback(async (variantId: number) => {
    try {
      const next = await removeCartItem(variantId);
      setCart(next);
    } catch (err) {
      console.error("[cart] failed to remove item:", err);
    }
  }, []);

  const setQuantity = useCallback(async (variantId: number, quantity: number) => {
    try {
      const next = await setCartItemQuantity(variantId, quantity);
      setCart(next);
    } catch (err) {
      console.error("[cart] failed to update quantity:", err);
    }
  }, []);

  const itemCount = cart?.items.reduce((sum, i) => sum + i.quantity, 0) ?? 0;

  return (
    <CartContext.Provider
      value={{
        cart,
        loading,
        itemCount,
        isDrawerOpen,
        openDrawer: () => setDrawerOpen(true),
        closeDrawer: () => setDrawerOpen(false),
        addItem,
        removeItem,
        setQuantity,
        refresh
      }}
    >
      {children}
    </CartContext.Provider>
  );
}

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