import type { Prisma } from '@prisma/client'
import { GraphQLError } from 'graphql'

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

// Employee Domain Resolvers - управление сотрудниками (мигрировано из employees-v2.ts)
// ПЕРЕИМЕНОВАННЫЕ РЕЗОЛВЕРЫ: employeesV2 → myEmployees, createEmployeeV2 → createEmployee

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

const withAuth = (resolver: any) => {
  return async (parent: any, args: any, context: Context) => {
    console.log('🔐 EMPLOYEE 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
}

// =============================================================================
// 🔄 TRANSFORM HELPERS
// =============================================================================

function transformEmployeeToV2(employee: any): any {
  return {
    id: employee.id,
    personalInfo: {
      firstName: employee.firstName,
      lastName: employee.lastName,
      middleName: employee.middleName,
      fullName: `${employee.lastName} ${employee.firstName} ${employee.middleName || ''}`.trim(),
      birthDate: employee.birthDate,
      avatar: employee.avatar,
    },
    documentsInfo: {
      passportPhoto: employee.passportPhoto,
      passportSeries: employee.passportSeries,
      passportNumber: employee.passportNumber,
      passportIssued: employee.passportIssued,
      passportDate: employee.passportDate,
    },
    contactInfo: {
      phone: employee.phone,
      email: employee.email,
      telegram: employee.telegram,
      whatsapp: employee.whatsapp,
      address: employee.address,
      emergencyContact: employee.emergencyContact,
      emergencyPhone: employee.emergencyPhone,
    },
    workInfo: {
      position: employee.position,
      department: employee.department,
      hireDate: employee.hireDate,
      salary: employee.salary,
      status: employee.status,
    },
    organizationId: employee.organizationId,
    organization: employee.organization ? {
      id: employee.organization.id,
      name: employee.organization.name,
      fullName: employee.organization.fullName,
      type: employee.organization.type,
    } : undefined,
    createdAt: employee.createdAt,
    updatedAt: employee.updatedAt,
    scheduleRecords: employee.scheduleRecords?.map(transformScheduleToV2) || [],
  }
}

function transformScheduleToV2(schedule: any): any {
  return {
    id: schedule.id,
    employeeId: schedule.employeeId,
    date: schedule.date,
    status: schedule.status,
    hoursWorked: schedule.hoursWorked,
    overtimeHours: schedule.overtimeHours,
    notes: schedule.notes,
    createdAt: schedule.createdAt,
    updatedAt: schedule.updatedAt,
  }
}

// =============================================================================
// 🧑‍💼 EMPLOYEE DOMAIN RESOLVERS
// =============================================================================

export const employeeResolvers: DomainResolvers = {
  Query: {
    // ПЕРЕИМЕНОВАНО: employeesV2 → myEmployees (для совместимости с монолитом)
    myEmployees: withAuth(async (_: unknown, args: any, context: Context) => {
      console.log('🔍 MY_EMPLOYEES DOMAIN QUERY STARTED:', { args, userId: context.user?.id })
      try {
        const { input = {} } = args
        const {
          status,
          department,
          search,
          page = 1,
          limit = 20,
          sortBy = 'CREATED_AT',
          sortOrder = 'DESC',
        } = input

        const user = await checkOrganizationAccess(context.user!.id)

        // Построение условий фильтрации
        const where: Prisma.EmployeeWhereInput = {
          organizationId: user.organizationId!,
          ...(status?.length && { status: { in: status } }),
          ...(department && { department }),
          ...(search && {
            OR: [
              { firstName: { contains: search, mode: 'insensitive' } },
              { lastName: { contains: search, mode: 'insensitive' } },
              { position: { contains: search, mode: 'insensitive' } },
              { phone: { contains: search } },
            ],
          }),
        }

        // Подсчет общего количества
        const total = await prisma.employee.count({ where })

        // Получение данных с пагинацией
        const employees = await prisma.employee.findMany({
          where,
          include: {
            organization: true,
            scheduleRecords: {
              orderBy: { date: 'desc' },
              take: 10,
            },
          },
          skip: (page - 1) * limit,
          take: limit,
          orderBy: getSortOrder(sortBy, sortOrder),
        })

        const result = {
          items: employees.map(transformEmployeeToV2),
          pagination: {
            total,
            page,
            limit,
            totalPages: Math.ceil(total / limit),
          },
        }

        console.log('✅ MY_EMPLOYEES DOMAIN SUCCESS:', { 
          total, 
          page, 
          employeesCount: employees.length, 
        })
        
        return result
      } catch (error) {
        console.error('❌ MY_EMPLOYEES DOMAIN ERROR:', error)
        throw error
      }
    }),

    // Резолвер для employeesV2 (алиас для myEmployees)
    employeesV2: withAuth(async (_: unknown, args: any, context: Context) => {
      // Делегируем к myEmployees и возвращаем полный результат
      const result = await employeeResolvers.Query.myEmployees(_, args, context)
      return result
    }),

    // Получение конкретного сотрудника
    employee: withAuth(async (_: unknown, args: { id: string }, context: Context) => {
      const user = await checkOrganizationAccess(context.user!.id)
      
      const employee = await prisma.employee.findFirst({
        where: {
          id: args.id,
          organizationId: user.organizationId!,
        },
        include: {
          organization: true,
          scheduleRecords: {
            orderBy: { date: 'desc' },
          },
        },
      })

      if (!employee) {
        throw new GraphQLError('Сотрудник не найден')
      }

      return transformEmployeeToV2(employee)
    }),

    // Резолвер для employeeV2 (алиас для employee)
    employeeV2: withAuth(async (_: unknown, args: { id: string }, context: Context) => {
      // Делегируем к employee
      return employeeResolvers.Query.employee(_, args, context)
    }),

    // Получение расписания сотрудника
    employeeSchedule: withAuth(async (_: unknown, args: any, context: Context) => {
      const { input } = args
      const { employeeId, startDate, endDate } = input
      
      const user = await checkOrganizationAccess(context.user!.id)
      
      // Проверяем, что сотрудник принадлежит организации
      const employee = await prisma.employee.findFirst({
        where: {
          id: employeeId,
          organizationId: user.organizationId!,
        },
      })

      if (!employee) {
        throw new GraphQLError('Сотрудник не найден')
      }

      const scheduleRecords = await prisma.employeeSchedule.findMany({
        where: {
          employeeId,
          date: {
            gte: new Date(startDate),
            lte: new Date(endDate),
          },
        },
        orderBy: { date: 'asc' },
      })

      return scheduleRecords.map(transformScheduleToV2)
    }),

    // Резолвер для employeeScheduleV2 (алиас для employeeSchedule)
    employeeScheduleV2: withAuth(async (_: unknown, args: any, context: Context) => {
      // Делегируем к employeeSchedule
      return employeeResolvers.Query.employeeSchedule(_, args, context)
    }),
  },

  Mutation: {
    // ПЕРЕИМЕНОВАНО: createEmployeeV2 → createEmployee (для совместимости)
    createEmployee: withAuth(async (_: unknown, args: any, context: Context) => {
      console.log('🔍 CREATE EMPLOYEE DOMAIN MUTATION STARTED:', { args, userId: context.user?.id })
      const { input } = args
      const user = await checkOrganizationAccess(context.user!.id)

      try {
        const employee = await prisma.employee.create({
          data: {
            organizationId: user.organizationId!,
            firstName: input.personalInfo.firstName,
            lastName: input.personalInfo.lastName,
            middleName: input.personalInfo.middleName,
            birthDate: input.personalInfo.birthDate,
            avatar: input.personalInfo.avatar,
            ...input.documentsInfo,
            ...input.contactInfo,
            ...input.workInfo,
          },
          include: {
            organization: true,
          },
        })

        const result = {
          success: true,
          message: 'Сотрудник успешно создан',
          employee: transformEmployeeToV2(employee),
          errors: [],
        }
        console.log('✅ CREATE EMPLOYEE DOMAIN SUCCESS:', { employeeId: employee.id, result })
        return result
      } catch (error: any) {
        console.error('❌ CREATE EMPLOYEE DOMAIN ERROR:', error)
        throw error
      }
    }),

    // ПЕРЕИМЕНОВАНО: updateEmployeeV2 → updateEmployee
    updateEmployee: withAuth(async (_: unknown, args: any, context: Context) => {
      const { id, input } = args
      const user = await checkOrganizationAccess(context.user!.id)

      try {
        // Проверяем существование и принадлежность сотрудника
        const existingEmployee = await prisma.employee.findFirst({
          where: {
            id,
            organizationId: user.organizationId!,
          },
        })

        if (!existingEmployee) {
          return {
            success: false,
            message: 'Сотрудник не найден',
            employee: null,
            errors: [{ field: 'id', message: 'Сотрудник не найден' }],
          }
        }

        const employee = await prisma.employee.update({
          where: { id },
          data: {
            ...(input.personalInfo && {
              firstName: input.personalInfo.firstName,
              lastName: input.personalInfo.lastName,
              middleName: input.personalInfo.middleName,
              birthDate: input.personalInfo.birthDate,
              avatar: input.personalInfo.avatar,
            }),
            ...(input.documentsInfo && input.documentsInfo),
            ...(input.contactInfo && input.contactInfo),
            ...(input.workInfo && input.workInfo),
          },
          include: {
            organization: true,
          },
        })

        return {
          success: true,
          message: 'Сотрудник успешно обновлен',
          employee: transformEmployeeToV2(employee),
          errors: [],
        }
      } catch (error: any) {
        console.error('❌ UPDATE EMPLOYEE DOMAIN ERROR:', error)
        return {
          success: false,
          message: 'Ошибка при обновлении сотрудника',
          employee: null,
          errors: [{ field: 'general', message: error.message }],
        }
      }
    }),

    // ПЕРЕИМЕНОВАНО: deleteEmployeeV2 → deleteEmployee
    deleteEmployee: withAuth(async (_: unknown, args: { id: string }, context: Context) => {
      const user = await checkOrganizationAccess(context.user!.id)

      try {
        // Проверяем существование и принадлежность сотрудника
        const existingEmployee = await prisma.employee.findFirst({
          where: {
            id: args.id,
            organizationId: user.organizationId!,
          },
        })

        if (!existingEmployee) {
          return false
        }

        await prisma.employee.delete({
          where: { id: args.id },
        })

        return true
      } catch (error: any) {
        console.error('❌ DELETE EMPLOYEE DOMAIN ERROR:', error)
        return false
      }
    }),

    // ПЕРЕИМЕНОВАНО: updateEmployeeScheduleV2 → updateEmployeeSchedule
    updateEmployeeSchedule: withAuth(async (_: unknown, args: any, context: Context) => {
      const { input } = args
      const { employeeId, scheduleData } = input
      
      const user = await checkOrganizationAccess(context.user!.id)

      // Проверяем, что сотрудник принадлежит организации
      const employee = await prisma.employee.findFirst({
        where: {
          id: employeeId,
          organizationId: user.organizationId!,
        },
      })

      if (!employee) {
        throw new GraphQLError('Сотрудник не найден')
      }

      // Обновление записей расписания
      const scheduleRecords = await Promise.all(
        scheduleData.map(async (record: any) => {
          return await prisma.employeeSchedule.upsert({
            where: {
              employeeId_date: {
                employeeId: employeeId,
                date: record.date,
              },
            },
            create: {
              employeeId: employeeId,
              date: record.date,
              status: record.status,
              hoursWorked: record.hoursWorked || 0,
              overtimeHours: record.overtimeHours || 0,
              notes: record.notes,
            },
            update: {
              status: record.status,
              hoursWorked: record.hoursWorked || 0,
              overtimeHours: record.overtimeHours || 0,
              notes: record.notes,
            },
          })
        }),
      )

      return {
        success: true,
        message: 'Расписание сотрудника успешно обновлено',
        scheduleRecords: scheduleRecords.map(transformScheduleToV2),
      }
    }),

    // V2 мутации (алиасы для совместимости)
    createEmployeeV2: withAuth(async (_: unknown, args: any, context: Context) => {
      return employeeResolvers.Mutation.createEmployee(_, args, context)
    }),

    updateEmployeeV2: withAuth(async (_: unknown, args: any, context: Context) => {
      return employeeResolvers.Mutation.updateEmployee(_, args, context)
    }),

    deleteEmployeeV2: withAuth(async (_: unknown, args: any, context: Context) => {
      return employeeResolvers.Mutation.deleteEmployee(_, args, context)
    }),

    updateEmployeeScheduleV2: withAuth(async (_: unknown, args: any, context: Context) => {
      return employeeResolvers.Mutation.updateEmployeeSchedule(_, args, context)
    }),
  },
}

// =============================================================================
// 🔧 UTILITY FUNCTIONS
// =============================================================================

function getSortOrder(sortBy: string, sortOrder: string): any {
  const orderDirection = sortOrder === 'ASC' ? 'asc' : 'desc'
  
  switch (sortBy) {
    case 'CREATED_AT':
      return { createdAt: orderDirection }
    case 'LAST_NAME':
      return { lastName: orderDirection }
    case 'HIRE_DATE':
      return { hireDate: orderDirection }
    case 'DEPARTMENT':
      return { department: orderDirection }
    default:
      return { createdAt: orderDirection }
  }
}