import { GraphQLError } from 'graphql'

import { processSellerConsumableSupplyReceipt } from '../../../lib/inventory-management'
import { prisma } from '../../../lib/prisma'
import { notifyOrganization } from '../../../lib/realtime'
import { Context } from '../../context'
import { DomainResolvers } from '../shared/types'

// Seller Consumables Domain Resolvers - система поставок расходников селлера

// =============================================================================
// 🔐 AUTHENTICATION HELPERS
// =============================================================================

const withAuth = (resolver: any) => {
  return async (parent: any, args: any, context: Context) => {
    console.log('🔐 SELLER CONSUMABLES DOMAIN AUTH CHECK:', { 
      hasUser: !!context.user, 
      userId: context.user?.id,
      organizationId: context.user?.organizationId, 
    })
    if (!context.user) {
      console.error('❌ AUTH FAILED: No user in context')
      throw new GraphQLError('Требуется авторизация', {
        extensions: { code: 'UNAUTHENTICATED' },
      })
    }
    console.log('✅ AUTH PASSED: Calling resolver')
    try {
      const result = await resolver(parent, args, context)
      console.log('🎯 RESOLVER RESULT TYPE:', typeof result, result === null ? 'NULL RESULT!' : 'Has result')
      return result
    } catch (error) {
      console.error('💥 RESOLVER ERROR:', error)
      throw error
    }
  }
}

const checkOrganizationAccess = async (userId: string) => {
  const user = await prisma.user.findUnique({
    where: { id: userId },
    include: { organization: true },
  })

  if (!user?.organizationId) {
    throw new GraphQLError('Пользователь не привязан к организации', {
      extensions: { code: 'FORBIDDEN' },
    })
  }

  return user
}

// =============================================================================
// 📦 SELLER CONSUMABLES DOMAIN RESOLVERS
// =============================================================================

export const sellerConsumablesResolvers: DomainResolvers = {
  Query: {
    // Мои поставки (для селлеров - заказы которые я создал)
    mySellerConsumableSupplies: withAuth(async (_: unknown, __: unknown, context: Context) => {
      console.log('🔍 MY_SELLER_CONSUMABLE_SUPPLIES DOMAIN QUERY STARTED:', { userId: context.user?.id })
      
      try {
        const user = await checkOrganizationAccess(context.user!.id)

        if (user.organization?.type !== 'SELLER') {
          console.log('✅ Not a seller, returning empty array')
          return [] // Возвращаем пустой массив если пользователь не селлер
        }

        const supplies = await prisma.sellerConsumableSupplyOrder.findMany({
          where: {
            sellerId: user.organizationId!,
          },
          include: {
            seller: true,
            fulfillmentCenter: true,
            supplier: true,
            logisticsPartner: true,
            receivedBy: true,
            items: {
              include: {
                product: true,
              },
            },
          },
          orderBy: {
            createdAt: 'desc',
          },
        })

        console.log('✅ MY_SELLER_CONSUMABLE_SUPPLIES DOMAIN SUCCESS:', { count: supplies.length })
        return supplies
      } catch (error) {
        console.error('❌ MY_SELLER_CONSUMABLE_SUPPLIES DOMAIN ERROR:', error)
        return []
      }
    }),

    // Входящие поставки (для фулфилмента - заказы селлеров для нас)
    incomingSellerSupplies: withAuth(async (_: unknown, __: unknown, context: Context) => {
      console.log('🔍 INCOMING_SELLER_SUPPLIES DOMAIN QUERY STARTED:', { userId: context.user?.id })
      
      try {
        const user = await checkOrganizationAccess(context.user!.id)

        const supplies = await prisma.sellerConsumableSupplyOrder.findMany({
          where: {
            fulfillmentCenterId: user.organizationId!,
          },
          include: {
            seller: true,
            fulfillmentCenter: true,
            supplier: true,
            logisticsPartner: true,
            receivedBy: true,
            items: {
              include: {
                product: true,
              },
            },
          },
          orderBy: {
            createdAt: 'desc',
          },
        })

        console.log('✅ INCOMING_SELLER_SUPPLIES DOMAIN SUCCESS:', { count: supplies.length })
        return supplies
      } catch (error) {
        console.error('❌ INCOMING_SELLER_SUPPLIES DOMAIN ERROR:', error)
        return []
      }
    }),

    // Мои запросы поставок (для поставщиков - заказы которые адресованы нам)
    mySellerSupplyRequests: withAuth(async (_: unknown, __: unknown, context: Context) => {
      console.log('🔍 MY_SELLER_SUPPLY_REQUESTS DOMAIN QUERY STARTED:', { userId: context.user?.id })
      
      try {
        const user = await checkOrganizationAccess(context.user!.id)

        const supplies = await prisma.sellerConsumableSupplyOrder.findMany({
          where: {
            supplierId: user.organizationId!,
          },
          include: {
            seller: true,
            fulfillmentCenter: true,
            supplier: true,
            logisticsPartner: true,
            receivedBy: true,
            items: {
              include: {
                product: true,
              },
            },
          },
          orderBy: {
            createdAt: 'desc',
          },
        })

        console.log('✅ MY_SELLER_SUPPLY_REQUESTS DOMAIN SUCCESS:', { count: supplies.length })
        return supplies
      } catch (error) {
        console.error('❌ MY_SELLER_SUPPLY_REQUESTS DOMAIN ERROR:', error)
        return []
      }
    }),

    // Детали конкретной поставки селлерских расходников
    sellerConsumableSupply: withAuth(async (_: unknown, args: { id: string }, context: Context) => {
      console.log('🔍 SELLER_CONSUMABLE_SUPPLY DOMAIN QUERY STARTED:', { 
        userId: context.user?.id,
        supplyId: args.id,
      })
      
      try {
        const user = await checkOrganizationAccess(context.user!.id)

        const supply = await prisma.sellerConsumableSupplyOrder.findFirst({
          where: { id: args.id },
          include: {
            seller: true,
            fulfillmentCenter: true,
            supplier: true,
            logisticsPartner: true,
            receivedBy: true,
            items: {
              include: {
                product: true,
              },
            },
          },
        })

        console.log('✅ SELLER_CONSUMABLE_SUPPLY DOMAIN SUCCESS:', { 
          found: !!supply,
          supplyId: supply?.id,
        })
        return supply
      } catch (error) {
        console.error('❌ SELLER_CONSUMABLE_SUPPLY DOMAIN ERROR:', error)
        return null
      }
    }),
  },

  Mutation: {
    // Создание поставки расходников селлера
    createSellerConsumableSupply: withAuth(async (_: unknown, args: { input: any }, context: Context) => {
      console.log('🔍 CREATE_SELLER_CONSUMABLE_SUPPLY DOMAIN MUTATION STARTED:', { 
        userId: context.user?.id,
        inputKeys: Object.keys(args.input),
      })
      
      try {
        const user = await checkOrganizationAccess(context.user!.id)

        const { fulfillmentCenterId, supplierId, requestedDeliveryDate, items, logisticsPartnerId, notes } = args.input

        // Проверяем фулфилмент-центр
        const fulfillmentCenter = await prisma.organization.findFirst({
          where: { id: fulfillmentCenterId },
          include: {
            counterpartyOf: {
              where: { organizationId: user.organizationId! },
            },
          },
        })

        if (!fulfillmentCenter || fulfillmentCenter.counterpartyOf.length === 0) {
          throw new GraphQLError('Фулфилмент-центр недоступен')
        }

        // Проверяем поставщика
        const supplier = await prisma.organization.findFirst({
          where: { id: supplierId },
          include: {
            counterpartyOf: {
              where: { organizationId: user.organizationId! },
            },
          },
        })

        if (!supplier || supplier.counterpartyOf.length === 0) {
          throw new GraphQLError('Поставщик недоступен')
        }

        // Подготавливаем товары и подсчитываем общую стоимость
        const orderItems = []
        let totalAmount = 0

        for (const item of items) {
          const product = await prisma.product.findUnique({
            where: { id: item.productId },
          })

          if (!product) {
            throw new GraphQLError(`Товар с ID ${item.productId} не найден`)
          }

          const itemTotalPrice = parseFloat(product.price.toString()) * item.requestedQuantity
          totalAmount += itemTotalPrice

          orderItems.push({
            productId: item.productId,
            requestedQuantity: item.requestedQuantity,
            unitPrice: product.price,
            totalPrice: itemTotalPrice,
          })
        }

        // Создаем заказ
        const supplyOrder = await prisma.sellerConsumableSupplyOrder.create({
          data: {
            sellerId: user.organizationId!,
            fulfillmentCenterId,
            supplierId,
            logisticsPartnerId,
            requestedDeliveryDate: new Date(requestedDeliveryDate),
            status: 'PENDING',
            notes,
            totalCostWithDelivery: totalAmount,
            items: {
              create: orderItems,
            },
          },
          include: {
            seller: true,
            fulfillmentCenter: true,
            supplier: true,
            logisticsPartner: true,
            items: {
              include: {
                product: true,
              },
            },
          },
        })

        // Резервируем товары у поставщика
        for (const item of orderItems) {
          await prisma.product.update({
            where: { id: item.productId },
            data: {
              ordered: {
                increment: item.requestedQuantity,
              },
            },
          })
        }

        // Отправляем уведомления
        await notifyOrganization(
          supplierId,
          `Новый заказ от ${user.organization.name}`,
          'NEW_SUPPLY_ORDER',
          { orderId: supplyOrder.id },
        )

        console.log('✅ CREATE_SELLER_CONSUMABLE_SUPPLY DOMAIN SUCCESS:', { 
          supplyOrderId: supplyOrder.id,
          totalAmount,
          itemsCount: orderItems.length,
        })

        return {
          success: true,
          message: 'Поставка успешно создана',
          supplyOrder: await prisma.sellerConsumableSupplyOrder.findUnique({
            where: { id: supplyOrder.id },
            include: {
              seller: true,
              fulfillmentCenter: true,
              supplier: true,
              logisticsPartner: true,
              receivedBy: true,
              items: {
                include: {
                  product: true,
                },
              },
            },
          }),
        }
      } catch (error) {
        console.error('❌ CREATE_SELLER_CONSUMABLE_SUPPLY DOMAIN ERROR:', error)
        
        if (error instanceof GraphQLError) {
          throw error
        }

        throw new GraphQLError('Ошибка создания поставки')
      }
    }),

    // Обновление статуса поставки
    updateSellerSupplyStatus: withAuth(async (
      _: unknown,
      args: { id: string; status: string; notes?: string },
      context: Context,
    ) => {
      console.log('🔍 UPDATE_SELLER_SUPPLY_STATUS DOMAIN MUTATION STARTED:', { 
        userId: context.user?.id,
        supplyId: args.id,
        newStatus: args.status,
      })
      
      try {
        const user = await checkOrganizationAccess(context.user!.id)

        const supply = await prisma.sellerConsumableSupplyOrder.findFirst({
          where: { id: args.id },
          include: {
            seller: true,
            supplier: true,
            fulfillmentCenter: true,
            items: {
              include: {
                product: true,
              },
            },
          },
        })

        if (!supply) {
          throw new GraphQLError('Поставка не найдена')
        }

        const updateData: any = {
          status: args.status,
          updatedAt: new Date(),
        }

        if (args.notes) {
          updateData.notes = args.notes
        }

        if (args.status === 'RECEIVED') {
          updateData.receivedAt = new Date()
          updateData.receivedById = user.id
        }

        const updatedSupply = await prisma.sellerConsumableSupplyOrder.update({
          where: { id: args.id },
          data: updateData,
          include: {
            seller: true,
            fulfillmentCenter: true,
            supplier: true,
            logisticsPartner: true,
            receivedBy: true,
            items: {
              include: {
                product: true,
              },
            },
          },
        })

        // Если поставка получена, добавляем товары на склад
        if (args.status === 'RECEIVED') {
          await processSellerConsumableSupplyReceipt(supply.id)

          for (const item of supply.items) {
            // V2: Создаем запись в SellerConsumableInventory вместо Supply
            await prisma.sellerConsumableInventory.upsert({
              where: {
                sellerId_fulfillmentCenterId_productId: {
                  sellerId: supply.sellerId,
                  fulfillmentCenterId: supply.fulfillmentCenterId,
                  productId: item.productId,
                },
              },
              update: {
                // Увеличиваем остаток при повторной поставке
                currentStock: {
                  increment: item.receivedQuantity || item.requestedQuantity,
                },
                totalReceived: {
                  increment: item.receivedQuantity || item.requestedQuantity,
                },
                lastSupplyDate: new Date(),
                updatedAt: new Date(),
              },
              create: {
                sellerId: supply.sellerId,
                fulfillmentCenterId: supply.fulfillmentCenterId,
                productId: item.productId,
                currentStock: item.receivedQuantity || item.requestedQuantity,
                minStock: 0, // TODO: настраивается селлером
                totalReceived: item.receivedQuantity || item.requestedQuantity,
                totalUsed: 0,
                reservedStock: 0,
                lastSupplyDate: new Date(),
                notes: `Поступление от поставки ${supply.id}`,
                // Связи создаются автоматически через ID
              },
            })
            
            console.log('✅ V2 MIGRATION: Created SellerConsumableInventory record', {
              sellerId: supply.sellerId,
              fulfillmentCenterId: supply.fulfillmentCenterId,
              productId: item.productId,
              quantity: item.receivedQuantity || item.requestedQuantity,
            })
          }
        }

        console.log('✅ UPDATE_SELLER_SUPPLY_STATUS DOMAIN SUCCESS:', { 
          supplyId: updatedSupply.id,
          oldStatus: supply.status,
          newStatus: args.status,
        })

        return updatedSupply
      } catch (error) {
        console.error('❌ UPDATE_SELLER_SUPPLY_STATUS DOMAIN ERROR:', error)
        
        if (error instanceof GraphQLError) {
          throw error
        }

        throw new GraphQLError('Ошибка обновления статуса поставки')
      }
    }),

    // Отмена поставки
    cancelSellerSupply: withAuth(async (_: unknown, args: { id: string }, context: Context) => {
      console.log('🔍 CANCEL_SELLER_SUPPLY DOMAIN MUTATION STARTED:', { 
        userId: context.user?.id,
        supplyId: args.id,
      })
      
      try {
        const user = await checkOrganizationAccess(context.user!.id)

        const supply = await prisma.sellerConsumableSupplyOrder.findFirst({
          where: { id: args.id },
          include: {
            seller: true,
            items: {
              include: {
                product: true,
              },
            },
          },
        })

        if (!supply) {
          throw new GraphQLError('Поставка не найдена')
        }

        if (!['PENDING', 'CONFIRMED'].includes(supply.status)) {
          throw new GraphQLError('Поставку в данном статусе нельзя отменить')
        }

        // Отменяем заказ в транзакции
        const cancelledSupply = await prisma.$transaction(async (tx) => {
          const updated = await tx.sellerConsumableSupplyOrder.update({
            where: { id: args.id },
            data: {
              status: 'CANCELLED',
              updatedAt: new Date(),
            },
            include: {
              seller: true,
              fulfillmentCenter: true,
              supplier: true,
              items: {
                include: {
                  product: true,
                },
              },
            },
          })

          // Освобождаем зарезервированные товары у поставщика
          for (const item of supply.items) {
            await tx.product.update({
              where: { id: item.productId },
              data: {
                ordered: {
                  decrement: item.requestedQuantity,
                },
              },
            })
          }

          return updated
        })

        // Уведомления об отмене
        if (supply.supplierId) {
          await notifyOrganization(
            supply.supplierId,
            `Селлер ${user.organization.name} отменил заказ`,
            'SUPPLY_CANCELLED',
            { orderId: args.id },
          )
        }

        await notifyOrganization(
          supply.fulfillmentCenterId,
          `Селлер ${user.organization.name} отменил поставку`,
          'SUPPLY_CANCELLED',
          { orderId: args.id },
        )

        console.log('✅ CANCEL_SELLER_SUPPLY DOMAIN SUCCESS:', { 
          supplyId: cancelledSupply.id,
          previousStatus: supply.status,
        })

        return cancelledSupply
      } catch (error) {
        console.error('❌ CANCEL_SELLER_SUPPLY DOMAIN ERROR:', error)

        if (error instanceof GraphQLError) {
          throw error
        }

        throw new GraphQLError('Ошибка отмены поставки')
      }
    }),
  },
}

console.warn('🔥 SELLER CONSUMABLES DOMAIN МОДУЛЬ ЭКСПОРТЫ ГОТОВЫ')