import { db } from '../db/db_index' import { addresses, deliverySlotInfo, orders, orderStatus } from '../db/schema' import { and, eq, gte } from 'drizzle-orm' import type { InferSelectModel } from 'drizzle-orm' import type { UserAddress } from '@packages/shared' type AddressRow = InferSelectModel const mapUserAddress = (address: AddressRow): UserAddress => ({ id: address.id, userId: address.userId, name: address.name, phone: address.phone, addressLine1: address.addressLine1, addressLine2: address.addressLine2 ?? null, city: address.city, state: address.state, pincode: address.pincode, isDefault: address.isDefault, latitude: address.latitude ?? null, longitude: address.longitude ?? null, googleMapsUrl: address.googleMapsUrl ?? null, adminLatitude: address.adminLatitude ?? null, adminLongitude: address.adminLongitude ?? null, zoneId: address.zoneId ?? null, createdAt: address.createdAt, }) export async function getDefaultAddress(userId: number): Promise { const [defaultAddress] = await db .select() .from(addresses) .where(and(eq(addresses.userId, userId), eq(addresses.isDefault, true))) .limit(1) return defaultAddress ? mapUserAddress(defaultAddress) : null } export async function getUserAddresses(userId: number): Promise { const userAddresses = await db.select().from(addresses).where(eq(addresses.userId, userId)) return userAddresses.map(mapUserAddress) } export async function getUserAddressById(userId: number, addressId: number): Promise { const [address] = await db .select() .from(addresses) .where(and(eq(addresses.id, addressId), eq(addresses.userId, userId))) .limit(1) return address ? mapUserAddress(address) : null } export async function clearDefaultAddress(userId: number): Promise { await db.update(addresses).set({ isDefault: false }).where(eq(addresses.userId, userId)) } export async function createUserAddress(input: { userId: number name: string phone: string addressLine1: string addressLine2?: string city: string state: string pincode: string isDefault: boolean latitude?: number longitude?: number googleMapsUrl?: string }): Promise { const [newAddress] = await db.insert(addresses).values({ userId: input.userId, name: input.name, phone: input.phone, addressLine1: input.addressLine1, addressLine2: input.addressLine2, city: input.city, state: input.state, pincode: input.pincode, isDefault: input.isDefault, latitude: input.latitude, longitude: input.longitude, googleMapsUrl: input.googleMapsUrl, }).returning() return mapUserAddress(newAddress) } export async function updateUserAddress(input: { userId: number addressId: number name: string phone: string addressLine1: string addressLine2?: string city: string state: string pincode: string isDefault: boolean latitude?: number longitude?: number googleMapsUrl?: string }): Promise { const [updatedAddress] = await db.update(addresses) .set({ name: input.name, phone: input.phone, addressLine1: input.addressLine1, addressLine2: input.addressLine2, city: input.city, state: input.state, pincode: input.pincode, isDefault: input.isDefault, googleMapsUrl: input.googleMapsUrl, latitude: input.latitude, longitude: input.longitude, }) .where(and(eq(addresses.id, input.addressId), eq(addresses.userId, input.userId))) .returning() return updatedAddress ? mapUserAddress(updatedAddress) : null } export async function deleteUserAddress(userId: number, addressId: number): Promise { const [deleted] = await db.delete(addresses) .where(and(eq(addresses.id, addressId), eq(addresses.userId, userId))) .returning({ id: addresses.id }) return !!deleted } export async function hasOngoingOrdersForAddress(addressId: number): Promise { const ongoingOrders = await db.select({ orderId: orders.id, }) .from(orders) .innerJoin(orderStatus, eq(orders.id, orderStatus.orderId)) .innerJoin(deliverySlotInfo, eq(orders.slotId, deliverySlotInfo.id)) .where(and( eq(orders.addressId, addressId), eq(orderStatus.isCancelled, false), gte(deliverySlotInfo.deliveryTime, new Date()) )) .limit(1) return ongoingOrders.length > 0 }