import { db } from '../db/db_index';
import { deliverySlotInfo, productInfo, vendorSnippets } from '../db/schema';
import { eq, and, inArray, desc } from 'drizzle-orm';

export async function getAllSlots(): Promise<any[]> {
  const slots = await db.query.deliverySlotInfo.findMany({
    orderBy: desc(deliverySlotInfo.createdAt),
    with: {
      vendorSnippets: true,
    },
  });

  // Fetch products for all slots
  const allProductIds = new Set<number>();
  for (const slot of slots) {
    for (const productId of (slot.productIds || [])) {
      allProductIds.add(productId);
    }
  }

  const productIdsArray = Array.from(allProductIds);
  const productsData = productIdsArray.length > 0
    ? await db.query.productInfo.findMany({
        where: inArray(productInfo.id, productIdsArray),
      })
    : [];

  const productMap = new Map(productsData.map(p => [p.id, p]));

  return slots.map(slot => ({
    ...slot,
    products: (slot.productIds || [])
      .map(productId => productMap.get(productId))
      .filter((p): p is NonNullable<typeof p> => p != null),
  }));
}

export async function getSlotById(id: number): Promise<any | null> {
  const slot = await db.query.deliverySlotInfo.findFirst({
    where: eq(deliverySlotInfo.id, id),
    with: {
      vendorSnippets: {
        with: {
          slot: true,
        },
      },
    },
  });

  if (!slot) {
    return null;
  }

  // Fetch products for this slot
  const productIds = slot.productIds || [];
  const productsData = productIds.length > 0
    ? await db.query.productInfo.findMany({
        where: inArray(productInfo.id, productIds),
      })
    : [];

  return {
    ...slot,
    products: productsData,
  };
}

export async function createSlot(input: any): Promise<any> {
  const [slot] = await db.insert(deliverySlotInfo).values(input).returning();
  return slot;
}

export async function updateSlot(id: number, updates: any): Promise<any> {
  const [slot] = await db.update(deliverySlotInfo)
    .set(updates)
    .where(eq(deliverySlotInfo.id, id))
    .returning();
  return slot;
}

export async function deleteSlot(id: number): Promise<void> {
  await db.delete(deliverySlotInfo).where(eq(deliverySlotInfo.id, id));
}

export async function getSlotProducts(slotId: number): Promise<any[]> {
  const slot = await db.query.deliverySlotInfo.findFirst({
    where: eq(deliverySlotInfo.id, slotId),
  });

  if (!slot) {
    return [];
  }

  const productIds = slot.productIds || [];
  if (productIds.length === 0) {
    return [];
  }

  return await db.query.productInfo.findMany({
    where: inArray(productInfo.id, productIds),
  });
}

export async function addProductToSlot(slotId: number, productId: number): Promise<void> {
  const slot = await db.query.deliverySlotInfo.findFirst({
    where: eq(deliverySlotInfo.id, slotId),
  });

  if (!slot) {
    throw new Error(`Slot ${slotId} not found`);
  }

  const currentProductIds = slot.productIds || [];
  if (!currentProductIds.includes(productId)) {
    await db.update(deliverySlotInfo)
      .set({ productIds: [...currentProductIds, productId] })
      .where(eq(deliverySlotInfo.id, slotId));
  }
}

export async function removeProductFromSlot(slotId: number, productId: number): Promise<void> {
  const slot = await db.query.deliverySlotInfo.findFirst({
    where: eq(deliverySlotInfo.id, slotId),
  });

  if (!slot) {
    throw new Error(`Slot ${slotId} not found`);
  }

  const currentProductIds = slot.productIds || [];
  const updatedProductIds = currentProductIds.filter(id => id !== productId);
  
  await db.update(deliverySlotInfo)
    .set({ productIds: updatedProductIds })
    .where(eq(deliverySlotInfo.id, slotId));
}

export async function clearSlotProducts(slotId: number): Promise<void> {
  await db.update(deliverySlotInfo)
    .set({ productIds: [] })
    .where(eq(deliverySlotInfo.id, slotId));
}

export async function updateSlotCapacity(slotId: number, maxCapacity: number): Promise<any> {
  const [slot] = await db.update(deliverySlotInfo)
    .set({ maxCapacity })
    .where(eq(deliverySlotInfo.id, slotId))
    .returning();
  return slot;
}

export async function getSlotDeliverySequence(slotId: number): Promise<any | null> {
  const slot = await db.query.deliverySlotInfo.findFirst({
    where: eq(deliverySlotInfo.id, slotId),
    columns: {
      deliverySequence: true,
    },
  });
  return slot?.deliverySequence || null;
}

export async function updateSlotDeliverySequence(slotId: number, sequence: any): Promise<void> {
  await db.update(deliverySlotInfo)
    .set({ deliverySequence: sequence })
    .where(eq(deliverySlotInfo.id, slotId));
}
