"use client";

import {
  createContext,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";
import { findCoupon } from "@/data/coupons";
import type { Coupon, Product } from "@/data/types";
import { useToast } from "./toast-context";

export type CartItem = {
  product: Product;
  quantity: number;
  variantLabel?: string;
};

type CartContextValue = {
  items: CartItem[];
  itemCount: number;
  subtotal: number;
  discount: number;
  shipping: number;
  total: number;
  coupon: Coupon | null;
  isOpen: boolean;
  openCart: () => void;
  closeCart: () => void;
  addItem: (
    product: Product,
    quantity?: number,
    variantLabel?: string,
    options?: { openDrawer?: boolean },
  ) => void;
  removeItem: (productId: string, variantLabel?: string) => void;
  updateQuantity: (
    productId: string,
    quantity: number,
    variantLabel?: string,
  ) => void;
  applyCoupon: (code: string) => boolean;
  clearCoupon: () => void;
  clearCart: () => void;
};

const CartContext = createContext<CartContextValue | null>(null);
const STORAGE_KEY = "fliemart-cart-v2";

function itemKey(productId: string, variantLabel?: string) {
  return `${productId}::${variantLabel ?? ""}`;
}

export function CartProvider({ children }: { children: ReactNode }) {
  const [items, setItems] = useState<CartItem[]>([]);
  const [coupon, setCoupon] = useState<Coupon | null>(null);
  const [hydrated, setHydrated] = useState(false);
  const [isOpen, setIsOpen] = useState(false);
  const { toast } = useToast();

  useEffect(() => {
    try {
      const raw = localStorage.getItem(STORAGE_KEY);
      if (raw) {
        const parsed = JSON.parse(raw) as {
          items: CartItem[];
          coupon: Coupon | null;
        };
        setItems(parsed.items ?? []);
        setCoupon(parsed.coupon ?? null);
      }
    } catch {
      // ignore
    }
    setHydrated(true);
  }, []);

  useEffect(() => {
    if (!hydrated) return;
    localStorage.setItem(STORAGE_KEY, JSON.stringify({ items, coupon }));
  }, [items, coupon, hydrated]);

  const openCart = () => setIsOpen(true);
  const closeCart = () => setIsOpen(false);

  const addItem = (
    product: Product,
    quantity = 1,
    variantLabel?: string,
    options?: { openDrawer?: boolean },
  ) => {
    const safeQty = Math.min(50, Math.max(1, Math.round(Number(quantity) || 1)));
    setItems((current) => {
      const key = itemKey(product.id, variantLabel);
      const existing = current.find(
        (item) => itemKey(item.product.id, item.variantLabel) === key,
      );
      if (existing) {
        return current.map((item) =>
          itemKey(item.product.id, item.variantLabel) === key
            ? {
                ...item,
                quantity: Math.min(50, item.quantity + safeQty),
              }
            : item,
        );
      }
      return [...current, { product, quantity: safeQty, variantLabel }];
    });
    toast(`${product.name} added to cart`);
    if (options?.openDrawer !== false) setIsOpen(true);
  };

  const removeItem = (productId: string, variantLabel?: string) => {
    const key = itemKey(productId, variantLabel);
    setItems((current) =>
      current.filter(
        (item) => itemKey(item.product.id, item.variantLabel) !== key,
      ),
    );
    toast("Item removed", "info");
  };

  const updateQuantity = (
    productId: string,
    quantity: number,
    variantLabel?: string,
  ) => {
    if (quantity <= 0) {
      removeItem(productId, variantLabel);
      return;
    }
    const safeQty = Math.min(50, Math.max(1, Math.round(Number(quantity) || 1)));
    const key = itemKey(productId, variantLabel);
    setItems((current) =>
      current.map((item) =>
        itemKey(item.product.id, item.variantLabel) === key
          ? { ...item, quantity: safeQty }
          : item,
      ),
    );
  };

  const applyCoupon = (code: string) => {
    const found = findCoupon(code);
    if (!found) {
      toast("Invalid coupon code", "error");
      return false;
    }
    setCoupon(found);
    toast(`Coupon applied: ${found.label}`);
    return true;
  };

  const clearCoupon = () => setCoupon(null);
  const clearCart = () => {
    setItems([]);
    setCoupon(null);
  };

  const subtotal = useMemo(
    () =>
      items.reduce(
        (sum, item) => sum + item.product.price * item.quantity,
        0,
      ),
    [items],
  );

  const discount = useMemo(() => {
    if (!coupon) return 0;
    if (coupon.type === "percent") return (subtotal * coupon.value) / 100;
    return Math.min(coupon.value, subtotal);
  }, [coupon, subtotal]);

  const shipping = subtotal - discount >= 150 || items.length === 0 ? 0 : 9;
  const total = Math.max(0, subtotal - discount + shipping);
  const itemCount = items.reduce((sum, item) => sum + item.quantity, 0);

  return (
    <CartContext.Provider
      value={{
        items,
        itemCount,
        subtotal,
        discount,
        shipping,
        total,
        coupon,
        isOpen,
        openCart,
        closeCart,
        addItem,
        removeItem,
        updateQuantity,
        applyCoupon,
        clearCoupon,
        clearCart,
      }}
    >
      {children}
    </CartContext.Provider>
  );
}

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