import { db } from '../db/db_index'
import { cartItems, productInfo, units } from '../db/schema'
import { and, eq, sql } from 'drizzle-orm'
import type { UserCartItem } from '@packages/shared'

const getStringArray = (value: unknown): string[] => {
  if (!Array.isArray(value)) return []
  return value.map((item) => String(item))
}

export async function getCartItemsWithProducts(userId: number): Promise<UserCartItem[]> {
  const cartItemsWithProducts = await db
    .select({
      cartId: cartItems.id,
      productId: productInfo.id,
      productName: productInfo.name,
      productPrice: productInfo.price,
      productImages: productInfo.images,
      productQuantity: productInfo.productQuantity,
      isOutOfStock: productInfo.isOutOfStock,
      unitShortNotation: units.shortNotation,
      quantity: cartItems.quantity,
      addedAt: cartItems.addedAt,
    })
    .from(cartItems)
    .innerJoin(productInfo, eq(cartItems.productId, productInfo.id))
    .innerJoin(units, eq(productInfo.unitId, units.id))
    .where(eq(cartItems.userId, userId))

  return cartItemsWithProducts.map((item) => ({
    id: item.cartId,
    productId: item.productId,
    quantity: parseFloat(item.quantity),
    addedAt: item.addedAt,
    product: {
      id: item.productId,
      name: item.productName,
      price: item.productPrice.toString(),
      productQuantity: item.productQuantity,
      unit: item.unitShortNotation,
      isOutOfStock: item.isOutOfStock,
      images: getStringArray(item.productImages),
    },
    subtotal: parseFloat(item.productPrice.toString()) * parseFloat(item.quantity),
  }))
}

export async function getProductById(productId: number) {
  return db.query.productInfo.findFirst({
    where: eq(productInfo.id, productId),
  })
}

export async function getCartItemByUserProduct(userId: number, productId: number) {
  return db.query.cartItems.findFirst({
    where: and(eq(cartItems.userId, userId), eq(cartItems.productId, productId)),
  })
}

export async function incrementCartItemQuantity(itemId: number, quantity: number): Promise<void> {
  await db.update(cartItems)
    .set({
      quantity: sql`${cartItems.quantity} + ${quantity}`,
    })
    .where(eq(cartItems.id, itemId))
}

export async function insertCartItem(userId: number, productId: number, quantity: number): Promise<void> {
  await db.insert(cartItems).values({
    userId,
    productId,
    quantity: quantity.toString(),
  })
}

export async function updateCartItemQuantity(userId: number, itemId: number, quantity: number) {
  const [updatedItem] = await db.update(cartItems)
    .set({ quantity: quantity.toString() })
    .where(and(eq(cartItems.id, itemId), eq(cartItems.userId, userId)))
    .returning({ id: cartItems.id })

  return !!updatedItem
}

export async function deleteCartItem(userId: number, itemId: number): Promise<boolean> {
  const [deletedItem] = await db.delete(cartItems)
    .where(and(eq(cartItems.id, itemId), eq(cartItems.userId, userId)))
    .returning({ id: cartItems.id })

  return !!deletedItem
}

export async function clearUserCart(userId: number): Promise<void> {
  await db.delete(cartItems).where(eq(cartItems.userId, userId))
}
