/**
 * Система автоматического обнаружения угроз
 *
 * Использует машинное обучение и эвристические алгоритмы
 * для выявления подозрительной активности и потенциальных угроз безопасности
 */

import { EventEmitter } from 'events'

import { PrismaClient } from '@prisma/client'

import { SecurityLogger } from '../../lib/security-logger'

import { RealTimeSecurityAlerts } from './real-time-security-alerts'
import { CommercialAccessType, ResourceType, SecurityAlert } from './types'

/**
 * Модель угрозы
 */
interface ThreatModel {
  id: string
  name: string
  description: string
  severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'
  patterns: ThreatPattern[]
  enabled: boolean
  confidence: number // 0-100
  falsePositiveRate: number // 0-1
  lastUpdated: Date
}

/**
 * Паттерн угрозы
 */
interface ThreatPattern {
  type: 'BEHAVIORAL' | 'VOLUMETRIC' | 'TEMPORAL' | 'CONTEXTUAL'
  rule: string
  weight: number
  threshold: number
  timeWindow: number // в минутах
}

/**
 * Профиль пользователя
 */
interface UserProfile {
  userId: string
  organizationType: string
  organizationId: string
  baseline: {
    avgActionsPerHour: number
    avgActionsPerDay: number
    commonActions: Array<{ action: string; frequency: number }>
    usualTimePattern: number[] // активность по часам (0-23)
    commonResources: string[]
    peakHours: number[]
  }
  anomalies: Array<{
    timestamp: Date
    type: string
    severity: string
    description: string
    confidence: number
  }>
  riskScore: number
  lastAnalysis: Date
}

/**
 * Обнаруженная угроза
 */
interface DetectedThreat {
  id: string
  modelId: string
  userId: string
  organizationType: string
  threatType: string
  description: string
  confidence: number
  riskScore: number
  indicators: string[]
  evidence: Record<string, unknown>
  timestamp: Date
  status: 'NEW' | 'INVESTIGATING' | 'CONFIRMED' | 'FALSE_POSITIVE' | 'RESOLVED'
}

export class AutomatedThreatDetection extends EventEmitter {
  private static instance: AutomatedThreatDetection
  private isActive = false
  private threatModels: ThreatModel[] = []
  private userProfiles = new Map<string, UserProfile>()
  private detectedThreats = new Map<string, DetectedThreat>()
  private analysisQueue: Array<{ userId: string; event: any }> = []
  private processing = false

  constructor(private prisma: PrismaClient) {
    super()
    this.initializeThreatModels()
  }

  /**
   * Получить singleton instance
   */
  static getInstance(prisma: PrismaClient): AutomatedThreatDetection {
    if (!AutomatedThreatDetection.instance) {
      AutomatedThreatDetection.instance = new AutomatedThreatDetection(prisma)
    }
    return AutomatedThreatDetection.instance
  }

  /**
   * Запуск системы обнаружения угроз
   */
  async start(): Promise<void> {
    if (this.isActive) {
      return
    }

    this.isActive = true
    
    // Загрузка базовых профилей пользователей
    await this.loadUserProfiles()
    
    // Запуск обработки очереди анализа
    this.startAnalysisLoop()
    
    // Периодическое обновление профилей (каждые 6 часов)
    setInterval(() => {
      this.updateUserProfiles()
    }, 6 * 60 * 60 * 1000)

    // Периодическая очистка старых угроз (каждые 24 часа)
    setInterval(() => {
      this.cleanupOldThreats()
    }, 24 * 60 * 60 * 1000)

    SecurityLogger.logSecurityInfo({
      message: 'Automated threat detection started',
      modelsCount: this.threatModels.length,
      profilesCount: this.userProfiles.size,
    })

    this.emit('threat_detection_started', {
      timestamp: new Date(),
      modelsLoaded: this.threatModels.length,
    })
  }

  /**
   * Остановка системы
   */
  stop(): void {
    this.isActive = false
    this.removeAllListeners()
    SecurityLogger.logSecurityInfo({ message: 'Automated threat detection stopped' })
  }

  /**
   * Анализ события пользователя
   */
  async analyzeUserEvent(event: {
    userId: string
    organizationType: string
    organizationId: string
    action: CommercialAccessType
    resourceType: ResourceType
    resourceId?: string
    metadata?: Record<string, unknown>
    ipAddress?: string
    userAgent?: string
    timestamp: Date
  }): Promise<DetectedThreat[]> {
    if (!this.isActive) {
      return []
    }

    // Добавляем событие в очередь анализа
    this.analysisQueue.push({ userId: event.userId, event })

    // Немедленный анализ для критичных событий
    if (this.isCriticalEvent(event)) {
      return await this.performImmediateAnalysis(event)
    }

    return []
  }

  /**
   * Получение профиля пользователя
   */
  getUserProfile(userId: string): UserProfile | undefined {
    return this.userProfiles.get(userId)
  }

  /**
   * Получение обнаруженных угроз
   */
  getDetectedThreats(filters?: {
    userId?: string
    severity?: string
    status?: string
    limit?: number
  }): DetectedThreat[] {
    let threats = Array.from(this.detectedThreats.values())

    if (filters) {
      if (filters.userId) {
        threats = threats.filter((t) => t.userId === filters.userId)
      }
      if (filters.severity) {
        const model = this.threatModels.find((m) => m.id === threats[0]?.modelId)
        threats = threats.filter(() => model?.severity === filters.severity)
      }
      if (filters.status) {
        threats = threats.filter((t) => t.status === filters.status)
      }
      if (filters.limit) {
        threats = threats.slice(0, filters.limit)
      }
    }

    return threats.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())
  }

  /**
   * Обновление статуса угрозы
   */
  async updateThreatStatus(
    threatId: string,
    status: DetectedThreat['status'],
    feedback?: { accurate: boolean; comment?: string },
  ): Promise<void> {
    const threat = this.detectedThreats.get(threatId)
    if (!threat) {
      throw new Error(`Threat ${threatId} not found`)
    }

    threat.status = status

    // Обновляем модель на основе обратной связи
    if (feedback) {
      await this.updateModelAccuracy(threat.modelId, feedback.accurate)
    }

    SecurityLogger.logSecurityInfo({
      message: 'Threat status updated',
      threatId,
      newStatus: status,
      feedback,
    })

    this.emit('threat_status_updated', {
      threat,
      oldStatus: threat.status,
      newStatus: status,
      feedback,
    })
  }

  /**
   * Инициализация моделей угроз
   */
  private initializeThreatModels(): void {
    this.threatModels = [
      {
        id: 'data-scraping-detection',
        name: 'Data Scraping Detection',
        description: 'Detects systematic data extraction attempts',
        severity: 'HIGH',
        confidence: 85,
        falsePositiveRate: 0.05,
        enabled: true,
        lastUpdated: new Date(),
        patterns: [
          {
            type: 'VOLUMETRIC',
            rule: 'actions_per_minute > 10',
            weight: 0.4,
            threshold: 10,
            timeWindow: 1,
          },
          {
            type: 'BEHAVIORAL',
            rule: 'sequential_resource_access',
            weight: 0.3,
            threshold: 20,
            timeWindow: 5,
          },
          {
            type: 'TEMPORAL',
            rule: 'consistent_interval_pattern',
            weight: 0.3,
            threshold: 0.8,
            timeWindow: 10,
          },
        ],
      },
      {
        id: 'competitor-intelligence-gathering',
        name: 'Competitor Intelligence Gathering',
        description: 'Detects attempts to gather competitive intelligence',
        severity: 'CRITICAL',
        confidence: 75,
        falsePositiveRate: 0.08,
        enabled: true,
        lastUpdated: new Date(),
        patterns: [
          {
            type: 'CONTEXTUAL',
            rule: 'cross_organization_price_viewing',
            weight: 0.5,
            threshold: 5,
            timeWindow: 60,
          },
          {
            type: 'BEHAVIORAL',
            rule: 'recipe_focus_pattern',
            weight: 0.3,
            threshold: 3,
            timeWindow: 30,
          },
          {
            type: 'TEMPORAL',
            rule: 'off_hours_activity',
            weight: 0.2,
            threshold: 0.3,
            timeWindow: 60,
          },
        ],
      },
      {
        id: 'insider-threat-detection',
        name: 'Insider Threat Detection',
        description: 'Detects unusual behavior from trusted users',
        severity: 'CRITICAL',
        confidence: 70,
        falsePositiveRate: 0.12,
        enabled: true,
        lastUpdated: new Date(),
        patterns: [
          {
            type: 'BEHAVIORAL',
            rule: 'deviation_from_baseline > 3_sigma',
            weight: 0.4,
            threshold: 3,
            timeWindow: 60,
          },
          {
            type: 'CONTEXTUAL',
            rule: 'access_to_unusual_resources',
            weight: 0.3,
            threshold: 5,
            timeWindow: 30,
          },
          {
            type: 'TEMPORAL',
            rule: 'activity_time_anomaly',
            weight: 0.3,
            threshold: 0.5,
            timeWindow: 60,
          },
        ],
      },
      {
        id: 'account-compromise-detection',
        name: 'Account Compromise Detection',
        description: 'Detects potentially compromised user accounts',
        severity: 'CRITICAL',
        confidence: 80,
        falsePositiveRate: 0.06,
        enabled: true,
        lastUpdated: new Date(),
        patterns: [
          {
            type: 'CONTEXTUAL',
            rule: 'ip_geolocation_anomaly',
            weight: 0.4,
            threshold: 1,
            timeWindow: 5,
          },
          {
            type: 'BEHAVIORAL',
            rule: 'user_agent_change',
            weight: 0.2,
            threshold: 1,
            timeWindow: 10,
          },
          {
            type: 'TEMPORAL',
            rule: 'simultaneous_sessions',
            weight: 0.4,
            threshold: 2,
            timeWindow: 1,
          },
        ],
      },
    ]
  }

  /**
   * Загрузка профилей пользователей
   */
  private async loadUserProfiles(): Promise<void> {
    try {
      // Получаем всех активных пользователей
      const users = await this.prisma.user.findMany({
        include: { organization: true },
        where: {
          // Только пользователи, активные за последние 30 дней
          auditLogs: {
            some: {
              timestamp: {
                gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
              },
            },
          },
        },
      })

      for (const user of users) {
        const profile = await this.buildUserProfile(user.id)
        if (profile) {
          this.userProfiles.set(user.id, profile)
        }
      }

      SecurityLogger.logSecurityInfo({
        message: 'User profiles loaded',
        count: this.userProfiles.size,
      })
    } catch (error) {
      SecurityLogger.logSecurityError(error as Error, {
        operation: 'loadUserProfiles',
      })
    }
  }

  /**
   * Построение профиля пользователя
   */
  private async buildUserProfile(userId: string): Promise<UserProfile | null> {
    try {
      const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)

      // Получаем активность пользователя за последние 30 дней
      const auditLogs = await this.prisma.auditLog.findMany({
        where: {
          userId,
          timestamp: { gte: thirtyDaysAgo },
          action: { startsWith: 'DATA_ACCESS:' },
        },
        orderBy: { timestamp: 'desc' },
      })

      if (auditLogs.length === 0) {
        return null
      }

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

      if (!user) return null

      // Вычисляем базовые показатели
      const avgActionsPerHour = this.calculateAvgActionsPerHour(auditLogs)
      const avgActionsPerDay = this.calculateAvgActionsPerDay(auditLogs)
      const commonActions = this.getCommonActions(auditLogs)
      const usualTimePattern = this.getTimePattern(auditLogs)
      const commonResources = this.getCommonResources(auditLogs)
      const peakHours = this.getPeakHours(usualTimePattern)

      return {
        userId,
        organizationType: user.organization?.type || 'UNKNOWN',
        organizationId: user.organizationId || '',
        baseline: {
          avgActionsPerHour,
          avgActionsPerDay,
          commonActions,
          usualTimePattern,
          commonResources,
          peakHours,
        },
        anomalies: [],
        riskScore: 0,
        lastAnalysis: new Date(),
      }
    } catch (error) {
      SecurityLogger.logSecurityError(error as Error, {
        operation: 'buildUserProfile',
        userId,
      })
      return null
    }
  }

  /**
   * Запуск цикла анализа
   */
  private startAnalysisLoop(): void {
    setInterval(async () => {
      if (this.processing || this.analysisQueue.length === 0) {
        return
      }

      this.processing = true

      try {
        const batch = this.analysisQueue.splice(0, 50) // Обрабатываем по 50 событий за раз

        for (const { userId, event } of batch) {
          await this.analyzeEvent(userId, event)
        }
      } catch (error) {
        SecurityLogger.logSecurityError(error as Error, {
          operation: 'analysisLoop',
        })
      } finally {
        this.processing = false
      }
    }, 5000) // Каждые 5 секунд
  }

  /**
   * Анализ события
   */
  private async analyzeEvent(userId: string, event: any): Promise<void> {
    const profile = this.userProfiles.get(userId)
    if (!profile) {
      // Создаем профиль на лету для нового пользователя
      const newProfile = await this.buildUserProfile(userId)
      if (newProfile) {
        this.userProfiles.set(userId, newProfile)
      }
      return
    }

    // Анализируем событие каждой моделью угрозы
    for (const model of this.threatModels.filter((m) => m.enabled)) {
      const threatScore = await this.evaluateThreatModel(model, profile, event)
      
      if (threatScore > 0.7) {
        // Высокая вероятность угрозы
        await this.createThreatAlert(model, profile, event, threatScore)
      }
    }

    // Обновляем профиль пользователя
    this.updateProfileWithEvent(profile, event)
  }

  /**
   * Оценка модели угрозы
   */
  private async evaluateThreatModel(
    model: ThreatModel,
    profile: UserProfile,
    event: any,
  ): Promise<number> {
    let totalScore = 0
    let totalWeight = 0

    for (const pattern of model.patterns) {
      const score = await this.evaluatePattern(pattern, profile, event)
      totalScore += score * pattern.weight
      totalWeight += pattern.weight
    }

    return totalWeight > 0 ? totalScore / totalWeight : 0
  }

  /**
   * Оценка паттерна угрозы
   */
  private async evaluatePattern(
    pattern: ThreatPattern,
    profile: UserProfile,
    event: any,
  ): Promise<number> {
    const now = new Date()
    const windowStart = new Date(now.getTime() - pattern.timeWindow * 60 * 1000)

    switch (pattern.type) {
      case 'VOLUMETRIC':
        return await this.evaluateVolumetricPattern(pattern, profile, event, windowStart)

      case 'BEHAVIORAL':
        return await this.evaluateBehavioralPattern(pattern, profile, event, windowStart)

      case 'TEMPORAL':
        return await this.evaluateTemporalPattern(pattern, profile, event, windowStart)

      case 'CONTEXTUAL':
        return await this.evaluateContextualPattern(pattern, profile, event, windowStart)

      default:
        return 0
    }
  }

  /**
   * Оценка объемного паттерна
   */
  private async evaluateVolumetricPattern(
    pattern: ThreatPattern,
    profile: UserProfile,
    event: any,
    windowStart: Date,
  ): Promise<number> {
    if (pattern.rule === 'actions_per_minute > 10') {
      const recentActions = await this.prisma.auditLog.count({
        where: {
          userId: profile.userId,
          timestamp: { gte: windowStart },
          action: { startsWith: 'DATA_ACCESS:' },
        },
      })

      const actionsPerMinute = recentActions / pattern.timeWindow
      return actionsPerMinute > pattern.threshold ? 1.0 : actionsPerMinute / pattern.threshold
    }

    return 0
  }

  /**
   * Оценка поведенческого паттерна
   */
  private async evaluateBehavioralPattern(
    pattern: ThreatPattern,
    profile: UserProfile,
    event: any,
    windowStart: Date,
  ): Promise<number> {
    if (pattern.rule === 'deviation_from_baseline > 3_sigma') {
      const currentHour = new Date().getHours()
      const expectedActivity = profile.baseline.usualTimePattern[currentHour] || 0
      const currentActivity = await this.getHourlyActivity(profile.userId, currentHour)

      if (expectedActivity === 0) return 0

      const deviation = Math.abs(currentActivity - expectedActivity) / expectedActivity
      return Math.min(1.0, deviation / 3) // 3 сигмы как порог
    }

    if (pattern.rule === 'sequential_resource_access') {
      // TODO: реализовать логику последовательного доступа к ресурсам
      return 0
    }

    return 0
  }

  /**
   * Оценка временного паттерна
   */
  private async evaluateTemporalPattern(
    pattern: ThreatPattern,
    profile: UserProfile,
    event: any,
    windowStart: Date,
  ): Promise<number> {
    if (pattern.rule === 'off_hours_activity') {
      const hour = event.timestamp.getHours()
      const isOffHours = hour < 6 || hour > 22 // Ночное время
      const offHoursRatio = this.calculateOffHoursRatio(profile, windowStart)

      return isOffHours && offHoursRatio > pattern.threshold ? 1.0 : offHoursRatio / pattern.threshold
    }

    return 0
  }

  /**
   * Оценка контекстуального паттерна
   */
  private async evaluateContextualPattern(
    pattern: ThreatPattern,
    profile: UserProfile,
    event: any,
    windowStart: Date,
  ): Promise<number> {
    if (pattern.rule === 'cross_organization_price_viewing') {
      // TODO: реализовать логику межорганизационного просмотра цен
      return 0
    }

    if (pattern.rule === 'ip_geolocation_anomaly') {
      // TODO: реализовать проверку геолокации IP
      return 0
    }

    return 0
  }

  /**
   * Проверка критичности события
   */
  private isCriticalEvent(event: any): boolean {
    const criticalActions = ['VIEW_RECIPE', 'BULK_EXPORT', 'VIEW_MARGINS']
    return criticalActions.includes(event.action)
  }

  /**
   * Немедленный анализ критичного события
   */
  private async performImmediateAnalysis(event: any): Promise<DetectedThreat[]> {
    const threats: DetectedThreat[] = []
    const profile = this.userProfiles.get(event.userId)

    if (!profile) {
      return threats
    }

    // Анализируем только критичные модели
    const criticalModels = this.threatModels.filter(
      (m) => m.enabled && m.severity === 'CRITICAL',
    )

    for (const model of criticalModels) {
      const threatScore = await this.evaluateThreatModel(model, profile, event)
      
      if (threatScore > 0.6) {
        // Для критичных событий понижаем порог
        const threat = await this.createThreatAlert(model, profile, event, threatScore)
        threats.push(threat)
      }
    }

    return threats
  }

  /**
   * Создание алерта угрозы
   */
  private async createThreatAlert(
    model: ThreatModel,
    profile: UserProfile,
    event: any,
    threatScore: number,
  ): Promise<DetectedThreat> {
    const threat: DetectedThreat = {
      id: `threat-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
      modelId: model.id,
      userId: profile.userId,
      organizationType: profile.organizationType,
      threatType: model.name,
      description: model.description,
      confidence: Math.round(threatScore * model.confidence),
      riskScore: Math.round(threatScore * 100),
      indicators: this.extractThreatIndicators(model, profile, event),
      evidence: {
        event,
        profileBaseline: profile.baseline,
        modelPatterns: model.patterns,
        threatScore,
      },
      timestamp: new Date(),
      status: 'NEW',
    }

    this.detectedThreats.set(threat.id, threat)

    // Создаем security alert через существующую систему
    const alertsInstance = RealTimeSecurityAlerts.getInstance(this.prisma)
    await alertsInstance.generateAlert({
      type: 'THREAT_DETECTED',
      severity: this.mapSeverity(model.severity),
      userId: profile.userId,
      message: `${model.name}: ${model.description}`,
      metadata: {
        threatId: threat.id,
        confidence: threat.confidence,
        riskScore: threat.riskScore,
        indicators: threat.indicators,
      },
    })

    SecurityLogger.logSecurityAlert({
      id: threat.id,
      type: 'THREAT_DETECTED',
      severity: model.severity as any,
      userId: profile.userId,
      message: threat.description,
      metadata: threat.evidence,
      timestamp: threat.timestamp,
      resolved: false,
    })

    this.emit('threat_detected', threat)

    return threat
  }

  /**
   * Извлечение индикаторов угрозы
   */
  private extractThreatIndicators(model: ThreatModel, profile: UserProfile, event: any): string[] {
    const indicators: string[] = []

    // Базовые индикаторы
    indicators.push(`Model: ${model.name}`)
    indicators.push(`User: ${profile.userId}`)
    indicators.push(`Organization: ${profile.organizationType}`)
    indicators.push(`Action: ${event.action}`)

    // Специфичные индикаторы в зависимости от модели
    if (model.id === 'data-scraping-detection') {
      indicators.push('High frequency access detected')
      indicators.push('Sequential resource pattern')
    }

    if (model.id === 'competitor-intelligence-gathering') {
      indicators.push('Cross-organization data access')
      indicators.push('Price/recipe focus pattern')
    }

    return indicators
  }

  /**
   * Маппинг уровня серьезности
   */
  private mapSeverity(severity: string): SecurityAlert['severity'] {
    const mapping: Record<string, SecurityAlert['severity']> = {
      LOW: 'LOW',
      MEDIUM: 'MEDIUM',
      HIGH: 'HIGH',
      CRITICAL: 'CRITICAL',
    }
    return mapping[severity] || 'MEDIUM'
  }

  /**
   * Обновление профиля пользователя с новым событием
   */
  private updateProfileWithEvent(profile: UserProfile, event: any): void {
    // Простое обновление - в реальной системе это должно быть более сложным
    profile.lastAnalysis = new Date()
  }

  /**
   * Вычисление средней активности в час
   */
  private calculateAvgActionsPerHour(logs: any[]): number {
    if (logs.length === 0) return 0

    const hourlyCount = new Map<string, number>()
    
    logs.forEach((log) => {
      const hour = log.timestamp.toISOString().substring(0, 13) // YYYY-MM-DDTHH
      hourlyCount.set(hour, (hourlyCount.get(hour) || 0) + 1)
    })

    const total = Array.from(hourlyCount.values()).reduce((sum, count) => sum + count, 0)
    return total / hourlyCount.size
  }

  /**
   * Вычисление средней активности в день
   */
  private calculateAvgActionsPerDay(logs: any[]): number {
    if (logs.length === 0) return 0

    const dailyCount = new Map<string, number>()
    
    logs.forEach((log) => {
      const day = log.timestamp.toISOString().substring(0, 10) // YYYY-MM-DD
      dailyCount.set(day, (dailyCount.get(day) || 0) + 1)
    })

    const total = Array.from(dailyCount.values()).reduce((sum, count) => sum + count, 0)
    return total / dailyCount.size
  }

  /**
   * Получение общих действий
   */
  private getCommonActions(logs: any[]): Array<{ action: string; frequency: number }> {
    const actionCount = new Map<string, number>()
    
    logs.forEach((log) => {
      const action = log.action.replace('DATA_ACCESS:', '')
      actionCount.set(action, (actionCount.get(action) || 0) + 1)
    })

    return Array.from(actionCount.entries())
      .map(([action, count]) => ({
        action,
        frequency: count / logs.length,
      }))
      .sort((a, b) => b.frequency - a.frequency)
      .slice(0, 10)
  }

  /**
   * Получение паттерна времени
   */
  private getTimePattern(logs: any[]): number[] {
    const pattern = new Array(24).fill(0)
    
    logs.forEach((log) => {
      const hour = log.timestamp.getHours()
      pattern[hour]++
    })

    // Нормализуем по общему количеству логов
    return pattern.map((count) => count / logs.length)
  }

  /**
   * Получение общих ресурсов
   */
  private getCommonResources(logs: any[]): string[] {
    const resourceCount = new Map<string, number>()
    
    logs.forEach((log) => {
      if (log.resourceId) {
        resourceCount.set(log.resourceId, (resourceCount.get(log.resourceId) || 0) + 1)
      }
    })

    return Array.from(resourceCount.entries())
      .sort(([, a], [, b]) => b - a)
      .slice(0, 20)
      .map(([resource]) => resource)
  }

  /**
   * Получение пиковых часов
   */
  private getPeakHours(timePattern: number[]): number[] {
    const avg = timePattern.reduce((sum, val) => sum + val, 0) / timePattern.length
    const threshold = avg * 1.5 // 150% от среднего

    return timePattern
      .map((activity, hour) => ({ hour, activity }))
      .filter(({ activity }) => activity > threshold)
      .map(({ hour }) => hour)
  }

  /**
   * Получение активности по часам
   */
  private async getHourlyActivity(userId: string, hour: number): Promise<number> {
    const startOfHour = new Date()
    startOfHour.setHours(hour, 0, 0, 0)
    const endOfHour = new Date()
    endOfHour.setHours(hour, 59, 59, 999)

    return await this.prisma.auditLog.count({
      where: {
        userId,
        timestamp: {
          gte: startOfHour,
          lte: endOfHour,
        },
        action: { startsWith: 'DATA_ACCESS:' },
      },
    })
  }

  /**
   * Вычисление соотношения ночной активности
   */
  private calculateOffHoursRatio(profile: UserProfile, since: Date): number {
    const offHoursPattern = profile.baseline.usualTimePattern
      .slice(0, 6) // 0-6 утра
      .concat(profile.baseline.usualTimePattern.slice(22)) // 22-23 вечера

    const totalOffHours = offHoursPattern.reduce((sum, val) => sum + val, 0)
    const totalActivity = profile.baseline.usualTimePattern.reduce((sum, val) => sum + val, 0)

    return totalActivity > 0 ? totalOffHours / totalActivity : 0
  }

  /**
   * Обновление точности модели
   */
  private async updateModelAccuracy(modelId: string, wasAccurate: boolean): Promise<void> {
    const model = this.threatModels.find((m) => m.id === modelId)
    if (!model) return

    // Простое обновление confidence на основе обратной связи
    if (wasAccurate) {
      model.confidence = Math.min(100, model.confidence + 1)
      model.falsePositiveRate = Math.max(0, model.falsePositiveRate - 0.01)
    } else {
      model.confidence = Math.max(0, model.confidence - 2)
      model.falsePositiveRate = Math.min(1, model.falsePositiveRate + 0.02)
    }

    model.lastUpdated = new Date()

    SecurityLogger.logSecurityInfo({
      message: 'Threat model accuracy updated',
      modelId,
      wasAccurate,
      newConfidence: model.confidence,
      newFalsePositiveRate: model.falsePositiveRate,
    })
  }

  /**
   * Обновление профилей пользователей
   */
  private async updateUserProfiles(): Promise<void> {
    SecurityLogger.logSecurityInfo({ message: 'Updating user profiles...' })

    for (const [userId] of this.userProfiles) {
      try {
        const updatedProfile = await this.buildUserProfile(userId)
        if (updatedProfile) {
          this.userProfiles.set(userId, updatedProfile)
        }
      } catch (error) {
        SecurityLogger.logSecurityError(error as Error, {
          operation: 'updateUserProfile',
          userId,
        })
      }
    }

    SecurityLogger.logSecurityInfo({
      message: 'User profiles updated',
      count: this.userProfiles.size,
    })
  }

  /**
   * Очистка старых угроз
   */
  private cleanupOldThreats(): void {
    const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
    let cleaned = 0

    for (const [id, threat] of this.detectedThreats) {
      if (threat.timestamp < sevenDaysAgo && threat.status === 'RESOLVED') {
        this.detectedThreats.delete(id)
        cleaned++
      }
    }

    SecurityLogger.logSecurityInfo({
      message: 'Old threats cleaned up',
      cleaned,
      remaining: this.detectedThreats.size,
    })
  }
}