import { CartItem, CartLensConfig, Product, ProductVariant } from './types';

type CartListener = () => void;

export function getCartItemUnitPrice(item: CartItem): number {
  const basePrice = item.variant ? item.variant.price_modifier : item.product.price;
  const lensExtra = item.lensConfig
    ? item.lensConfig.offerPrice + item.lensConfig.options.reduce((sum, option) => sum + option.price, 0)
    : 0;

  return basePrice + lensExtra;
}

export function getCartItemTotal(item: CartItem): number {
  return getCartItemUnitPrice(item) * item.quantity;
}

export function getCartSubtotal(items: CartItem[]): number {
  return items.reduce((sum, item) => sum + getCartItemTotal(item), 0);
}

class CartStore {
  private items: CartItem[] = [];
  private listeners: Set<CartListener> = new Set();
  private isOpen = false;

  constructor() {
    if (typeof window !== 'undefined') {
      const saved = localStorage.getItem('cart');
      if (saved) {
        try {
          this.items = JSON.parse(saved);
        } catch {
          this.items = [];
        }
      }
    }
  }

  subscribe(listener: CartListener): () => void {
    this.listeners.add(listener);
    return () => { this.listeners.delete(listener); };
  }

  private notify() {
    if (typeof window !== 'undefined') {
      localStorage.setItem('cart', JSON.stringify(this.items));
    }
    this.listeners.forEach((l) => l());
  }

  getItems(): CartItem[] {
    return this.items;
  }

  getIsOpen(): boolean {
    return this.isOpen;
  }

  setIsOpen(open: boolean) {
    this.isOpen = open;
    this.notify();
  }

  private getCartKey(productId: string, variantId?: string): string {
    return variantId ? `${productId}:${variantId}` : productId;
  }

  addItem(product: Product, quantity = 1, variant?: ProductVariant, lensConfig?: CartLensConfig) {
    const key = this.getCartKey(product.id, variant?.id);
    const existing = this.items.find(
      (i) => this.getCartKey(i.product.id, i.variant?.id) === key && !i.lensConfig && !lensConfig
    );
    if (existing && !lensConfig) {
      existing.quantity += quantity;
    } else {
      this.items.push({ product, quantity, variant, lensConfig });
    }
    this.isOpen = true;
    this.notify();
  }

  removeItem(productId: string, variantId?: string) {
    const key = this.getCartKey(productId, variantId);
    this.items = this.items.filter(
      (i) => this.getCartKey(i.product.id, i.variant?.id) !== key
    );
    this.notify();
  }

  updateQuantity(productId: string, quantity: number, variantId?: string) {
    if (quantity <= 0) {
      this.removeItem(productId, variantId);
      return;
    }
    const key = this.getCartKey(productId, variantId);
    const item = this.items.find(
      (i) => this.getCartKey(i.product.id, i.variant?.id) === key
    );
    if (item) {
      item.quantity = quantity;
      this.notify();
    }
  }

  clear() {
    this.items = [];
    this.notify();
  }

  getSubtotal(): number {
    return getCartSubtotal(this.items);
  }

  getItemCount(): number {
    return this.items.reduce((sum, item) => sum + item.quantity, 0);
  }
}

export const cartStore = new CartStore();
