// import redisClient from '@/src/lib/redis-client'
import {
  getAllSlotsWithProductsForCache,
  type SlotWithProductsData,
} from '@/src/dbService'
import { scaffoldAssetUrl } from '@/src/lib/s3-client'
import dayjs from 'dayjs'

// Define the structure for slot with products
interface SlotWithProducts {
  id: number
  deliveryTime: Date
  freezeTime: Date
  isActive: boolean
  isCapacityFull: boolean
  products: Array<{
    id: number
    name: string
    shortDescription: string | null
    productQuantity: number
    price: string
    marketPrice: string | null
    unit: string | null
    images: string[]
    isOutOfStock: boolean
    storeId: number | null
    nextDeliveryDate: Date
  }>
}

interface SlotInfo {
  id: number
  deliveryTime: Date
  freezeTime: Date
  isCapacityFull: boolean
}

async function transformSlotToStoreSlot(slot: SlotWithProductsData): Promise<SlotWithProducts> {
  return {
    id: slot.id,
    deliveryTime: slot.deliveryTime,
    freezeTime: slot.freezeTime,
    isActive: slot.isActive,
    isCapacityFull: slot.isCapacityFull,
    products: slot.products.map((product) => ({
      id: product.id,
      name: product.name,
      productQuantity: product.productQuantity,
      shortDescription: product.shortDescription,
      price: product.price.toString(),
      marketPrice: product.marketPrice?.toString() || null,
      unit: product.unit?.shortNotation || null,
      images: scaffoldAssetUrl(
        (product.images as string[]) || []
      ),
      isOutOfStock: product.isOutOfStock,
      storeId: product.storeId,
      nextDeliveryDate: slot.deliveryTime,
    })),
  }
}

function extractSlotInfo(slot: SlotWithProductsData): SlotInfo {
  return {
    id: slot.id,
    deliveryTime: slot.deliveryTime,
    freezeTime: slot.freezeTime,
    isCapacityFull: slot.isCapacityFull,
  }
}

async function fetchAllTransformedSlots(): Promise<SlotWithProducts[]> {
  const slots = await getAllSlotsWithProductsForCache()
  return Promise.all(slots.map(transformSlotToStoreSlot))
}

export async function initializeSlotStore(): Promise<void> {
  try {
    console.log('Initializing slot store in Redis...')

    // Fetch active delivery slots with future delivery times
    const slots = await getAllSlotsWithProductsForCache()

    /*
    // Old implementation - direct DB queries:
    import { db } from '@/src/db/db_index'
    import { deliverySlotInfo } from '@/src/db/schema'
    import { eq, gt, and, asc } from 'drizzle-orm'

    const now = new Date();
    const slots = await db.query.deliverySlotInfo.findMany({
      where: and(
        eq(deliverySlotInfo.isActive, true),
        gt(deliverySlotInfo.deliveryTime, now),
      ),
      with: {
        productSlots: {
          with: {
            product: {
              with: {
                unit: true,
                store: true,
              },
            },
          },
        },
      },
      orderBy: asc(deliverySlotInfo.deliveryTime),
    });
    */

    // Transform data for storage
    const slotsWithProducts = await Promise.all(
      slots.map(async (slot) => ({
        id: slot.id,
        deliveryTime: slot.deliveryTime,
        freezeTime: slot.freezeTime,
        isActive: slot.isActive,
        isCapacityFull: slot.isCapacityFull,
        products: await Promise.all(
          slot.products.map(async (product) => ({
            id: product.id,
            name: product.name,
            productQuantity: product.productQuantity,
            shortDescription: product.shortDescription,
            price: product.price.toString(),
            marketPrice: product.marketPrice?.toString() || null,
            unit: product.unit?.shortNotation || null,
            images: scaffoldAssetUrl(
              (product.images as string[]) || []
            ),
            isOutOfStock: product.isOutOfStock,
            storeId: product.storeId,
            nextDeliveryDate: slot.deliveryTime,
          }))
        ),
      }))
    )

    // Store each slot in Redis with key pattern "slot:{id}"
    // for (const slot of slotsWithProducts) {
    //   await redisClient.set(`slot:${slot.id}`, JSON.stringify(slot))
    // }

    // Build and store product-slots map
    // Group slots by productId
    const productSlotsMap: Record<number, SlotInfo[]> = {}

    for (const slot of slotsWithProducts) {
      for (const product of slot.products) {
        if (!productSlotsMap[product.id]) {
          productSlotsMap[product.id] = []
        }
        productSlotsMap[product.id].push({
          id: slot.id,
          deliveryTime: slot.deliveryTime,
          freezeTime: slot.freezeTime,
          isCapacityFull: slot.isCapacityFull,
        })
      }
    }

    // Store each product's slots in Redis with key pattern "product:{id}:slots"
    // for (const [productId, slotInfos] of Object.entries(productSlotsMap)) {
    //   await redisClient.set(
    //     `product:${productId}:slots`,
    //     JSON.stringify(slotInfos)
    //   )
    // }

    console.log('Slot store initialized successfully')
  } catch (error) {
    console.error('Error initializing slot store:', error)
  }
}

export async function getSlotById(slotId: number): Promise<SlotWithProducts | null> {
  try {
    // const key = `slot:${slotId}`
    // const data = await redisClient.get(key)
    // if (!data) return null
    // return JSON.parse(data) as SlotWithProducts

    const slots = await getAllSlotsWithProductsForCache()
    const slot = slots.find(s => s.id === slotId)
    if (!slot) return null

    return transformSlotToStoreSlot(slot)
  } catch (error) {
    console.error(`Error getting slot ${slotId}:`, error)
    return null
  }
}

export async function getAllSlots(): Promise<SlotWithProducts[]> {
  try {
    // Get all keys matching the pattern "slot:*"
    // const keys = await redisClient.KEYS('slot:*')
    //
    // if (keys.length === 0) return []
    //
    // // Get all slots using MGET for better performance
    // const slotsData = await redisClient.MGET(keys)
    //
    // const slots: SlotWithProducts[] = []
    // for (const slotData of slotsData) {
    //   if (slotData) {
    //     slots.push(JSON.parse(slotData) as SlotWithProducts)
    //   }
    // }
    //
    // return slots

    return fetchAllTransformedSlots()
  } catch (error) {
    console.error('Error getting all slots:', error)
    return []
  }
}

export async function getProductSlots(productId: number): Promise<SlotInfo[]> {
  try {
    // const key = `product:${productId}:slots`
    // const data = await redisClient.get(key)
    // if (!data) return []
    // return JSON.parse(data) as SlotInfo[]

    const slots = await getAllSlotsWithProductsForCache()
    const productSlots: SlotInfo[] = []

    for (const slot of slots) {
      const hasProduct = slot.products.some(p => p.id === productId)
      if (hasProduct) {
        productSlots.push(extractSlotInfo(slot))
      }
    }

    return productSlots
  } catch (error) {
    console.error(`Error getting slots for product ${productId}:`, error)
    return []
  }
}

export async function getAllProductsSlots(): Promise<Record<number, SlotInfo[]>> {
  try {
    // Get all keys matching the pattern "product:*:slots"
    // const keys = await redisClient.KEYS('product:*:slots')
    //
    // if (keys.length === 0) return {}
    //
    // // Get all product slots using MGET for better performance
    // const productsData = await redisClient.MGET(keys)
    //
    // const result: Record<number, SlotInfo[]> = {}
    // for (const key of keys) {
    //   // Extract productId from key "product:{id}:slots"
    //   const match = key.match(/product:(\d+):slots/)
    //   if (match) {
    //     const productId = parseInt(match[1], 10)
    //     const dataIndex = keys.indexOf(key)
    //     if (productsData[dataIndex]) {
    //       result[productId] = JSON.parse(productsData[dataIndex]) as SlotInfo[]
    //     }
    //   }
    // }
    //
    // return result

    const slots = await getAllSlotsWithProductsForCache()
    const result: Record<number, SlotInfo[]> = {}

    for (const slot of slots) {
      const slotInfo = extractSlotInfo(slot)
      for (const product of slot.products) {
        const productId = product.id
        if (!result[productId]) {
          result[productId] = []
        }
        result[productId].push(slotInfo)
      }
    }

    return result
  } catch (error) {
    console.error('Error getting all products slots:', error)
    return {}
  }
}

export async function getMultipleProductsSlots(
  productIds: number[]
): Promise<Record<number, SlotInfo[]>> {
  try {
    if (productIds.length === 0) return {}

    // Build keys for all productIds
    // const keys = productIds.map((id) => `product:${id}:slots`)
    //
    // // Use MGET for batch retrieval
    // const productsData = await redisClient.MGET(keys)
    //
    // const result: Record<number, SlotInfo[]> = {}
    // for (let i = 0; i < productIds.length; i++) {
    //   const data = productsData[i]
    //   if (data) {
    //     const slots = JSON.parse(data) as SlotInfo[]
    //     // Filter out slots that are at full capacity
    //     result[productIds[i]] = slots.filter((slot) => !slot.isCapacityFull)
    //   }
    // }
    //
    // return result

    const slots = await getAllSlotsWithProductsForCache()
    const productIdSet = new Set(productIds)
    const result: Record<number, SlotInfo[]> = {}

    for (const productId of productIds) {
      result[productId] = []
    }

    for (const slot of slots) {
      const slotInfo = extractSlotInfo(slot)
      for (const product of slot.products) {
        const pid = product.id
        if (productIdSet.has(pid) && !slot.isCapacityFull) {
          result[pid].push(slotInfo)
        }
      }
    }

    return result
  } catch (error) {
    console.error('Error getting products slots:', error)
    return {}
  }
}
