import bcrypt from 'bcryptjs'
import { GraphQLError } from 'graphql'
import jwt from 'jsonwebtoken'

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

// Admin Tools Domain Resolvers - управление административными инструментами

// =============================================================================
// 🔧 JWT UTILITIES
// =============================================================================

interface AuthTokenPayload {
  adminId?: string
  username: string
  type: 'admin'
}

// JWT утилита для админов
const generateToken = (payload: AuthTokenPayload): string => {
  return jwt.sign(payload, process.env.JWT_SECRET!, { expiresIn: '30d' })
}

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

const withAuth = (resolver: any) => {
  return async (parent: any, args: any, context: Context) => {
    console.log('🔐 ADMIN TOOLS DOMAIN AUTH CHECK:', { 
      hasUser: !!context.user, 
      userId: context.user?.id,
      hasAdmin: !!context.admin,
      adminId: context.admin?.id,
    })
    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 withAdminAuth = (resolver: any) => {
  return async (parent: any, args: any, context: Context) => {
    console.log('🔐 ADMIN TOOLS DOMAIN ADMIN AUTH CHECK:', { 
      hasAdmin: !!context.admin,
      adminId: context.admin?.id,
    })
    if (!context.admin) {
      console.error('❌ ADMIN AUTH FAILED: No admin in context')
      throw new GraphQLError('Требуется авторизация администратора', {
        extensions: { code: 'UNAUTHENTICATED' },
      })
    }
    console.log('✅ ADMIN AUTH PASSED: Calling resolver')
    try {
      const result = await resolver(parent, args, context)
      console.log('🎯 ADMIN RESOLVER RESULT TYPE:', typeof result, result === null ? 'NULL RESULT!' : 'Has result')
      return result
    } catch (error) {
      console.error('💥 ADMIN RESOLVER ERROR:', error)
      throw error
    }
  }
}

// =============================================================================
// 🛠️ ADMIN TOOLS DOMAIN RESOLVERS
// =============================================================================

export const adminToolsResolvers: DomainResolvers = {
  Query: {
    // Получение информации об администраторе
    adminMe: withAdminAuth(async (_: unknown, __: unknown, context: Context) => {
      console.log('🔍 ADMIN_ME DOMAIN QUERY STARTED:', { adminId: context.admin?.id })
      
      try {
        const admin = await prisma.admin.findUnique({
          where: { id: context.admin!.id },
        })

        if (!admin) {
          throw new GraphQLError('Администратор не найден')
        }

        console.log('✅ ADMIN_ME DOMAIN SUCCESS:', { 
          adminId: admin.id,
          username: admin.username,
          isActive: admin.isActive,
        })

        return admin
      } catch (error) {
        console.error('❌ ADMIN_ME DOMAIN ERROR:', error)
        throw error
      }
    }),

    // Получение всех пользователей (админская функция)
    allUsers: withAdminAuth(async (_: unknown, args: { search?: string; limit?: number; offset?: number }, context: Context) => {
      console.log('🔍 ALL_USERS DOMAIN QUERY STARTED:', { 
        adminId: context.admin?.id,
        search: args.search,
        limit: args.limit,
        offset: args.offset,
      })

      try {
        const limit = args.limit || 50
        const offset = args.offset || 0

        // Строим условие поиска
        const whereCondition = args.search
          ? {
              OR: [
                { phone: { contains: args.search, mode: 'insensitive' as const } },
                { 
                  organization: {
                    OR: [
                      { name: { contains: args.search, mode: 'insensitive' as const } },
                      { fullName: { contains: args.search, mode: 'insensitive' as const } },
                      { inn: { contains: args.search, mode: 'insensitive' as const } },
                    ],
                  },
                },
              ],
            }
          : {}

        // Получаем пользователей с пагинацией
        const [users, totalCount] = await Promise.all([
          prisma.user.findMany({
            where: whereCondition,
            include: {
              organization: {
                include: {
                  apiKeys: true,
                },
              },
            },
            orderBy: { createdAt: 'desc' },
            take: limit,
            skip: offset,
          }),
          prisma.user.count({ where: whereCondition }),
        ])

        console.log('✅ ALL_USERS DOMAIN SUCCESS:', { 
          adminId: context.admin?.id,
          usersFound: users.length,
          totalCount,
          hasSearch: !!args.search,
        })

        return {
          users,
          total: totalCount,
          hasMore: offset + users.length < totalCount,
        }
      } catch (error) {
        console.error('❌ ALL_USERS DOMAIN ERROR:', error)
        throw error
      }
    }),
  },

  Mutation: {
    // Авторизация администратора
    adminLogin: async (
      _: unknown,
      args: { username: string; password: string },
    ) => {
      console.log('🔍 ADMIN_LOGIN DOMAIN MUTATION STARTED:', { 
        username: args.username,
        hasPassword: !!args.password,
      })

      try {
        // Найти администратора
        const admin = await prisma.admin.findUnique({
          where: { username: args.username },
        })

        if (!admin) {
          console.log('❌ ADMIN_LOGIN: Admin not found')
          return {
            success: false,
            message: 'Неверные учетные данные',
            token: null,
            admin: null,
          }
        }

        // Проверка активности
        if (!admin.isActive) {
          console.log('❌ ADMIN_LOGIN: Admin is inactive')
          return {
            success: false,
            message: 'Аккаунт администратора заблокирован',
            token: null,
            admin: null,
          }
        }

        // Проверка пароля
        const isPasswordValid = await bcrypt.compare(args.password, admin.password)
        if (!isPasswordValid) {
          console.log('❌ ADMIN_LOGIN: Invalid password')
          return {
            success: false,
            message: 'Неверные учетные данные',
            token: null,
            admin: null,
          }
        }

        // Обновление последнего входа
        await prisma.admin.update({
          where: { id: admin.id },
          data: { lastLogin: new Date() },
        })

        // Генерация токена
        const token = generateToken({
          adminId: admin.id,
          username: admin.username,
          type: 'admin',
        })

        console.log('✅ ADMIN_LOGIN DOMAIN SUCCESS:', { 
          adminId: admin.id,
          username: admin.username,
          tokenGenerated: !!token,
        })

        return {
          success: true,
          message: 'Успешная авторизация',
          token,
          admin: {
            ...admin,
            password: undefined, // Не возвращаем пароль
          },
        }
      } catch (error: any) {
        console.error('❌ ADMIN_LOGIN DOMAIN ERROR:', error)
        return {
          success: false,
          message: error.message || 'Ошибка при авторизации администратора',
          token: null,
          admin: null,
        }
      }
    },

    // Выход администратора из системы
    adminLogout: withAdminAuth(async (_: unknown, __: unknown, context: Context) => {
      console.log('🔍 ADMIN_LOGOUT DOMAIN MUTATION STARTED:', { adminId: context.admin?.id })
      
      try {
        // В текущей реализации просто возвращаем true
        // В реальной системе здесь можно добавить инвалидацию токена
        
        console.log('✅ ADMIN_LOGOUT DOMAIN SUCCESS:', { 
          adminId: context.admin?.id,
        })

        return true
      } catch (error) {
        console.error('❌ ADMIN_LOGOUT DOMAIN ERROR:', error)
        throw new GraphQLError('Ошибка при выходе из системы')
      }
    }),
  },
}

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