import { Injectable, NotFoundException } from '@nestjs/common';
import { Food } from '../../foods/entities/food.entity';
import { Cart, CartItem } from '../interfaces/cart.interface';
import { CartValidationService } from './cart-validation.service';
import { CartCalculationService } from './cart-calculation.service';
import { CartMessage } from 'src/common/enums/message.enum';

@Injectable()
export class CartItemService {
  constructor(
    private readonly validationService: CartValidationService,
    private readonly calculationService: CartCalculationService,
  ) {}

  /**
   * Create a new cart item from food
   */
  createCartItem(food: Food, quantity: number): CartItem {
    const itemPrice = food.price || 0;
    const itemDiscount = food.discount || 0;

    return {
      foodId: food.id,
      foodTitle: food.title,
      quantity,
      price: itemPrice,
      discount: itemDiscount,
      totalPrice: this.calculationService.calculateItemTotalPrice(itemPrice, itemDiscount, quantity),
    };
  }

  /**
   * Build cart item from food (updating existing item if provided)
   */
  buildCartItemFromFood(food: Food, quantity: number, previous?: CartItem): CartItem {
    const itemPrice = food.price || 0;
    const itemDiscount = food.discount || 0;
    return {
      ...(previous ?? ({} as CartItem)),
      foodId: food.id,
      foodTitle: food.title,
      quantity,
      price: itemPrice,
      discount: itemDiscount,
      totalPrice: this.calculationService.calculateItemTotalPrice(itemPrice, itemDiscount, quantity),
    };
  }

  /**
   * Get item index in cart
   */
  getItemIndex(cart: Cart, foodId: string): number {
    return cart.items.findIndex(item => item.foodId === foodId);
  }

  /**
   * Add or increment item in cart
   */
  async addOrIncrementItem(cart: Cart, foodId: string, restaurantId: string, quantityToAdd: number): Promise<void> {
    const food = await this.validationService.validateAndGetFood(foodId, restaurantId, quantityToAdd);
    
    // Validate meal type compatibility
    this.validationService.assertMealTypeCompatibility(food);
    
    // Validate weekday compatibility
    this.validationService.assertWeekdayCompatibility(food);
    
    const index = this.getItemIndex(cart, food.id);

    if (index < 0) {
      cart.items.push(this.createCartItem(food, quantityToAdd));
      return;
    }

    const existingItem = cart.items[index];
    const newQuantity = existingItem.quantity + quantityToAdd;
    this.validationService.validateStock(food, newQuantity);
    cart.items[index] = this.buildCartItemFromFood(food, newQuantity, existingItem);
  }

  /**
   * Remove item from cart
   */
  removeItemOrFail(cart: Cart, foodId: string): void {
    const itemIndex = this.getItemIndex(cart, foodId);
    if (itemIndex < 0) {
      throw new NotFoundException(CartMessage.ITEM_NOT_FOUND);
    }
    cart.items.splice(itemIndex, 1);
  }

  /**
   * Decrement item quantity or remove if quantity reaches 0
   */
  async decrementOrRemoveItem(cart: Cart, foodId: string): Promise<void> {
    const itemIndex = this.getItemIndex(cart, foodId);
    if (itemIndex < 0) {
      throw new NotFoundException(CartMessage.ITEM_NOT_FOUND);
    }

    const existingItem = cart.items[itemIndex];
    const newQuantity = existingItem.quantity - 1;

    if (newQuantity <= 0) {
      cart.items.splice(itemIndex, 1);
      return;
    }

    const food = await this.validationService.getFoodOrFail(foodId);
    cart.items[itemIndex] = this.buildCartItemFromFood(food, newQuantity, existingItem);
  }
}

