/**
 * Безопасные резолверы для системы поставок
 * 
 * Интегрирует систему безопасности данных с существующими резолверами
 * для обеспечения ролевого доступа и защиты коммерческой информации
 */

import { OrganizationType } from '@prisma/client'
import { GraphQLError } from 'graphql'

import { prisma } from '@/lib/prisma'
import { notifyMany, notifyOrganization } from '@/lib/realtime'

import { SecurityLogger } from '../../lib/security-logger'
import type { Context } from '../context'
import { createSecureResolver, SecurityHelpers } from '../security'
import { CommercialDataAudit } from '../security/commercial-data-audit'
import { ParticipantIsolation } from '../security/participant-isolation'
import { RecipeAccessControl } from '../security/recipe-access-control'
import { SupplyDataFilter } from '../security/supply-data-filter'


/**
 * Интерфейс аргументов для получения поставок
 */
interface GetSupplyOrdersArgs {
  filters?: {
    status?: string
    organizationType?: OrganizationType
    dateFrom?: string
    dateTo?: string
  }
  pagination?: {
    limit?: number
    offset?: number
  }
}

/**
 * Интерфейс для создания заказа поставки
 */
interface CreateSupplyOrderArgs {
  input: {
    partnerId: string
    deliveryDate: string
    fulfillmentCenterId?: string
    logisticsPartnerId?: string
    items: Array<{
      productId: string
      quantity: number
      recipe?: {
        services?: string[]
        fulfillmentConsumables?: string[]
        sellerConsumables?: string[]
        marketplaceCardId?: string
      }
    }>
    notes?: string
    consumableType?: string
    packagesCount?: number
    volume?: number
    routes?: Array<{
      logisticsId?: string
      fromLocation: string
      toLocation: string
      fromAddress?: string
      toAddress?: string
    }>
  }
}

/**
 * Безопасные резолверы поставок
 */
export const secureSuppliesResolvers = {
  Query: {
    /**
     * Безопасный резолвер для получения заказов поставок
     * Применяет фильтрацию по ролям и аудит доступа
     */
    secureSupplyOrders: createSecureResolver(
      async (_: unknown, args: GetSupplyOrdersArgs, 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('У пользователя нет организации')
        }

        // Построение where-клаузы на основе роли
        let whereClause: Record<string, unknown> = {}

        switch (currentUser.organization.type) {
          case 'SELLER':
            // Селлер видит только свои заказы
            whereClause = { organizationId: currentUser.organization.id }
            break

          case 'WHOLESALE':
            // Поставщик видит заказы, где есть его товары
            whereClause = {
              items: {
                some: {
                  product: {
                    organizationId: currentUser.organization.id,
                  },
                },
              },
            }
            break

          case 'FULFILLMENT':
            // Фулфилмент видит заказы, где он назначен
            whereClause = {
              OR: [
                { fulfillmentCenterId: currentUser.organization.id },
                { organizationId: currentUser.organization.id }, // Свои заказы расходников
              ],
            }
            break

          case 'LOGIST':
            // Логистика видит заказы, где она назначена
            whereClause = { logisticsPartnerId: currentUser.organization.id }
            break

          default:
            throw new GraphQLError('Неподдерживаемый тип организации')
        }

        // Применение дополнительных фильтров
        if (args.filters) {
          if (args.filters.status) {
            whereClause.status = args.filters.status
          }
          if (args.filters.dateFrom || args.filters.dateTo) {
            whereClause.createdAt = {}
            if (args.filters.dateFrom) {
              whereClause.createdAt.gte = new Date(args.filters.dateFrom)
            }
            if (args.filters.dateTo) {
              whereClause.createdAt.lte = new Date(args.filters.dateTo)
            }
          }
        }

        const orders = await prisma.supplyOrder.findMany({
          where: whereClause,
          include: {
            organization: true,
            partner: true,
            fulfillmentCenter: true,
            logisticsPartner: true,
            items: {
              include: {
                product: {
                  include: {
                    category: true,
                    organization: true,
                  },
                },
              },
            },
            routes: true,
          },
          take: args.pagination?.limit || 50,
          skip: args.pagination?.offset || 0,
          orderBy: { createdAt: 'desc' },
        })

        SecurityLogger.logDataAccess({
          userId: context.user.id,
          organizationType: currentUser.organization.type,
          action: 'VIEW_PRICE',
          resource: 'SUPPLY_ORDER',
          filtered: true,
          removedFields: [],
          ipAddress: context.req?.ip,
          userAgent: context.req?.get?.('User-Agent'),
        })

        return orders
      },
      {
        resourceType: 'SUPPLY_ORDER',
        auditAction: 'VIEW_PRICE',
        enableFiltering: true,
        enableAudit: true,
      },
    ),

    /**
     * Безопасный резолвер для получения моих заказов поставок
     */
    secureMySupplyOrders: createSecureResolver(
      async (_: unknown, args: GetSupplyOrdersArgs, 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('У пользователя нет организации')
        }

        // Определяем логику фильтрации в зависимости от типа организации
        let whereClause: Record<string, unknown>

        if (currentUser.organization.type === 'WHOLESALE') {
          // Поставщик видит заказы, где он является поставщиком
          whereClause = {
            items: {
              some: {
                product: {
                  organizationId: currentUser.organization.id,
                },
              },
            },
          }
        } else {
          // Остальные видят заказы, которые они создали
          whereClause = {
            organizationId: currentUser.organization.id,
          }
        }

        const supplyOrders = await prisma.supplyOrder.findMany({
          where: whereClause,
          include: {
            organization: true,
            partner: true,
            fulfillmentCenter: true,
            logisticsPartner: true,
            items: {
              include: {
                product: {
                  include: {
                    category: true,
                    organization: true,
                  },
                },
              },
            },
            routes: true,
          },
          orderBy: { createdAt: 'desc' },
        })

        return supplyOrders
      },
      {
        resourceType: 'SUPPLY_ORDER',
        auditAction: 'VIEW_PRICE',
        enableFiltering: true,
        enableAudit: true,
      },
    ),
  },

  Mutation: {
    /**
     * Безопасный резолвер для создания заказа поставки
     * Проверяет партнерские отношения и права доступа
     */
    secureCreateSupplyOrder: createSecureResolver(
      async (_: unknown, args: CreateSupplyOrderArgs, 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 hasPartnership = await ParticipantIsolation.validatePartnerAccess(
          prisma,
          currentUser.organization.id,
          args.input.partnerId,
          {
            user: {
              id: context.user.id,
              organizationId: currentUser.organization.id,
              organizationType: currentUser.organization.type,
            },
            ipAddress: context.req?.ip,
            userAgent: context.req?.get?.('User-Agent'),
            request: {
              headers: context.req?.headers || {},
              timestamp: new Date(),
            },
          },
        )

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

        // Проверка доступа к рецептурам
        for (const item of args.input.items) {
          if (item.recipe) {
            if (item.recipe.services) {
              await RecipeAccessControl.validateServiceAccess(
                prisma,
                item.recipe.services,
                args.input.fulfillmentCenterId || '',
                currentUser.organization.id,
                currentUser.organization.type,
              )
            }

            if (item.recipe.fulfillmentConsumables) {
              await RecipeAccessControl.validateConsumableAccess(
                prisma,
                item.recipe.fulfillmentConsumables,
                args.input.fulfillmentCenterId || '',
                currentUser.organization.id,
                currentUser.organization.type,
              )
            }

            if (item.recipe.sellerConsumables) {
              await RecipeAccessControl.validateConsumableAccess(
                prisma,
                item.recipe.sellerConsumables,
                currentUser.organization.id,
                currentUser.organization.id,
                currentUser.organization.type,
              )
            }
          }
        }

        // Логирование создания заказа
        SecurityLogger.logDataAccess({
          userId: context.user.id,
          organizationType: currentUser.organization.type,
          action: 'VIEW_RECIPE',
          resource: 'SUPPLY_ORDER',
          filtered: false,
          removedFields: [],
          ipAddress: context.req?.ip,
          userAgent: context.req?.get?.('User-Agent'),
        })

        // TODO: Здесь будет основная логика создания заказа
        // Пока возвращаем заглушку
        return {
          success: true,
          message: 'Заказ поставки создан успешно',
          order: null,
        }
      },
      {
        resourceType: 'SUPPLY_ORDER',
        auditAction: 'VIEW_RECIPE',
        requiredRole: ['SELLER', 'FULFILLMENT'],
        enableFiltering: false,
        enableAudit: true,
      },
    ),

    /**
     * Безопасный резолвер для обновления статуса заказа
     */
    secureUpdateSupplyOrderStatus: createSecureResolver(
      async (
        _: unknown,
        args: { id: string; status: string },
        context: Context,
      ) => {
        if (!context.user) {
          throw new GraphQLError('Требуется авторизация', {
            extensions: { code: 'UNAUTHENTICATED' },
          })
        }

        // Проверка доступа к заказу
        const hasAccess = await SecurityHelpers.checkSupplyOrderAccess(
          context.prisma,
          args.id,
          {
            user: {
              id: context.user.id,
              organizationId: context.user.organizationId,
              organizationType: context.user.organizationType,
            },
            ipAddress: context.req?.ip,
            userAgent: context.req?.get?.('User-Agent'),
            request: {
              headers: context.req?.headers || {},
              timestamp: new Date(),
            },
          },
        )

        if (!hasAccess) {
          throw new GraphQLError('Нет доступа к данному заказу', {
            extensions: { code: 'FORBIDDEN' },
          })
        }

        // TODO: Здесь будет основная логика обновления статуса
        // Пока возвращаем заглушку
        return {
          success: true,
          message: 'Статус заказа обновлен успешно',
          order: null,
        }
      },
      {
        resourceType: 'SUPPLY_ORDER',
        auditAction: 'VIEW_PRICE',
        enableFiltering: true,
        enableAudit: true,
      },
    ),
  },
}