import { Prisma } from '@prisma/client'

import { prisma } from './prisma'

/**
 * СИСТЕМА УПРАВЛЕНИЯ СКЛАДСКИМИ ОСТАТКАМИ V2
 * 
 * Автоматически обновляет инвентарь при:
 * - Приемке поставок (увеличивает остатки)
 * - Отгрузке селлерам (уменьшает остатки)
 * - Списании брака (уменьшает остатки)
 */

export interface InventoryMovement {
  fulfillmentCenterId: string
  productId: string
  quantity: number
  type: 'INCOMING' | 'OUTGOING' | 'DEFECT'
  sourceId: string // ID поставки или отгрузки
  sourceType: 'SUPPLY_ORDER' | 'SELLER_SHIPMENT' | 'DEFECT_WRITEOFF'
  unitCost?: number // Себестоимость для расчета средней цены
  notes?: string
}

/**
 * Основная функция обновления инвентаря
 */
export async function updateInventory(movement: InventoryMovement): Promise<void> {
  const { fulfillmentCenterId, productId, quantity, type, unitCost } = movement

  // Находим или создаем запись в инвентаре
  const inventory = await prisma.fulfillmentConsumableInventory.upsert({
    where: {
      fulfillmentCenterId_productId: {
        fulfillmentCenterId,
        productId,
      },
    },
    create: {
      fulfillmentCenterId,
      productId,
      currentStock: type === 'INCOMING' ? quantity : -quantity,
      totalReceived: type === 'INCOMING' ? quantity : 0,
      totalShipped: type === 'OUTGOING' ? quantity : 0,
      averageCost: unitCost || 0,
      lastSupplyDate: type === 'INCOMING' ? new Date() : undefined,
      lastUsageDate: type === 'OUTGOING' ? new Date() : undefined,
    },
    update: {
      // Обновляем остатки в зависимости от типа движения
      currentStock: {
        increment: type === 'INCOMING' ? quantity : -quantity,
      },
      totalReceived: {
        increment: type === 'INCOMING' ? quantity : 0,
      },
      totalShipped: {
        increment: type === 'OUTGOING' ? quantity : 0,
      },
      lastSupplyDate: type === 'INCOMING' ? new Date() : undefined,
      lastUsageDate: type === 'OUTGOING' ? new Date() : undefined,
    },
    include: {
      product: true,
    },
  })

  // Пересчитываем среднюю себестоимость при поступлении
  if (type === 'INCOMING' && unitCost) {
    await recalculateAverageCost(inventory.id, quantity, unitCost)
  }

  console.warn('✅ Inventory updated:', {
    productName: inventory.product.name,
    movement: `${type === 'INCOMING' ? '+' : '-'}${quantity}`,
    newStock: inventory.currentStock,
    fulfillmentCenter: fulfillmentCenterId,
  })

  // 🔄 АВТОСИНХРОНИЗАЦИЯ: Синхронизируем с FulfillmentConsumable (Система А)
  if (type === 'INCOMING') {
    try {
      // Ищем существующую запись в каталоге по названию товара
      const existingCatalogItem = await prisma.fulfillmentConsumable.findFirst({
        where: {
          fulfillmentId: fulfillmentCenterId,
          name: inventory.product.name,
        },
      })

      if (existingCatalogItem) {
        // Обновляем существующую запись в каталоге
        await prisma.fulfillmentConsumable.update({
          where: { id: existingCatalogItem.id },
          data: {
            currentStock: inventory.currentStock,
            isAvailable: inventory.currentStock > 0,
            inventoryId: inventory.id,
            updatedAt: new Date(),
          },
        })
        
        console.warn('✅ FulfillmentConsumable updated (existing):', {
          catalogId: existingCatalogItem.id,
          productName: inventory.product.name,
          newStock: inventory.currentStock,
        })
      } else {
        // Создаем новую запись в каталоге
        const newCatalogItem = await prisma.fulfillmentConsumable.create({
          data: {
            fulfillmentId: fulfillmentCenterId,
            inventoryId: inventory.id,
            name: inventory.product.name,
            article: inventory.product.article || '',
            pricePerUnit: 0, // Цену устанавливает фулфилмент вручную
            unit: inventory.product.unit || 'шт',
            minStock: inventory.minStock,
            currentStock: inventory.currentStock,
            isAvailable: inventory.currentStock > 0,
            imageUrl: inventory.product.imageUrl,
            sortOrder: 0,
          },
        })
        
        console.warn('✅ FulfillmentConsumable created (new):', {
          catalogId: newCatalogItem.id,
          productName: inventory.product.name,
          currentStock: inventory.currentStock,
        })
      }
    } catch (syncError) {
      console.error('⚠️ Failed to sync FulfillmentConsumable:', syncError)
      // Не останавливаем процесс, если синхронизация не удалась
    }
  }
}

/**
 * Пересчет средней себестоимости по методу взвешенной средней
 */
async function recalculateAverageCost(inventoryId: string, newQuantity: number, newUnitCost: number): Promise<void> {
  const inventory = await prisma.fulfillmentConsumableInventory.findUnique({
    where: { id: inventoryId },
  })

  if (!inventory) return

  // Рассчитываем новую среднюю стоимость
  const oldTotalCost = parseFloat(inventory.averageCost.toString()) * (inventory.currentStock - newQuantity)
  const newTotalCost = newUnitCost * newQuantity
  const totalQuantity = inventory.currentStock
  
  const newAverageCost = totalQuantity > 0 ? (oldTotalCost + newTotalCost) / totalQuantity : newUnitCost

  await prisma.fulfillmentConsumableInventory.update({
    where: { id: inventoryId },
    data: {
      averageCost: newAverageCost,
    },
  })
}

/**
 * Обработка приемки поставки V2
 */
export async function processSupplyOrderReceipt(
  supplyOrderId: string,
  items: Array<{
    productId: string
    receivedQuantity: number
    unitPrice: number
  }>,
): Promise<void> {
  console.warn(`🔄 Processing supply order receipt: ${supplyOrderId}`)

  // Получаем информацию о поставке
  const supplyOrder = await prisma.fulfillmentConsumableSupplyOrder.findUnique({
    where: { id: supplyOrderId },
    include: { fulfillmentCenter: true },
  })

  if (!supplyOrder) {
    throw new Error(`Supply order not found: ${supplyOrderId}`)
  }

  // Обрабатываем каждую позицию
  for (const item of items) {
    await updateInventory({
      fulfillmentCenterId: supplyOrder.fulfillmentCenterId,
      productId: item.productId,
      quantity: item.receivedQuantity,
      type: 'INCOMING',
      sourceId: supplyOrderId,
      sourceType: 'SUPPLY_ORDER',
      unitCost: item.unitPrice,
      notes: `Приемка заказа ${supplyOrderId}`,
    })
  }

  console.warn(`✅ Supply order ${supplyOrderId} processed successfully`)
}

/**
 * Обрабатывает поступление заказа расходников селлера
 * Автоматически пополняет SellerConsumableInventory при статусе DELIVERED
 */
export async function processSellerConsumableSupplyReceipt(
  supplyOrderId: string,
  items: Array<{
    productId: string
    receivedQuantity: number
    unitPrice: number
  }>,
): Promise<void> {
  console.warn(`🔄 Processing seller consumable supply receipt: ${supplyOrderId}`)

  // Получаем информацию о поставке селлера
  const supplyOrder = await prisma.sellerConsumableSupplyOrder.findUnique({
    where: { id: supplyOrderId },
    include: { 
      seller: true,
      fulfillmentCenter: true,
    },
  })

  if (!supplyOrder) {
    throw new Error(`Seller supply order not found: ${supplyOrderId}`)
  }

  // Обрабатываем каждую позицию расходников селлера
  for (const item of items) {
    await updateSellerInventory({
      sellerId: supplyOrder.sellerId,
      fulfillmentCenterId: supplyOrder.fulfillmentCenterId,
      productId: item.productId,
      quantity: item.receivedQuantity,
      type: 'INCOMING',
      sourceId: supplyOrderId,
      sourceType: 'SELLER_SUPPLY_ORDER',
      unitCost: item.unitPrice,
      notes: `Приемка заказа селлера ${supplyOrderId}`,
    })
  }

  console.warn(`✅ Seller consumable supply receipt processed: ${items.length} items`)
}

/**
 * Обработка отгрузки селлеру
 */
export async function processSellerShipment(
  fulfillmentCenterId: string,
  sellerId: string,
  items: Array<{
    productId: string
    shippedQuantity: number
  }>,
): Promise<void> {
  console.warn(`🔄 Processing seller shipment to ${sellerId}`)

  // Обрабатываем каждую позицию
  for (const item of items) {
    // Проверяем достаточность остатков
    const inventory = await prisma.fulfillmentConsumableInventory.findUnique({
      where: {
        fulfillmentCenterId_productId: {
          fulfillmentCenterId,
          productId: item.productId,
        },
      },
      include: { product: true },
    })

    if (!inventory || inventory.currentStock < item.shippedQuantity) {
      throw new Error(
        `Insufficient stock for product ${inventory?.product.name}. ` +
        `Available: ${inventory?.currentStock || 0}, Required: ${item.shippedQuantity}`,
      )
    }

    await updateInventory({
      fulfillmentCenterId,
      productId: item.productId,
      quantity: item.shippedQuantity,
      type: 'OUTGOING',
      sourceId: sellerId,
      sourceType: 'SELLER_SHIPMENT',
      notes: `Отгрузка селлеру ${sellerId}`,
    })
  }

  console.warn(`✅ Seller shipment to ${sellerId} processed successfully`)
}

/**
 * Проверка критически низких остатков
 */
export async function checkLowStockAlerts(fulfillmentCenterId: string): Promise<Array<{
  productId: string
  productName: string
  currentStock: number
  minStock: number
}>> {
  const lowStockItems = await prisma.fulfillmentConsumableInventory.findMany({
    where: {
      fulfillmentCenterId,
      OR: [
        { currentStock: { lte: prisma.fulfillmentConsumableInventory.fields.minStock } },
        { currentStock: 0 },
      ],
    },
    include: {
      product: true,
    },
  })

  return lowStockItems.map(item => ({
    productId: item.productId,
    productName: item.product.name,
    currentStock: item.currentStock,
    minStock: item.minStock,
  }))
}

/**
 * Получение статистики склада
 */
export async function getInventoryStats(fulfillmentCenterId: string) {
  const stats = await prisma.fulfillmentConsumableInventory.aggregate({
    where: { fulfillmentCenterId },
    _count: { id: true },
    _sum: {
      currentStock: true,
      totalReceived: true,
      totalShipped: true,
    },
  })

  const lowStockCount = await prisma.fulfillmentConsumableInventory.count({
    where: {
      fulfillmentCenterId,
      currentStock: { lte: prisma.fulfillmentConsumableInventory.fields.minStock },
    },
  })

  return {
    totalProducts: stats._count.id,
    totalStock: stats._sum.currentStock || 0,
    totalReceived: stats._sum.totalReceived || 0,
    totalShipped: stats._sum.totalShipped || 0,
    lowStockCount,
  }
}

/**
 * Обновляет складские остатки расходников селлера
 * Аналог updateInventory, но для SellerConsumableInventory
 */
async function updateSellerInventory(operation: {
  sellerId: string
  fulfillmentCenterId: string
  productId: string
  quantity: number
  type: 'INCOMING' | 'OUTGOING' | 'USAGE'
  sourceId: string
  sourceType: 'SELLER_SUPPLY_ORDER' | 'SELLER_USAGE' | 'SELLER_WRITEOFF'
  unitCost?: number
  notes?: string
}): Promise<void> {
  const {
    sellerId,
    fulfillmentCenterId,
    productId,
    quantity,
    type,
    sourceId,
    sourceType,
    unitCost,
    notes,
  } = operation

  console.warn(`📦 Updating seller inventory: ${type} ${quantity} units for product ${productId}`)

  // Находим или создаем запись в инвентаре селлера
  const existingInventory = await prisma.sellerConsumableInventory.findUnique({
    where: {
      sellerId_fulfillmentCenterId_productId: {
        sellerId,
        fulfillmentCenterId,
        productId,
      },
    },
  })

  if (existingInventory) {
    // Обновляем существующую запись
    const stockChange = type === 'INCOMING' ? quantity : -quantity
    const newCurrentStock = Math.max(0, existingInventory.currentStock + stockChange)
    
    // Пересчитываем среднюю стоимость при поступлении
    let newAverageCost = existingInventory.averageCost
    if (type === 'INCOMING' && unitCost) {
      const totalCost = parseFloat(existingInventory.averageCost.toString()) * 
        existingInventory.totalReceived + unitCost * quantity
      const totalQuantity = existingInventory.totalReceived + quantity
      newAverageCost = totalQuantity > 0 ? 
        new Prisma.Decimal(totalCost / totalQuantity) : new Prisma.Decimal(0)
    }

    await prisma.sellerConsumableInventory.update({
      where: { id: existingInventory.id },
      data: {
        currentStock: newCurrentStock,
        totalReceived: type === 'INCOMING' ? existingInventory.totalReceived + quantity : existingInventory.totalReceived,
        totalUsed: type === 'OUTGOING' || type === 'USAGE' ? existingInventory.totalUsed + quantity : existingInventory.totalUsed,
        averageCost: newAverageCost,
        lastSupplyDate: type === 'INCOMING' ? new Date() : existingInventory.lastSupplyDate,
        lastUsageDate: type === 'OUTGOING' || type === 'USAGE' ? new Date() : existingInventory.lastUsageDate,
        notes: notes || existingInventory.notes,
        updatedAt: new Date(),
      },
    })

    console.warn(`✅ Updated seller inventory: ${existingInventory.id} → stock: ${newCurrentStock}`)
  } else if (type === 'INCOMING') {
    // Создаем новую запись только при поступлении
    const newInventory = await prisma.sellerConsumableInventory.create({
      data: {
        sellerId,
        fulfillmentCenterId,
        productId,
        currentStock: quantity,
        totalReceived: quantity,
        totalUsed: 0,
        averageCost: new Prisma.Decimal(unitCost || 0),
        lastSupplyDate: new Date(),
        notes: notes || `Создано при ${sourceType} ${sourceId}`,
      },
    })

    console.warn(`✅ Created new seller inventory: ${newInventory.id} → stock: ${quantity}`)
  } else {
    console.warn(`⚠️ Cannot perform ${type} operation on non-existent seller inventory`)
  }
}