"use client";

import { createContext, useContext, useEffect, useRef, useState, type ReactNode } from "react";
import { catalogProducts } from "@/data/catalog";
import { useAccount } from "@/components/account/account-store";
import { checkoutTransaction, emptyCheckout, restoreOrder, restoreOrderHistory, type CartLine, type CheckoutDetails, type DeliveryZone, type DemoOrder, type OrderResult } from "@/lib/commerce";

type DemoState = { wishlist: string[]; cart: CartLine[]; deliveryZone: DeliveryZone; lastOrder: DemoOrder | null; orders: DemoOrder[] };
type DemoStore = DemoState & {
  toggleWish: (id: string) => void;
  addItem: (productId: string, variantId: string, quantity?: number) => boolean;
  updateQuantity: (variantId: string, quantity: number) => void;
  removeItem: (variantId: string) => void;
  hydrated: boolean;
  checkoutDraft: CheckoutDetails;
  updateCheckoutDraft: (patch: Partial<CheckoutDetails>) => void;
  setDeliveryZone: (zone: DeliveryZone) => void;
  placeOrder: (checkoutKey: string) => OrderResult;
  count: number; notice: string;
};
const DemoContext = createContext<DemoStore | null>(null);
const storageKey = "fashion-mart:demo:v1";
const validVariant = (productId: string, variantId: string) => catalogProducts.find((product) => product.id === productId)?.variants.find((variant) => variant.id === variantId);

export function DemoStoreProvider({ children }: { children: ReactNode }) {
  const { profile } = useAccount();
  const [state, setState] = useState<DemoState>({ wishlist: [], cart: [], deliveryZone: "dhaka", lastOrder: null, orders: [] });
  const snapshot = useRef(state);
  const [hydrated, setHydrated] = useState(false);
  const [notice, setNotice] = useState("");
  const [checkoutDraft, setCheckoutDraft] = useState<CheckoutDetails>(emptyCheckout);
  const draftSnapshot = useRef(checkoutDraft);
  function updateCheckoutDraft(patch: Partial<CheckoutDetails>) {
    const next = { ...draftSnapshot.current, ...patch };
    draftSnapshot.current = next;
    setCheckoutDraft(next);
  }
  function changeState(update: (current: DemoState) => DemoState) {
    const next = update(snapshot.current);
    snapshot.current = next;
    setState(next);
  }
  useEffect(() => {
    try {
      const stored: unknown = JSON.parse(localStorage.getItem(storageKey) ?? "null");
      if (stored && typeof stored === "object") {
        const data = stored as Record<string, unknown>;
        const wishlist = Array.isArray(data.wishlist) ? [...new Set(data.wishlist.filter((id): id is string => typeof id === "string" && catalogProducts.some((product) => product.id === id)))] : [];
        const cart: CartLine[] = [];
        if (Array.isArray(data.cart)) for (const item of data.cart) {
          if (!item || typeof item !== "object" || typeof item.productId !== "string" || typeof item.variantId !== "string" || !Number.isInteger(item.quantity) || item.quantity <= 0) continue;
          const variant = validVariant(item.productId, item.variantId);
          if (variant && variant.stock > 0 && !cart.some((line) => line.variantId === item.variantId)) cart.push({ productId: item.productId, variantId: item.variantId, quantity: Math.min(item.quantity, variant.stock) });
        }
        const deliveryZone = data.deliveryZone === "outside" ? "outside" : "dhaka";
        const lastOrder = restoreOrder(data.lastOrder);
        changeState(() => ({ wishlist, cart, deliveryZone, lastOrder, orders: restoreOrderHistory(data.orders, lastOrder) }));
        updateCheckoutDraft({ deliveryZone, district: deliveryZone === "dhaka" ? "Dhaka" : "" });
      }
    } catch { /* Storage may be disabled or contain an old demo. */ }
    setHydrated(true);
  }, []);
  useEffect(() => { if (hydrated) try { localStorage.setItem(storageKey, JSON.stringify(state)); } catch { /* The demo still works in memory. */ } }, [state, hydrated]);
  useEffect(() => { if (!notice) return; const timeout = setTimeout(() => setNotice(""), 3000); return () => clearTimeout(timeout); }, [notice]);

  function toggleWish(id: string) {
    if (!catalogProducts.some((product) => product.id === id)) return;
    changeState((current) => ({ ...current, wishlist: current.wishlist.includes(id) ? current.wishlist.filter((item) => item !== id) : [...current.wishlist, id] }));
  }
  function addItem(productId: string, variantId: string, requestedQuantity = 1) {
    const variant = validVariant(productId, variantId);
    const quantity = snapshot.current.cart.find((line) => line.variantId === variantId)?.quantity ?? 0;
    if (!variant || !Number.isInteger(requestedQuantity) || requestedQuantity < 1 || quantity + requestedQuantity > variant.stock) { setNotice("This selection has reached its available stock."); return false; }
    changeState((current) => {
      const exists = current.cart.some((line) => line.variantId === variantId);
      return { ...current, cart: exists ? current.cart.map((line) => line.variantId === variantId ? { ...line, quantity: line.quantity + requestedQuantity } : line) : [...current.cart, { productId, variantId, quantity: requestedQuantity }] };
    });
    setNotice("Added to your bag");
    return true;
  }
  function updateQuantity(variantId: string, quantity: number) {
    if (!Number.isInteger(quantity) || quantity < 1) return;
    changeState((current) => ({ ...current, cart: current.cart.map((line) => {
      const variant = validVariant(line.productId, variantId);
      return line.variantId === variantId && variant ? { ...line, quantity: Math.min(quantity, variant.stock) } : line;
    }) }));
  }
  function removeItem(variantId: string) { changeState((current) => ({ ...current, cart: current.cart.filter((line) => line.variantId !== variantId) })); }
  function setDeliveryZone(zone: DeliveryZone) {
    if (zone !== "dhaka" && zone !== "outside") return;
    changeState((current) => ({ ...current, deliveryZone: zone }));
    updateCheckoutDraft({ deliveryZone: zone, ...(zone === "dhaka" ? { district: "Dhaka" } : draftSnapshot.current.deliveryZone === "dhaka" ? { district: "" } : {}) });
  }
  function placeOrder(checkoutKey: string): OrderResult {
    if (!hydrated) return { ok: false, errors: {}, message: "Please wait for your bag to finish loading." };
    const current = snapshot.current;
    const token = crypto.randomUUID().slice(0, 6).toUpperCase();
    const transaction = checkoutTransaction(current, draftSnapshot.current, checkoutKey, { id: `FM-DEMO-${Date.now().toString(36).toUpperCase()}-${token}`, placedAt: new Date().toISOString(), ...(profile ? { accountEmail: profile.email } : {}) });
    const result = transaction.result;
    if (!result.ok) return result;
    if (transaction.state === current) return result;
    // One synchronous state transition saves the snapshot and empties the bag.
    changeState((latest) => ({ ...latest, ...transaction.state, orders: [result.order, ...latest.orders.filter((order) => order.id !== result.order.id)].slice(0, 100), deliveryZone: result.order.customer.deliveryZone }));
    updateCheckoutDraft({ ...emptyCheckout(), deliveryZone: result.order.customer.deliveryZone, district: result.order.customer.deliveryZone === "dhaka" ? "Dhaka" : "" });
    setNotice("");
    return result;
  }
  return <DemoContext.Provider value={{ ...state, toggleWish, addItem, updateQuantity, removeItem, hydrated, checkoutDraft, updateCheckoutDraft, setDeliveryZone, placeOrder, count: state.cart.reduce((sum, line) => sum + line.quantity, 0), notice }}>{children}</DemoContext.Provider>;
}

export function useDemoStore() { const value = useContext(DemoContext); if (!value) throw new Error("Demo store provider is missing"); return value; }
