import { GraphQLError } from 'graphql'

import { prisma } from '../../../lib/prisma'
import { Context } from '../../context'
import { DomainResolvers } from '../shared/types'

// Logistics Domain Resolvers - управление логистикой и маршрутами
export const logisticsDomainResolvers: DomainResolvers = {
  Query: {
    // Логистика организации
    myLogistics: async (_: unknown, __: unknown, context: Context) => {
      if (!context.user) {
        throw new GraphQLError('Требуется авторизация', {
          extensions: { code: 'UNAUTHENTICATED' },
        })
      }

      const currentUser = await prisma.user.findUnique({
        where: { id: context.user.id },
        include: { organization: true },
      })

      if (!currentUser?.organization) {
        throw new GraphQLError('У пользователя нет организации')
      }

      const organizationId = currentUser.organization.id

      console.warn('🚚 MY_LOGISTICS RESOLVER CALLED:', {
        userId: context.user.id,
        organizationId,
        organizationType: currentUser.organization.type,
        timestamp: new Date().toISOString(),
      })

      // Получаем логистические маршруты организации
      const logistics = await prisma.logistics.findMany({
        where: { organizationId },
        include: {
          organization: {
            select: {
              id: true,
              name: true,
              fullName: true,
              type: true,
            },
          },
        },
        orderBy: { createdAt: 'desc' },
      })

      console.warn('📊 MY_LOGISTICS RESULT:', {
        logisticsCount: logistics.length,
        organizationType: currentUser.organization.type,
      })

      return logistics
    },

    // Логистика конкретной организации (для партнеров)
    organizationLogistics: async (_: unknown, args: { organizationId: string }, context: Context) => {
      if (!context.user) {
        throw new GraphQLError('Требуется авторизация', {
          extensions: { code: 'UNAUTHENTICATED' },
        })
      }

      const currentUser = await prisma.user.findUnique({
        where: { id: context.user.id },
        include: { organization: true },
      })

      if (!currentUser?.organization) {
        throw new GraphQLError('У пользователя нет организации')
      }

      console.warn('🏢 ORGANIZATION_LOGISTICS RESOLVER CALLED:', {
        requestedOrganizationId: args.organizationId,
        currentOrganizationId: currentUser.organization.id,
        timestamp: new Date().toISOString(),
      })

      // Проверяем права доступа - только партнеры или сама организация
      let hasAccess = false

      // Если запрашиваем свою логистику
      if (args.organizationId === currentUser.organization.id) {
        hasAccess = true
      } else {
        // Проверяем, есть ли партнерство
        const partnership = await prisma.counterparty.findFirst({
          where: {
            organizationId: currentUser.organization.id,
            counterpartyId: args.organizationId,
          },
        })
        hasAccess = !!partnership
      }

      if (!hasAccess) {
        throw new GraphQLError('Нет доступа к логистике этой организации', {
          extensions: { code: 'FORBIDDEN' },
        })
      }

      // Получаем логистические маршруты организации
      const logistics = await prisma.logistics.findMany({
        where: { organizationId: args.organizationId },
        include: {
          organization: {
            select: {
              id: true,
              name: true,
              fullName: true,
              type: true,
            },
          },
        },
        orderBy: { createdAt: 'desc' },
      })

      return logistics
    },

    // Логистические партнеры (организации-логисты)
    logisticsPartners: async (_: unknown, __: unknown, context: Context) => {
      if (!context.user) {
        throw new GraphQLError('Требуется авторизация', {
          extensions: { code: 'UNAUTHENTICATED' },
        })
      }

      const currentUser = await prisma.user.findUnique({
        where: { id: context.user.id },
        include: { organization: true },
      })

      if (!currentUser?.organization) {
        throw new GraphQLError('У пользователя нет организации')
      }

      console.warn('📦 LOGISTICS_PARTNERS RESOLVER CALLED:', {
        organizationId: currentUser.organization.id,
        organizationType: currentUser.organization.type,
        timestamp: new Date().toISOString(),
      })

      // Получаем логистические компании среди контрагентов
      const logisticsPartners = await prisma.counterparty.findMany({
        where: {
          organizationId: currentUser.organization.id,
          counterparty: {
            type: 'LOGIST',
          },
        },
        include: {
          counterparty: {
            include: {
              users: true,
              apiKeys: true,
            },
          },
        },
        orderBy: {
          createdAt: 'desc',
        },
      })

      const partners = logisticsPartners.map((partnership) => partnership.counterparty)

      console.warn('📊 LOGISTICS_PARTNERS RESULT:', {
        partnersCount: partners.length,
        organizationType: currentUser.organization.type,
      })

      return partners
    },
  },

  Mutation: {
    // Создать логистический маршрут
    createLogistics: async (
      _: unknown,
      args: {
        input: {
          fromAddress: string
          toAddress: string
          fromCoordinates?: string
          toCoordinates?: string
          distance?: number
          estimatedTime?: number
          cost?: number
          vehicleType?: string
          maxWeight?: number
          maxVolume?: number
          notes?: string
        }
      },
      context: Context,
    ) => {
      console.warn('🆕 CREATE_LOGISTICS - ВЫЗВАН:', {
        fromAddress: args.input.fromAddress,
        toAddress: args.input.toAddress,
        vehicleType: args.input.vehicleType,
        timestamp: new Date().toISOString(),
      })

      if (!context.user) {
        throw new GraphQLError('Требуется авторизация', {
          extensions: { code: 'UNAUTHENTICATED' },
        })
      }

      const currentUser = await prisma.user.findUnique({
        where: { id: context.user.id },
        include: { organization: true },
      })

      if (!currentUser?.organization) {
        throw new GraphQLError('У пользователя нет организации')
      }

      // Только логистические компании могут создавать маршруты
      if (currentUser.organization.type !== 'LOGIST') {
        throw new GraphQLError('Только логистические компании могут создавать маршруты')
      }

      try {
        const logistics = await prisma.logistics.create({
          data: {
            organizationId: currentUser.organization.id,
            fromAddress: args.input.fromAddress,
            toAddress: args.input.toAddress,
            fromCoordinates: args.input.fromCoordinates,
            toCoordinates: args.input.toCoordinates,
            distance: args.input.distance,
            estimatedTime: args.input.estimatedTime,
            cost: args.input.cost,
            vehicleType: args.input.vehicleType,
            maxWeight: args.input.maxWeight,
            maxVolume: args.input.maxVolume,
            notes: args.input.notes,
          },
          include: {
            organization: {
              select: {
                id: true,
                name: true,
                fullName: true,
                type: true,
              },
            },
          },
        })

        console.warn('✅ ЛОГИСТИЧЕСКИЙ МАРШРУТ СОЗДАН:', {
          logisticsId: logistics.id,
          organizationId: currentUser.organization.id,
          fromAddress: args.input.fromAddress,
          toAddress: args.input.toAddress,
          cost: args.input.cost,
        })

        return {
          success: true,
          message: 'Логистический маршрут успешно создан',
          logistics,
        }
      } catch (error) {
        console.error('Error creating logistics:', error)
        return {
          success: false,
          message: 'Ошибка при создании логистического маршрута',
          logistics: null,
        }
      }
    },

    // Обновить логистический маршрут
    updateLogistics: async (
      _: unknown,
      args: {
        id: string
        input: {
          fromAddress?: string
          toAddress?: string
          fromCoordinates?: string
          toCoordinates?: string
          distance?: number
          estimatedTime?: number
          cost?: number
          vehicleType?: string
          maxWeight?: number
          maxVolume?: number
          notes?: string
        }
      },
      context: Context,
    ) => {
      console.warn('📝 UPDATE_LOGISTICS - ВЫЗВАН:', {
        logisticsId: args.id,
        hasUpdates: Object.keys(args.input).length,
        timestamp: new Date().toISOString(),
      })

      if (!context.user) {
        throw new GraphQLError('Требуется авторизация', {
          extensions: { code: 'UNAUTHENTICATED' },
        })
      }

      const currentUser = await prisma.user.findUnique({
        where: { id: context.user.id },
        include: { organization: true },
      })

      if (!currentUser?.organization) {
        throw new GraphQLError('У пользователя нет организации')
      }

      try {
        // Проверяем, что маршрут принадлежит текущей организации
        const existingLogistics = await prisma.logistics.findFirst({
          where: {
            id: args.id,
            organizationId: currentUser.organization.id,
          },
        })

        if (!existingLogistics) {
          return {
            success: false,
            message: 'Логистический маршрут не найден или нет доступа',
            logistics: null,
          }
        }

        // Обновляем маршрут
        const updatedLogistics = await prisma.logistics.update({
          where: { id: args.id },
          data: {
            ...args.input,
            updatedAt: new Date(),
          },
          include: {
            organization: {
              select: {
                id: true,
                name: true,
                fullName: true,
                type: true,
              },
            },
          },
        })

        console.warn('✅ ЛОГИСТИЧЕСКИЙ МАРШРУТ ОБНОВЛЕН:', {
          logisticsId: args.id,
          organizationId: currentUser.organization.id,
          updatedFields: Object.keys(args.input),
        })

        return {
          success: true,
          message: 'Логистический маршрут успешно обновлен',
          logistics: updatedLogistics,
        }
      } catch (error) {
        console.error('Error updating logistics:', error)
        return {
          success: false,
          message: 'Ошибка при обновлении логистического маршрута',
          logistics: null,
        }
      }
    },

    // Удалить логистический маршрут
    deleteLogistics: async (_: unknown, args: { id: string }, context: Context) => {
      console.warn('🗑️ DELETE_LOGISTICS - ВЫЗВАН:', {
        logisticsId: args.id,
        timestamp: new Date().toISOString(),
      })

      if (!context.user) {
        throw new GraphQLError('Требуется авторизация', {
          extensions: { code: 'UNAUTHENTICATED' },
        })
      }

      const currentUser = await prisma.user.findUnique({
        where: { id: context.user.id },
        include: { organization: true },
      })

      if (!currentUser?.organization) {
        throw new GraphQLError('У пользователя нет организации')
      }

      try {
        // Проверяем, что маршрут принадлежит текущей организации
        const existingLogistics = await prisma.logistics.findFirst({
          where: {
            id: args.id,
            organizationId: currentUser.organization.id,
          },
        })

        if (!existingLogistics) {
          return {
            success: false,
            message: 'Логистический маршрут не найден или нет доступа',
          }
        }

        // Проверяем, что маршрут не используется в активных заказах
        const activeSupplyOrders = await prisma.supplyOrder.findMany({
          where: {
            logisticsPartnerId: currentUser.organization.id,
            status: { in: ['CONFIRMED', 'IN_TRANSIT'] },
          },
        })

        if (activeSupplyOrders.length > 0) {
          return {
            success: false,
            message: 'Нельзя удалить маршрут, используемый в активных заказах',
          }
        }

        // Удаляем маршрут
        await prisma.logistics.delete({
          where: { id: args.id },
        })

        console.warn('🗑️ ЛОГИСТИЧЕСКИЙ МАРШРУТ УДАЛЕН:', {
          logisticsId: args.id,
          organizationId: currentUser.organization.id,
        })

        return {
          success: true,
          message: 'Логистический маршрут успешно удален',
        }
      } catch (error) {
        console.error('Error deleting logistics:', error)
        return {
          success: false,
          message: 'Ошибка при удалении логистического маршрута',
        }
      }
    },

    // Назначить логистику к заказу (дублируется из supplies, но с другой логикой)
    assignLogisticsToSupply: async (
      _: unknown,
      args: {
        supplyOrderId: string
        logisticsId: string
        estimatedDeliveryDate?: string
        specialInstructions?: string
      },
      context: Context,
    ) => {
      console.warn('🚛 ASSIGN_LOGISTICS - ВЫЗВАН:', {
        supplyOrderId: args.supplyOrderId,
        logisticsId: args.logisticsId,
        timestamp: new Date().toISOString(),
      })

      if (!context.user) {
        throw new GraphQLError('Требуется авторизация', {
          extensions: { code: 'UNAUTHENTICATED' },
        })
      }

      const currentUser = await prisma.user.findUnique({
        where: { id: context.user.id },
        include: { organization: true },
      })

      if (!currentUser?.organization) {
        throw new GraphQLError('У пользователя нет организации')
      }

      try {
        // Проверяем, что это логистическая компания
        if (currentUser.organization.type !== 'LOGIST') {
          throw new GraphQLError('Только логистические компании могут назначать свои маршруты')
        }

        // Проверяем заказ поставки
        const supplyOrder = await prisma.supplyOrder.findFirst({
          where: {
            id: args.supplyOrderId,
            status: 'CONFIRMED',
            logisticsPartnerId: currentUser.organization.id,
          },
        })

        if (!supplyOrder) {
          return {
            success: false,
            message: 'Заказ поставки не найден или не назначен этой логистической компании',
            supplyOrder: null,
          }
        }

        // Проверяем логистический маршрут
        const logistics = await prisma.logistics.findFirst({
          where: {
            id: args.logisticsId,
            organizationId: currentUser.organization.id,
          },
        })

        if (!logistics) {
          return {
            success: false,
            message: 'Логистический маршрут не найден',
            supplyOrder: null,
          }
        }

        // Назначаем маршрут и обновляем статус
        const updatedSupplyOrder = await prisma.supplyOrder.update({
          where: { id: args.supplyOrderId },
          data: {
            // TODO: добавить поле logisticsId когда будет в модели
            deliveryDate: args.estimatedDeliveryDate
              ? new Date(args.estimatedDeliveryDate)
              : supplyOrder.deliveryDate,
            status: 'IN_TRANSIT',
            notes: args.specialInstructions || supplyOrder.notes,
            updatedAt: new Date(),
          },
          include: {
            organization: true,
            fulfillmentCenter: true,
            logisticsPartner: true,
            items: {
              include: {
                product: true,
              },
            },
          },
        })

        console.warn('✅ ЛОГИСТИКА НАЗНАЧЕНА НА ЗАКАЗ:', {
          supplyOrderId: args.supplyOrderId,
          logisticsId: args.logisticsId,
          logisticsCompany: currentUser.organization.name || currentUser.organization.fullName,
          route: `${logistics.fromAddress} → ${logistics.toAddress}`,
        })

        return {
          success: true,
          message: 'Логистический маршрут назначен на заказ',
          supplyOrder: updatedSupplyOrder,
        }
      } catch (error) {
        console.error('Error assigning logistics:', error)
        return {
          success: false,
          message: 'Ошибка при назначении логистического маршрута',
          supplyOrder: null,
        }
      }
    },
  },
}