import { GraphQLError } from 'graphql'
import * as jwt from 'jsonwebtoken'

import { apiKeyUtility, ApiKeyInput } from '../graphql/resolvers/shared/api-keys'
import { prisma } from '../lib/prisma'

import { DaDataService } from './dadata-service'
import { SmsService } from './sms-service'

// Типы для OrganizationRegistrationService
export interface OrganizationRegistrationInput {
  phone: string
  type: 'FULFILLMENT' | 'SELLER' | 'LOGIST' | 'WHOLESALE'
  
  // Для бизнес-организаций (FULFILLMENT, LOGIST, WHOLESALE)
  inn?: string
  kpp?: string
  name?: string
  fullName?: string
  address?: string
  addressFull?: string
  ogrn?: string
  ogrnDate?: string
  managerName?: string
  managerEmail?: string
  managerPhone?: string
  description?: string
  logoUrl?: string
  website?: string
  bankName?: string
  bik?: string
  correspondentAccount?: string
  currentAccount?: string
  taxSystem?: string
  
  // Для селлеров (SELLER)
  wbApiKey?: string
  ozonApiKey?: string
  ozonClientId?: string
  
  // Общие поля
  referralCode?: string
  partnerCode?: string
}

export interface OrganizationRegistrationResult {
  success: boolean
  message: string
  token?: string
  user?: {
    id: string
    phone: string
    organization?: {
      id: string
      inn: string
      kpp?: string
      name?: string
      fullName?: string
      type: string
      referralPoints?: number
      apiKeys?: Array<{
        id: string
        marketplace: string
        isActive: boolean
      }>
    }
  }
}

// JWT утилита
const generateToken = (payload: { userId: string; phone: string }): string => {
  return jwt.sign(payload, process.env.JWT_SECRET!, { expiresIn: '30d' })
}

/**
 * Универсальный сервис регистрации организаций всех типов
 * Объединяет логику регистрации FULFILLMENT, SELLER, LOGIST, WHOLESALE
 */
export class OrganizationRegistrationService {
  private dadataService: DaDataService
  private smsService: SmsService

  constructor() {
    this.dadataService = new DaDataService()
    this.smsService = new SmsService()
  }

  /**
   * Главная функция регистрации организации любого типа
   */
  async registerOrganization(input: OrganizationRegistrationInput): Promise<OrganizationRegistrationResult> {
    console.warn('🚀 OrganizationRegistrationService - registerOrganization вызван:', {
      phone: input.phone,
      type: input.type,
      hasInn: !!input.inn,
      hasWbApiKey: !!input.wbApiKey,
      hasOzonApiKey: !!input.ozonApiKey,
      referralCode: input.referralCode,
      partnerCode: input.partnerCode,
      timestamp: new Date().toISOString(),
    })

    try {
      // Валидация входных данных
      await this.validateInput(input)

      // Определяем тип регистрации и вызываем соответствующую функцию
      if (['FULFILLMENT', 'LOGIST', 'WHOLESALE'].includes(input.type)) {
        return await this.registerBusinessOrganization(input)
      } else if (input.type === 'SELLER') {
        return await this.registerSellerOrganization(input)
      } else {
        throw new GraphQLError('Неподдерживаемый тип организации', {
          extensions: { code: 'INVALID_INPUT' },
        })
      }
    } catch (error) {
      console.error('❌ OrganizationRegistrationService - Critical error:', error)
      
      return {
        success: false,
        message: error instanceof GraphQLError 
          ? error.message 
          : 'Критическая ошибка при регистрации организации',
      }
    }
  }

  /**
   * Валидация входных данных в зависимости от типа организации
   */
  private async validateInput(input: OrganizationRegistrationInput): Promise<void> {
    console.warn('🔍 OrganizationRegistrationService - Валидация input:', input.type)

    // Общие валидации
    if (!input.phone || !input.type) {
      throw new GraphQLError('Телефон и тип организации обязательны')
    }

    // Валидация для бизнес-организаций
    if (['FULFILLMENT', 'LOGIST', 'WHOLESALE'].includes(input.type)) {
      if (!input.inn) {
        throw new GraphQLError('Для бизнес-организаций обязателен ИНН')
      }
      
      // Проверяем формат ИНН
      if (!this.dadataService.validateInn(input.inn)) {
        throw new GraphQLError('Неверный формат ИНН')
      }
    }

    // Валидация для селлеров
    if (input.type === 'SELLER') {
      const hasWB = !!input.wbApiKey
      const hasOzon = !!(input.ozonApiKey && input.ozonClientId)
      
      if (!hasWB && !hasOzon) {
        throw new GraphQLError('Для селлеров обязательны API ключи маркетплейсов (Wildberries или Ozon)')
      }
    }

    console.warn('✅ OrganizationRegistrationService - Валидация прошла успешно')
  }

  /**
   * Регистрация бизнес-организации (FULFILLMENT, LOGIST, WHOLESALE)
   */
  private async registerBusinessOrganization(input: OrganizationRegistrationInput): Promise<OrganizationRegistrationResult> {
    console.warn('🏢 OrganizationRegistrationService - Регистрация бизнес-организации:', {
      type: input.type,
      inn: input.inn,
      phone: input.phone,
    })

    // Проверяем уникальность ИНН
    const existingOrganization = await prisma.organization.findFirst({
      where: { inn: input.inn! },
    })

    if (existingOrganization) {
      return {
        success: false,
        message: 'Организация с таким ИНН уже зарегистрирована',
      }
    }

    // Проверяем уникальность телефона
    const existingUser = await prisma.user.findUnique({
      where: { phone: input.phone },
    })

    if (existingUser && existingUser.organizationId) {
      return {
        success: false,
        message: 'Пользователь с таким телефоном уже зарегистрирован в системе',
      }
    }

    // Обработка реферального кода
    let referredByOrganization = null
    if (input.referralCode) {
      referredByOrganization = await prisma.organization.findUnique({
        where: { referralCode: input.referralCode },
      })

      if (!referredByOrganization) {
        return {
          success: false,
          message: 'Неверный реферальный код',
        }
      }
    }

    // Получаем данные организации из DaData
    console.warn('🔍 OrganizationRegistrationService - Получение данных из DaData для ИНН:', input.inn)
    const organizationData = await this.dadataService.getOrganizationByInn(input.inn!)
    
    if (!organizationData) {
      console.error('❌ OrganizationRegistrationService - Данные организации не найдены в DaData:', input.inn)
      return {
        success: false,
        message: 'Организация с таким ИНН не найдена в реестре',
      }
    }

    console.warn('✅ OrganizationRegistrationService - Данные из DaData получены:', {
      name: organizationData.name,
      fullName: organizationData.fullName,
      address: organizationData.address,
      isActive: organizationData.isActive,
    })

    // Создание организации и пользователя в транзакции
    const result = await prisma.$transaction(async (tx) => {
      console.warn('🔄 OrganizationRegistrationService - Начинаем транзакцию создания бизнес организации:', {
        inn: input.inn,
        type: input.type,
        phone: input.phone,
      })

      // Создаем организацию
      const organization = await tx.organization.create({
        data: {
          inn: input.inn!,
          kpp: organizationData.kpp || input.kpp,
          name: organizationData.name || input.name,
          fullName: organizationData.fullName || input.fullName,
          address: organizationData.address || input.address,
          addressFull: organizationData.addressFull || input.addressFull,
          ogrn: organizationData.ogrn || input.ogrn,
          ogrnDate: organizationData.ogrnDate || (input.ogrnDate ? new Date(input.ogrnDate) : null),
          type: input.type,
          // Дополнительные данные из DaData
          status: organizationData.status || null,
          actualityDate: organizationData.actualityDate || null,
          registrationDate: organizationData.registrationDate || null,
          liquidationDate: organizationData.liquidationDate || null,
          managementName: organizationData.managementName || null,
          managementPost: organizationData.managementPost || null,
          opfCode: organizationData.opfCode || null,
          opfFull: organizationData.opfFull || null,
          opfShort: organizationData.opfShort || null,
          okato: organizationData.okato || null,
          oktmo: organizationData.oktmo || null,
          okpo: organizationData.okpo || null,
          okved: organizationData.okved || null,
          employeeCount: organizationData.employeeCount || null,
          revenue: organizationData.revenue ? BigInt(organizationData.revenue) : null,
          taxSystem: organizationData.taxSystem || input.taxSystem,
          phones: organizationData.phones ? JSON.stringify(organizationData.phones) : null,
          emails: organizationData.emails ? JSON.stringify(organizationData.emails) : null,
          referralCode: `${input.type.substring(0, 2)}_${input.inn}_${Date.now()}`,
          referredById: referredByOrganization?.id,
        },
        include: {
          apiKeys: true,
        },
      })

      console.warn('✅ OrganizationRegistrationService - Бизнес организация создана в транзакции:', { 
        organizationId: organization.id, 
        name: organization.name,
      })

      // Создаем или обновляем пользователя в той же транзакции
      let user
      if (existingUser) {
        user = await tx.user.update({
          where: { id: existingUser.id },
          data: { organizationId: organization.id },
          include: {
            organization: {
              include: {
                apiKeys: true,
              },
            },
          },
        })
        console.warn('✅ OrganizationRegistrationService - Существующий пользователь обновлен в транзакции:', { 
          userId: user.id,
          organizationId: organization.id,
        })
      } else {
        user = await tx.user.create({
          data: {
            phone: input.phone,
            organizationId: organization.id,
          },
          include: {
            organization: {
              include: {
                apiKeys: true,
              },
            },
          },
        })
        console.warn('✅ OrganizationRegistrationService - Новый пользователь создан в транзакции:', { 
          userId: user.id,
          organizationId: organization.id,
        })
      }

      return { organization, user }
    }, {
      timeout: 30000, // 30 секунд максимум на транзакцию
      maxWait: 5000,   // Максимум 5 секунд ожидания блокировки
    })

    const { organization, user } = result
    console.warn('🎉 OrganizationRegistrationService - Транзакция бизнес организации успешно завершена:', {
      organizationId: organization.id,
      userId: user.id,
      organizationType: organization.type,
    })

    // Обработка партнерского кода (автопартнерство) в отдельной транзакции
    if (input.partnerCode) {
      await this.handlePartnershipLogic(organization, input.partnerCode, 100)
    }

    // Начисляем реферальные баллы (если есть реферер)
    if (referredByOrganization) {
      await this.handleReferralPoints(referredByOrganization.id, organization.id, 100)
    }

    // Создаем JWT токен
    const token = generateToken({
      userId: user.id,
      phone: user.phone,
    })

    console.warn('✅ OrganizationRegistrationService - Бизнес организация успешно зарегистрирована:', {
      organizationId: organization.id,
      userId: user.id,
      inn: organization.inn,
      type: organization.type,
      referralCode: organization.referralCode,
    })

    return {
      success: true,
      message: `${input.type} организация успешно зарегистрирована`,
      token,
      user,
    }
  }

  /**
   * Регистрация селлер-организации (SELLER)
   */
  private async registerSellerOrganization(input: OrganizationRegistrationInput): Promise<OrganizationRegistrationResult> {
    console.warn('🛍️ OrganizationRegistrationService - Регистрация селлер организации:', {
      phone: input.phone,
      hasWbApiKey: !!input.wbApiKey,
      hasOzonApiKey: !!input.ozonApiKey,
    })

    // Проверяем уникальность телефона
    const existingUser = await prisma.user.findUnique({
      where: { phone: input.phone },
    })

    if (existingUser && existingUser.organizationId) {
      return {
        success: false,
        message: 'Пользователь с таким телефоном уже зарегистрирован в системе',
      }
    }

    // Обработка реферального кода
    let referredByOrganization = null
    if (input.referralCode) {
      referredByOrganization = await prisma.organization.findUnique({
        where: { referralCode: input.referralCode },
      })

      if (!referredByOrganization) {
        return {
          success: false,
          message: 'Неверный реферальный код',
        }
      }
    }

    // Создание селлер организации и пользователя в транзакции
    const result = await prisma.$transaction(async (tx) => {
      console.warn('🔄 OrganizationRegistrationService - Начинаем транзакцию создания селлер организации:', {
        phone: input.phone,
        type: 'SELLER',
      })

      // Создаем организацию селлера с псевдо-ИНН
      const organization = await tx.organization.create({
        data: {
          inn: `SELLER_${Date.now()}`, // Псевдо-ИНН для селлеров
          type: 'SELLER',
          name: `Селлер ${input.phone}`, // Временное название на основе телефона
          referralCode: `SL_${input.phone.replace(/\D/g, '')}_${Date.now()}`,
          referredById: referredByOrganization?.id,
        },
        include: {
          apiKeys: true,
        },
      })

      console.warn('✅ OrganizationRegistrationService - Селлер организация создана в транзакции:', { 
        organizationId: organization.id, 
        name: organization.name,
      })

      // Создаем или обновляем пользователя в той же транзакции
      let user
      if (existingUser) {
        user = await tx.user.update({
          where: { id: existingUser.id },
          data: { organizationId: organization.id },
          include: {
            organization: {
              include: {
                apiKeys: true,
              },
            },
          },
        })
        console.warn('✅ OrganizationRegistrationService - Существующий пользователь обновлен в транзакции:', { 
          userId: user.id,
          organizationId: organization.id,
        })
      } else {
        user = await tx.user.create({
          data: {
            phone: input.phone,
            organizationId: organization.id,
          },
          include: {
            organization: {
              include: {
                apiKeys: true,
              },
            },
          },
        })
        console.warn('✅ OrganizationRegistrationService - Новый пользователь создан в транзакции:', { 
          userId: user.id,
          organizationId: organization.id,
        })
      }

      return { organization, user }
    }, {
      timeout: 30000, // 30 секунд максимум на транзакцию
      maxWait: 5000,   // Максимум 5 секунд ожидания блокировки
    })

    const { organization, user } = result
    console.warn('🎉 OrganizationRegistrationService - Транзакция селлера успешно завершена:', {
      organizationId: organization.id,
      userId: user.id,
      organizationType: organization.type,
    })

    // Обработка партнерского кода для селлера (автопартнерство) в отдельной транзакции
    if (input.partnerCode) {
      await this.handlePartnershipLogic(organization, input.partnerCode, 100)
    }

    // Начисляем реферальные баллы (если есть реферер)
    if (referredByOrganization) {
      await this.handleReferralPoints(referredByOrganization.id, organization.id, 50) // 50 баллов за селлера
    }

    // Обработка API ключей маркетплейсов
    await this.handleMarketplaceApiKeys(organization, input)

    // Создаем JWT токен
    const token = generateToken({
      userId: user.id,
      phone: user.phone,
    })

    console.warn('✅ OrganizationRegistrationService - Селлер организация успешно зарегистрирована:', {
      organizationId: organization.id,
      userId: user.id,
      type: organization.type,
      referralCode: organization.referralCode,
    })

    return {
      success: true,
      message: 'Селлер организация успешно зарегистрирована',
      token,
      user,
    }
  }

  /**
   * Обработка партнерской логики (автопартнерство)
   */
  private async handlePartnershipLogic(
    organization: { id: string; type: string },
    partnerCode: string,
    points: number,
  ): Promise<void> {
    try {
      console.warn('🔍 OrganizationRegistrationService - Партнерский код проверка:', {
        partnerCode,
        organizationId: organization.id,
        points,
      })
      
      // Находим партнера по партнерскому коду
      const partner = await prisma.organization.findUnique({
        where: { referralCode: partnerCode },
      })
      
      console.warn('🔍 OrganizationRegistrationService - Результат поиска партнера:', {
        found: !!partner,
        partnerId: partner?.id,
        partnerName: partner?.name,
        partnerType: partner?.type,
      })

      if (partner) {
        // Партнерская логика в отдельной транзакции
        await prisma.$transaction(async (tx) => {
          console.warn('🔄 OrganizationRegistrationService - Начинаем транзакцию партнерства:', {
            partnerId: partner.id,
            organizationId: organization.id,
            points,
          })

          // Создаем реферальную транзакцию
          await tx.referralTransaction.create({
            data: {
              referrerId: partner.id,
              referralId: organization.id,
              points,
              type: 'AUTO_PARTNERSHIP',
              description: `Регистрация ${organization.type.toLowerCase()} организации по партнерской ссылке`,
            },
          })

          // Увеличиваем счетчик сфер у партнера
          await tx.organization.update({
            where: { id: partner.id },
            data: { referralPoints: { increment: points } },
          })

          // Устанавливаем связь реферала и источник регистрации
          await tx.organization.update({
            where: { id: organization.id },
            data: { referredById: partner.id },
          })

          // Создаем партнерскую связь (автоматическое добавление в контрагенты)
          await tx.counterparty.create({
            data: {
              organizationId: partner.id,
              counterpartyId: organization.id,
              type: 'AUTO',
              triggeredBy: 'PARTNER_LINK',
            },
          })

          await tx.counterparty.create({
            data: {
              organizationId: organization.id,
              counterpartyId: partner.id,
              type: 'AUTO',
              triggeredBy: 'PARTNER_LINK',
            },
          })

          console.warn('✅ OrganizationRegistrationService - Партнерская транзакция завершена успешно')
        }, {
          timeout: 20000, // 20 секунд для партнерских операций
          maxWait: 3000,   // 3 секунды ожидания
        })

        console.warn('🤝 OrganizationRegistrationService - Автоматическое партнерство создано:', {
          organizationId: organization.id,
          partnerId: partner.id,
          referralPoints: points,
          type: organization.type,
        })
      } else {
        console.warn('⚠️ OrganizationRegistrationService - Партнер не найден по коду:', partnerCode)
      }
    } catch (partnerError) {
      console.error('❌ OrganizationRegistrationService - Критическая ошибка обработки партнерского кода:', partnerError)
      // Партнерская ошибка не должна блокировать создание организации
    }
  }

  /**
   * Начисление реферальных баллов
   */
  private async handleReferralPoints(referrerId: string, referralId: string, points: number): Promise<void> {
    try {
      await prisma.organization.update({
        where: { id: referrerId },
        data: {
          referralPoints: {
            increment: points,
          },
        },
      })

      console.warn('💰 OrganizationRegistrationService - Начислены реферальные баллы:', {
        referrerId,
        points,
        newOrganizationId: referralId,
      })
    } catch (error) {
      console.error('❌ OrganizationRegistrationService - Ошибка начисления реферальных баллов:', error)
    }
  }

  /**
   * Обработка API ключей маркетплейсов для селлеров
   */
  private async handleMarketplaceApiKeys(
    organization: { id: string },
    input: OrganizationRegistrationInput,
  ): Promise<void> {
    const apiKeysToCreate: ApiKeyInput[] = []

    if (input.wbApiKey) {
      apiKeysToCreate.push({
        marketplace: 'WILDBERRIES',
        apiKey: input.wbApiKey,
      })
    }

    if (input.ozonApiKey && input.ozonClientId) {
      apiKeysToCreate.push({
        marketplace: 'OZON',
        apiKey: input.ozonApiKey,
        clientId: input.ozonClientId,
      })
    }

    // Сохраняем API ключи в базу данных
    if (apiKeysToCreate.length > 0) {
      console.warn('🔑 OrganizationRegistrationService - Сохранение API ключей для селлера:', {
        organizationId: organization.id,
        keysCount: apiKeysToCreate.length,
        marketplaces: apiKeysToCreate.map(k => k.marketplace),
      })

      const apiKeysResult = await apiKeyUtility.createMultipleApiKeys(
        organization.id,
        apiKeysToCreate,
      )

      if (apiKeysResult.success) {
        console.warn('✅ OrganizationRegistrationService - Все API ключи сохранены успешно:', {
          organizationId: organization.id,
          savedKeys: apiKeysResult.results.filter(r => r.success).length,
          totalKeys: apiKeysResult.results.length,
        })

        // Обновляем название организации данными продавца из маркетплейса
        if (apiKeysResult.sellerData) {
          const { sellerName, tradeMark } = apiKeysResult.sellerData
          const organizationName = tradeMark || sellerName || `Селлер ${input.phone}`

          console.warn('🏪 OrganizationRegistrationService - Обновление названия организации:', {
            organizationId: organization.id,
            newName: organizationName,
            source: tradeMark ? 'tradeMark' : sellerName ? 'sellerName' : 'fallback',
          })

          await prisma.organization.update({
            where: { id: organization.id },
            data: {
              name: organizationName,
              fullName: sellerName || tradeMark || null,
            },
          })

          console.warn('✅ OrganizationRegistrationService - Название организации обновлено:', {
            organizationId: organization.id,
            name: organizationName,
          })
        }
      } else {
        console.warn('⚠️ OrganizationRegistrationService - Некоторые API ключи не сохранены:', {
          organizationId: organization.id,
          failed: apiKeysResult.results.filter(r => !r.success).map(r => r.message),
        })
      }
    }
  }
}