import { create } from "zustand";
import type { Customer, MenuItem, Order } from "@/lib/api/types";
import { iranMobileForApi } from "@/lib/phone";

export interface CartItem {
  menuItem: MenuItem;
  quantity: number;
  notes?: string;
  orderItemId?: string;
  isVoided?: boolean;
}

export interface AppliedCoupon {
  id: string;
  code: string;
  discountAmount: number;
}

interface CartState {
  items: CartItem[];
  syncedQtyByMenuId: Record<string, number>;
  couponCode: string;
  appliedCoupon: AppliedCoupon | null;
  tableId: string | null;
  activeOrderId: string | null;
  customerId: string | null;
  guestName: string;
  guestPhone: string;
  getPendingLines: () => { menuItemId: string; quantity: number; notes?: string }[];
  addItem: (item: MenuItem) => void;
  removeItem: (menuItemId: string) => void;
  updateQty: (menuItemId: string, quantity: number) => void;
  setCouponCode: (code: string) => void;
  setAppliedCoupon: (coupon: AppliedCoupon | null) => void;
  clearCoupon: () => void;
  setTableId: (tableId: string | null) => void;
  setActiveOrderId: (orderId: string | null) => void;
  setGuestName: (name: string) => void;
  setGuestPhone: (phone: string) => void;
  setCustomer: (customer: Customer | null) => void;
  clearCustomer: () => void;
  hydrateFromOrder: (order: Order, menuById: Map<string, MenuItem>) => void;
  clearCart: () => void;
  clearSession: () => void;
  subtotal: () => number;
}

const clearCouponState = {
  couponCode: "",
  appliedCoupon: null as AppliedCoupon | null,
};

function orderLineToMenuItem(
  line: Order["items"][number],
  menuById: Map<string, MenuItem>
): MenuItem {
  const existing = menuById.get(line.menuItemId);
  if (existing) return existing;
  return {
    id: line.menuItemId,
    categoryId: "",
    name: line.menuItemName,
    price: line.unitPrice,
    isAvailable: true,
  };
}

export const useCartStore = create<CartState>((set, get) => ({
  items: [],
  syncedQtyByMenuId: {},
  couponCode: "",
  appliedCoupon: null,
  tableId: null,
  activeOrderId: null,
  customerId: null,
  guestName: "",
  guestPhone: "",

  getPendingLines: () => {
    const { items, syncedQtyByMenuId } = get();
    const pending: { menuItemId: string; quantity: number; notes?: string }[] = [];
    for (const line of items) {
      const synced = syncedQtyByMenuId[line.menuItem.id] ?? 0;
      const delta = line.quantity - synced;
      if (delta > 0) {
        pending.push({
          menuItemId: line.menuItem.id,
          quantity: delta,
          notes: line.notes,
        });
      }
    }
    return pending;
  },

  addItem: (menuItem) => {
    const existing = get().items.find((i) => i.menuItem.id === menuItem.id);
    if (existing) {
      set({
        items: get().items.map((i) =>
          i.menuItem.id === menuItem.id
            ? { ...i, quantity: i.quantity + 1 }
            : i
        ),
        ...clearCouponState,
      });
    } else {
      set({ items: [...get().items, { menuItem, quantity: 1 }], ...clearCouponState });
    }
  },

  removeItem: (menuItemId) =>
    set({
      items: get().items.filter((i) => i.menuItem.id !== menuItemId),
      ...clearCouponState,
    }),

  updateQty: (menuItemId, quantity) => {
    if (quantity <= 0) {
      get().removeItem(menuItemId);
      return;
    }
    set({
      items: get().items.map((i) =>
        i.menuItem.id === menuItemId ? { ...i, quantity } : i
      ),
      ...clearCouponState,
    });
  },

  setCouponCode: (code) => set({ couponCode: code }),
  setAppliedCoupon: (coupon) => set({ appliedCoupon: coupon }),
  clearCoupon: () => set(clearCouponState),
  setTableId: (tableId) => set({ tableId }),
  setActiveOrderId: (activeOrderId) => set({ activeOrderId }),
  setGuestName: (guestName) =>
    set((s) => ({
      guestName,
      customerId: s.customerId && guestName !== s.guestName ? null : s.customerId,
    })),
  setGuestPhone: (guestPhone) =>
    set((s) => ({
      guestPhone,
      customerId: s.customerId && guestPhone !== s.guestPhone ? null : s.customerId,
    })),

  setCustomer: (customer) =>
    set({
      customerId: customer?.id ?? null,
      guestName: customer?.name ?? "",
      guestPhone: customer?.phone
        ? (iranMobileForApi(customer.phone) ?? customer.phone)
        : "",
    }),

  clearCustomer: () => set({ customerId: null }),

  hydrateFromOrder: (order, menuById) => {
    const syncedQtyByMenuId: Record<string, number> = {};
    for (const line of order.items) {
      syncedQtyByMenuId[line.menuItemId] = line.quantity;
    }
    set({
      activeOrderId: order.id,
      tableId: order.tableId ?? null,
      customerId: order.customerId ?? null,
      guestName: order.guestName ?? order.customerName ?? "",
      guestPhone: order.guestPhone ?? order.customerPhone ?? "",
      syncedQtyByMenuId,
      items: order.items.map((line) => ({
        menuItem: orderLineToMenuItem(line, menuById),
        quantity: line.quantity,
        notes: line.notes,
        orderItemId: line.id,
        isVoided: line.isVoided ?? false,
      })),
      ...clearCouponState,
    });
  },

  clearCart: () =>
    set({
      items: [],
      ...clearCouponState,
    }),

  clearSession: () =>
    set({
      items: [],
      syncedQtyByMenuId: {},
      tableId: null,
      activeOrderId: null,
      customerId: null,
      guestName: "",
      guestPhone: "",
      ...clearCouponState,
    }),

  subtotal: () =>
    get().items.reduce(
      (sum, i) =>
        i.isVoided ? sum : sum + i.menuItem.price * i.quantity,
      0
    ),
}));
