"use client";

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";
import type { ShopCurrency, ShopProduct } from "@/lib/shopCatalog";

const CART_KEY = "cyberlux-cart-v1";

export type CartLine = {
  productId: string;
  qty: number;
  name: string;
  price: number;
  currency: ShopCurrency;
};

type CartContextValue = {
  lines: CartLine[];
  itemCount: number;
  hydrated: boolean;
  addToCart: (product: ShopProduct, qty?: number) => void;
  removeLine: (productId: string) => void;
  setLineQty: (productId: string, qty: number) => void;
  clearCart: () => void;
};

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

function loadRaw(): CartLine[] {
  if (typeof window === "undefined") return [];
  try {
    const raw = localStorage.getItem(CART_KEY);
    if (!raw) return [];
    const v = JSON.parse(raw) as CartLine[];
    if (!Array.isArray(v)) return [];
    return v.filter(
      (row) =>
        row &&
        typeof row.productId === "string" &&
        typeof row.qty === "number" &&
        row.qty > 0 &&
        typeof row.name === "string" &&
        typeof row.price === "number" &&
        row.currency &&
        ["BTC", "ETH", "USD", "XMR"].includes(row.currency),
    );
  } catch {
    return [];
  }
}

function persist(lines: CartLine[]) {
  if (typeof window === "undefined") return;
  localStorage.setItem(CART_KEY, JSON.stringify(lines));
}

export function CartProvider({ children }: { children: ReactNode }) {
  const [lines, setLines] = useState<CartLine[]>([]);
  const [hydrated, setHydrated] = useState(false);

  useEffect(() => {
    setLines(loadRaw());
    setHydrated(true);
  }, []);

  const flush = useCallback((next: CartLine[]) => {
    persist(next);
    setLines(next);
  }, []);

  const addToCart = useCallback((product: ShopProduct, qty = 1) => {
    const q = Math.max(1, Math.min(99, qty));
    const cur = loadRaw();
    const i = cur.findIndex((l) => l.productId === product.id);
    let next: CartLine[];
    if (i >= 0) {
      next = [...cur];
      next[i] = { ...next[i]!, qty: Math.min(99, next[i]!.qty + q) };
    } else {
      next = [
        ...cur,
        {
          productId: product.id,
          qty: q,
          name: product.name,
          price: product.price,
          currency: product.currency,
        },
      ];
    }
    persist(next);
    setLines(next);
  }, []);

  const removeLine = useCallback((productId: string) => {
    const next = loadRaw().filter((l) => l.productId !== productId);
    persist(next);
    setLines(next);
  }, []);

  const setLineQty = useCallback((productId: string, qty: number) => {
    const q = Math.floor(qty);
    if (q < 1) {
      const next = loadRaw().filter((l) => l.productId !== productId);
      persist(next);
      setLines(next);
      return;
    }
    const capped = Math.min(99, q);
    const next = loadRaw().map((l) => (l.productId === productId ? { ...l, qty: capped } : l));
    persist(next);
    setLines(next);
  }, []);

  const clearCart = useCallback(() => {
    persist([]);
    setLines([]);
  }, []);

  const itemCount = useMemo(() => lines.reduce((s, l) => s + l.qty, 0), [lines]);

  const value = useMemo(
    () => ({
      lines,
      itemCount,
      hydrated,
      addToCart,
      removeLine,
      setLineQty,
      clearCart,
    }),
    [lines, itemCount, hydrated, addToCart, removeLine, setLineQty, clearCart],
  );

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

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