import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { PrismaService } from '../../../prisma/prisma.service';

@Injectable()
export class CartsService {
  constructor(private readonly prisma: PrismaService) {}

  async getOrCreateCart(businessId: string, whatsappNumber: string, customerId?: string) {
    const cleanPhone = whatsappNumber.replace(/^\+/, '').trim();
    let cart = await this.prisma.cart.findFirst({
      where: {
        businessId,
        whatsappNumber: cleanPhone,
        status: 'ACTIVE',
      },
      include: {
        items: {
          include: {
            product: true,
            variant: true,
          },
        },
      },
    });

    if (!cart) {
      cart = await this.prisma.cart.create({
        data: {
          businessId,
          whatsappNumber: cleanPhone,
          customerId,
          status: 'ACTIVE',
          expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours expiry
        },
        include: {
          items: {
            include: {
              product: true,
              variant: true,
            },
          },
        },
      });
    }

    return cart;
  }

  async addToCart(
    businessId: string,
    whatsappNumber: string,
    productId: string,
    quantity: number,
    variantId?: string,
  ) {
    const cleanPhone = whatsappNumber.replace(/^\+/, '').trim();
    const cart = await this.getOrCreateCart(businessId, cleanPhone);
    
    // Check product exists
    const product = await this.prisma.product.findUnique({
      where: { id: productId },
    });
    if (!product) {
      throw new NotFoundException('Product not found');
    }

    let unitPrice = product.price;
    let stockLimit = product.stockQuantity;

    if (variantId) {
      const variant = await this.prisma.productVariant.findUnique({
        where: { id: variantId },
      });
      if (!variant) {
        throw new NotFoundException('Product variant not found');
      }
      unitPrice = variant.price;
      if (variant.stockQuantity !== null) {
        stockLimit = variant.stockQuantity;
      }
    }

    // Check if item already exists in cart
    const existingItem = cart.items.find(
      (item) => item.productId === productId && item.variantId === (variantId || null),
    );
    const currentCartQty = existingItem ? existingItem.quantity : 0;

    if (stockLimit !== null && (currentCartQty + quantity) > stockLimit) {
      throw new BadRequestException(
        `We only have ${stockLimit} of *${product.name}* in stock. You currently have ${currentCartQty} in your cart.`
      );
    }

    const lineTotal = unitPrice * quantity;

    if (existingItem) {
      const newQuantity = existingItem.quantity + quantity;
      await this.prisma.cartItem.update({
        where: { id: existingItem.id },
        data: {
          quantity: newQuantity,
          lineTotal: unitPrice * newQuantity,
        },
      });
    } else {
      await this.prisma.cartItem.create({
        data: {
          cartId: cart.id,
          productId,
          variantId: variantId || null,
          quantity,
          unitPrice,
          lineTotal,
        },
      });
    }

    return this.recalculateCart(cart.id);
  }

  async updateItemQuantity(cartId: string, itemId: string, quantity: number) {
    const item = await this.prisma.cartItem.findUnique({
      where: { id: itemId },
      include: { product: true, variant: true },
    });

    if (!item) {
      throw new NotFoundException('Cart item not found');
    }

    if (quantity <= 0) {
      await this.prisma.cartItem.delete({ where: { id: itemId } });
    } else {
      let stockLimit = item.product.stockQuantity;
      if (item.variant && item.variant.stockQuantity !== null) {
        stockLimit = item.variant.stockQuantity;
      }

      if (stockLimit !== null && quantity > stockLimit) {
        throw new BadRequestException(
          `We only have ${stockLimit} of *${item.product.name}* in stock.`
        );
      }

      await this.prisma.cartItem.update({
        where: { id: itemId },
        data: {
          quantity,
          lineTotal: item.unitPrice * quantity,
        },
      });
    }

    return this.recalculateCart(cartId);
  }

  async removeItem(cartId: string, itemId: string) {
    await this.prisma.cartItem.delete({ where: { id: itemId } });
    return this.recalculateCart(cartId);
  }

  async clearCart(cartId: string) {
    await this.prisma.cartItem.deleteMany({
      where: { cartId },
    });
    return this.prisma.cart.update({
      where: { id: cartId },
      data: {
        totalAmount: 0.0,
        status: 'ACTIVE',
      },
      include: {
        items: true,
      },
    });
  }

  private async recalculateCart(cartId: string) {
    const items = await this.prisma.cartItem.findMany({
      where: { cartId },
    });

    const totalAmount = items.reduce((sum, item) => sum + item.lineTotal, 0);

    return this.prisma.cart.update({
      where: { id: cartId },
      data: { totalAmount },
      include: {
        items: {
          include: {
            product: true,
            variant: true,
          },
        },
      },
    });
  }
}
