/**
 * Система real-time security alerts
 *
 * Обеспечивает мгновенные уведомления о критичных событиях безопасности,
 * автоматическую эскалацию инцидентов и интеграцию с внешними системами
 */

import { EventEmitter } from 'events'

import { PrismaClient } from '@prisma/client'

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

import { CommercialAccessType, ResourceType, SecurityAlert } from './types'

/**
 * Конфигурация уведомлений
 */
interface NotificationConfig {
  email: {
    enabled: boolean
    recipients: string[]
    template: string
  }
  sms: {
    enabled: boolean
    phones: string[]
  }
  slack: {
    enabled: boolean
    webhook: string
    channel: string
  }
  telegram: {
    enabled: boolean
    botToken: string
    chatIds: string[]
  }
  push: {
    enabled: boolean
    serviceUrl: string
  }
}

/**
 * Правила эскалации
 */
interface EscalationRule {
  id: string
  name: string
  condition: {
    alertType: SecurityAlert['type']
    severity: SecurityAlert['severity']
    userRole?: string
    organizationType?: string
    timeWindow?: number // минуты
    threshold?: number // количество событий
  }
  actions: Array<{
    type: 'NOTIFY' | 'BLOCK_USER' | 'ESCALATE' | 'AUTO_RESOLVE'
    delay: number // секунды
    config: Record<string, unknown>
  }>
  enabled: boolean
}

/**
 * Событие real-time алерта
 */
interface RealTimeAlertEvent {
  alert: SecurityAlert
  escalationLevel: number
  autoActions: string[]
  notificationsSent: string[]
  timestamp: Date
}

/**
 * Конфигурация monitoring rules
 */
interface MonitoringRule {
  id: string
  name: string
  description: string
  type: 'RATE_LIMIT' | 'ANOMALY_DETECTION' | 'PATTERN_MATCHING' | 'THRESHOLD'
  config: {
    // Для RATE_LIMIT
    maxRequests?: number
    timeWindow?: number

    // Для ANOMALY_DETECTION
    baseline?: number
    deviation?: number

    // Для PATTERN_MATCHING
    patterns?: string[]

    // Для THRESHOLD
    field?: string
    operator?: '>' | '<' | '=' | '!=' | '>=' | '<='
    value?: number | string
  }
  severity: SecurityAlert['severity']
  enabled: boolean
}

export class RealTimeSecurityAlerts extends EventEmitter {
  private static instance: RealTimeSecurityAlerts
  private isActive = false
  private monitoringRules: MonitoringRule[] = []
  private escalationRules: EscalationRule[] = []
  private notificationConfig: NotificationConfig
  private activeAlerts = new Map<string, SecurityAlert>()
  private userSessions = new Map<string, { actions: number; lastReset: Date }>()

  constructor(private prisma: PrismaClient) {
    super()

    // Конфигурация уведомлений по умолчанию
    this.notificationConfig = {
      email: {
        enabled: process.env.SECURITY_EMAIL_ENABLED === 'true',
        recipients: process.env.SECURITY_EMAIL_RECIPIENTS?.split(',') || [],
        template: 'security-alert',
      },
      sms: {
        enabled: process.env.SECURITY_SMS_ENABLED === 'true',
        phones: process.env.SECURITY_SMS_PHONES?.split(',') || [],
      },
      slack: {
        enabled: process.env.SECURITY_SLACK_ENABLED === 'true',
        webhook: process.env.SECURITY_SLACK_WEBHOOK || '',
        channel: process.env.SECURITY_SLACK_CHANNEL || '#security-alerts',
      },
      telegram: {
        enabled: process.env.SECURITY_TELEGRAM_ENABLED === 'true',
        botToken: process.env.SECURITY_TELEGRAM_BOT_TOKEN || '',
        chatIds: process.env.SECURITY_TELEGRAM_CHAT_IDS?.split(',') || [],
      },
      push: {
        enabled: process.env.SECURITY_PUSH_ENABLED === 'true',
        serviceUrl: process.env.SECURITY_PUSH_SERVICE_URL || '',
      },
    }

    this.initializeDefaultRules()
    this.setupEventHandlers()
  }

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

  /**
   * Запуск real-time мониторинга
   */
  async start(): Promise<void> {
    if (this.isActive) {
      return
    }

    this.isActive = true
    await this.loadConfigurationFromDatabase()

    // Сбросить счетчики пользователей каждый час
    setInterval(
      () => {
        this.resetUserSessions()
      },
      60 * 60 * 1000,
    )

    SecurityLogger.logSecurityInfo({
      message: 'Real-time security monitoring started',
      activeRules: this.monitoringRules.length,
      escalationRules: this.escalationRules.length,
    })

    this.emit('monitoring_started', {
      timestamp: new Date(),
      rulesCount: this.monitoringRules.length,
    })
  }

  /**
   * Остановка мониторинга
   */
  stop(): void {
    this.isActive = false
    this.removeAllListeners()
    SecurityLogger.logSecurityInfo({ message: 'Real-time security monitoring stopped' })
  }

  /**
   * Обработка события доступа к данным
   */
  async processDataAccess(event: {
    userId: string
    organizationType: string
    organizationId: string
    action: CommercialAccessType
    resourceType: ResourceType
    resourceId?: string
    metadata?: Record<string, unknown>
    ipAddress?: string
    userAgent?: string
  }): Promise<void> {
    if (!this.isActive) {
      return
    }

    try {
      // Обновляем статистику пользователя
      this.updateUserSession(event.userId)

      // Проверяем каждое правило мониторинга
      for (const rule of this.monitoringRules.filter((r) => r.enabled)) {
        const violation = await this.checkRule(rule, event)
        if (violation) {
          await this.handleRuleViolation(rule, event, violation)
        }
      }
    } catch (error) {
      SecurityLogger.logSecurityError(error as Error, {
        operation: 'processDataAccess',
        userId: event.userId,
        action: event.action,
      })
    }
  }

  /**
   * Генерация нового алерта
   */
  async generateAlert(params: {
    type: SecurityAlert['type']
    severity: SecurityAlert['severity']
    userId: string
    message: string
    metadata: Record<string, unknown>
    autoResolve?: boolean
  }): Promise<SecurityAlert> {
    const alert: SecurityAlert = {
      id: `alert-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
      type: params.type,
      severity: params.severity,
      userId: params.userId,
      message: params.message,
      metadata: params.metadata,
      timestamp: new Date(),
      resolved: params.autoResolve || false,
    }

    // Сохраняем в базу
    await this.saveAlert(alert)

    // Добавляем в активные алерты
    if (!alert.resolved) {
      this.activeAlerts.set(alert.id, alert)
    }

    // Запускаем процесс эскалации
    await this.processEscalation(alert)

    // Отправляем событие
    this.emit('alert_generated', {
      alert,
      timestamp: new Date(),
    } as RealTimeAlertEvent)

    return alert
  }

  /**
   * Добавление нового правила мониторинга
   */
  addMonitoringRule(rule: MonitoringRule): void {
    this.monitoringRules.push(rule)
    SecurityLogger.logSecurityInfo({
      message: 'New monitoring rule added',
      ruleId: rule.id,
      ruleName: rule.name,
      type: rule.type,
    })
  }

  /**
   * Добавление правила эскалации
   */
  addEscalationRule(rule: EscalationRule): void {
    this.escalationRules.push(rule)
    SecurityLogger.logSecurityInfo({
      message: 'New escalation rule added',
      ruleId: rule.id,
      ruleName: rule.name,
    })
  }

  /**
   * Получение статистики активных алертов
   */
  getActiveAlertsStats(): {
    total: number
    bySeverity: Record<string, number>
    byType: Record<string, number>
    oldest: Date | null
  } {
    const alerts = Array.from(this.activeAlerts.values())

    const bySeverity: Record<string, number> = {}
    const byType: Record<string, number> = {}
    let oldest: Date | null = null

    alerts.forEach((alert) => {
      bySeverity[alert.severity] = (bySeverity[alert.severity] || 0) + 1
      byType[alert.type] = (byType[alert.type] || 0) + 1

      if (!oldest || alert.timestamp < oldest) {
        oldest = alert.timestamp
      }
    })

    return {
      total: alerts.length,
      bySeverity,
      byType,
      oldest,
    }
  }

  /**
   * Инициализация правил по умолчанию
   */
  private initializeDefaultRules(): void {
    // Rate limiting правила
    this.monitoringRules = [
      {
        id: 'rate-limit-view-price',
        name: 'Price View Rate Limit',
        description: 'Detect excessive price viewing',
        type: 'RATE_LIMIT',
        config: {
          maxRequests: 100,
          timeWindow: 60, // 1 час
        },
        severity: 'HIGH',
        enabled: true,
      },
      {
        id: 'rate-limit-view-recipe',
        name: 'Recipe View Rate Limit',
        description: 'Detect excessive recipe viewing',
        type: 'RATE_LIMIT',
        config: {
          maxRequests: 50,
          timeWindow: 60,
        },
        severity: 'HIGH',
        enabled: true,
      },
      {
        id: 'anomaly-night-activity',
        name: 'Night Activity Anomaly',
        description: 'Detect unusual night activity',
        type: 'ANOMALY_DETECTION',
        config: {
          baseline: 5, // Обычное количество действий ночью
          deviation: 3, // Отклонение в разах
        },
        severity: 'MEDIUM',
        enabled: true,
      },
    ]

    // Правила эскалации
    this.escalationRules = [
      {
        id: 'critical-immediate',
        name: 'Critical Immediate Escalation',
        condition: {
          alertType: 'UNAUTHORIZED_ATTEMPT',
          severity: 'CRITICAL',
        },
        actions: [
          {
            type: 'NOTIFY',
            delay: 0,
            config: { channels: ['email', 'sms', 'slack'] },
          },
          {
            type: 'BLOCK_USER',
            delay: 30,
            config: { duration: 3600 }, // 1 час
          },
        ],
        enabled: true,
      },
      {
        id: 'high-escalate',
        name: 'High Severity Escalation',
        condition: {
          alertType: 'EXCESSIVE_ACCESS',
          severity: 'HIGH',
        },
        actions: [
          {
            type: 'NOTIFY',
            delay: 0,
            config: { channels: ['slack', 'telegram'] },
          },
          {
            type: 'ESCALATE',
            delay: 300, // 5 минут
            config: { level: 2 },
          },
        ],
        enabled: true,
      },
    ]
  }

  /**
   * Настройка обработчиков событий
   */
  private setupEventHandlers(): void {
    this.on('alert_generated', async (event: RealTimeAlertEvent) => {
      SecurityLogger.logSecurityAlert(event.alert)
    })

    this.on('escalation_triggered', async (data: { alert: SecurityAlert; level: number }) => {
      SecurityLogger.logSecurityInfo({
        message: 'Alert escalation triggered',
        alertId: data.alert.id,
        level: data.level,
      })
    })
  }

  /**
   * Обновление сессии пользователя
   */
  private updateUserSession(userId: string): void {
    const now = new Date()
    const session = this.userSessions.get(userId)

    if (!session || now.getTime() - session.lastReset.getTime() > 60 * 60 * 1000) {
      // Новая сессия или прошел час
      this.userSessions.set(userId, {
        actions: 1,
        lastReset: now,
      })
    } else {
      session.actions++
    }
  }

  /**
   * Сброс сессий пользователей
   */
  private resetUserSessions(): void {
    const now = new Date()
    for (const [userId, session] of this.userSessions.entries()) {
      if (now.getTime() - session.lastReset.getTime() > 60 * 60 * 1000) {
        this.userSessions.delete(userId)
      }
    }
  }

  /**
   * Проверка правила мониторинга
   */
  private async checkRule(
    rule: MonitoringRule,
    event: {
      userId: string
      action: CommercialAccessType
      organizationType: string
      [key: string]: unknown
    },
  ): Promise<Record<string, unknown> | null> {
    switch (rule.type) {
      case 'RATE_LIMIT':
        return this.checkRateLimit(rule, event)

      case 'ANOMALY_DETECTION':
        return await this.checkAnomaly(rule, event)

      case 'PATTERN_MATCHING':
        return this.checkPattern(rule, event)

      case 'THRESHOLD':
        return this.checkThreshold(rule, event)

      default:
        return null
    }
  }

  /**
   * Проверка rate limit
   */
  private checkRateLimit(
    rule: MonitoringRule,
    event: { userId: string; action: CommercialAccessType },
  ): Record<string, unknown> | null {
    const session = this.userSessions.get(event.userId)
    if (!session) return null

    const maxRequests = rule.config.maxRequests || 100

    if (session.actions > maxRequests) {
      return {
        currentActions: session.actions,
        maxAllowed: maxRequests,
        timeWindow: rule.config.timeWindow || 60,
      }
    }

    return null
  }

  /**
   * Проверка аномалий
   */
  private async checkAnomaly(
    rule: MonitoringRule,
    event: { userId: string; action: CommercialAccessType },
  ): Promise<Record<string, unknown> | null> {
    if (rule.id === 'anomaly-night-activity') {
      const hour = new Date().getHours()
      if (hour >= 0 && hour <= 6) {
        const session = this.userSessions.get(event.userId)
        const actions = session?.actions || 0
        const baseline = rule.config.baseline || 5
        const deviation = rule.config.deviation || 3

        if (actions > baseline * deviation) {
          return {
            nightActions: actions,
            baseline,
            threshold: baseline * deviation,
          }
        }
      }
    }

    return null
  }

  /**
   * Проверка паттернов
   */
  private checkPattern(rule: MonitoringRule, event: { [key: string]: unknown }): Record<string, unknown> | null {
    // Простая реализация pattern matching
    const patterns = rule.config.patterns || []

    for (const pattern of patterns) {
      const regex = new RegExp(pattern as string)
      const eventString = JSON.stringify(event)

      if (regex.test(eventString)) {
        return {
          matchedPattern: pattern,
          eventData: eventString,
        }
      }
    }

    return null
  }

  /**
   * Проверка threshold
   */
  private checkThreshold(rule: MonitoringRule, event: { [key: string]: unknown }): Record<string, unknown> | null {
    const field = rule.config.field
    const operator = rule.config.operator
    const expectedValue = rule.config.value

    if (!field || !operator || expectedValue === undefined) {
      return null
    }

    const actualValue = event[field]
    let violated = false

    switch (operator) {
      case '>':
        violated = Number(actualValue) > Number(expectedValue)
        break
      case '<':
        violated = Number(actualValue) < Number(expectedValue)
        break
      case '>=':
        violated = Number(actualValue) >= Number(expectedValue)
        break
      case '<=':
        violated = Number(actualValue) <= Number(expectedValue)
        break
      case '=':
        violated = actualValue === expectedValue
        break
      case '!=':
        violated = actualValue !== expectedValue
        break
    }

    if (violated) {
      return {
        field,
        actualValue,
        expectedValue,
        operator,
      }
    }

    return null
  }

  /**
   * Обработка нарушения правила
   */
  private async handleRuleViolation(
    rule: MonitoringRule,
    event: { userId: string; action: CommercialAccessType; [key: string]: unknown },
    violation: Record<string, unknown>,
  ): Promise<void> {
    const alert = await this.generateAlert({
      type: 'RULE_VIOLATION',
      severity: rule.severity,
      userId: event.userId,
      message: `Rule violation: ${rule.name}`,
      metadata: {
        ruleId: rule.id,
        ruleName: rule.name,
        ruleType: rule.type,
        violation,
        event,
      },
    })

    SecurityLogger.logSecurityInfo({
      message: 'Monitoring rule violation detected',
      ruleId: rule.id,
      userId: event.userId,
      alertId: alert.id,
    })
  }

  /**
   * Обработка эскалации алерта
   */
  private async processEscalation(alert: SecurityAlert): Promise<void> {
    const matchingRules = this.escalationRules.filter(
      (rule) => rule.enabled && this.matchesEscalationCondition(rule.condition, alert),
    )

    for (const rule of matchingRules) {
      for (const action of rule.actions) {
        // Задержка перед выполнением действия
        setTimeout(async () => {
          await this.executeEscalationAction(action, alert, rule)
        }, action.delay * 1000)
      }
    }
  }

  /**
   * Проверка соответствия условиям эскалации
   */
  private matchesEscalationCondition(condition: EscalationRule['condition'], alert: SecurityAlert): boolean {
    if (condition.alertType && condition.alertType !== alert.type) {
      return false
    }

    if (condition.severity && condition.severity !== alert.severity) {
      return false
    }

    // TODO: Добавить другие проверки условий

    return true
  }

  /**
   * Выполнение действия эскалации
   */
  private async executeEscalationAction(
    action: EscalationRule['actions'][0],
    alert: SecurityAlert,
    rule: EscalationRule,
  ): Promise<void> {
    try {
      switch (action.type) {
        case 'NOTIFY':
          await this.sendNotifications(alert, action.config.channels as string[])
          break

        case 'BLOCK_USER':
          await this.blockUser(alert.userId, action.config.duration as number)
          break

        case 'ESCALATE':
          await this.escalateAlert(alert, action.config.level as number)
          break

        case 'AUTO_RESOLVE':
          await this.autoResolveAlert(alert.id)
          break
      }

      SecurityLogger.logSecurityInfo({
        message: 'Escalation action executed',
        actionType: action.type,
        alertId: alert.id,
        ruleId: rule.id,
      })
    } catch (error) {
      SecurityLogger.logSecurityError(error as Error, {
        operation: 'executeEscalationAction',
        actionType: action.type,
        alertId: alert.id,
      })
    }
  }

  /**
   * Отправка уведомлений
   */
  private async sendNotifications(alert: SecurityAlert, channels: string[]): Promise<void> {
    const promises: Promise<void>[] = []

    for (const channel of channels) {
      switch (channel) {
        case 'email':
          if (this.notificationConfig.email.enabled) {
            promises.push(this.sendEmailNotification(alert))
          }
          break

        case 'sms':
          if (this.notificationConfig.sms.enabled) {
            promises.push(this.sendSmsNotification(alert))
          }
          break

        case 'slack':
          if (this.notificationConfig.slack.enabled) {
            promises.push(this.sendSlackNotification(alert))
          }
          break

        case 'telegram':
          if (this.notificationConfig.telegram.enabled) {
            promises.push(this.sendTelegramNotification(alert))
          }
          break

        case 'push':
          if (this.notificationConfig.push.enabled) {
            promises.push(this.sendPushNotification(alert))
          }
          break
      }
    }

    await Promise.allSettled(promises)
  }

  /**
   * Отправка email уведомления
   */
  private async sendEmailNotification(alert: SecurityAlert): Promise<void> {
    // TODO: Реализовать отправку email
    console.log(`📧 Email notification sent for alert ${alert.id}`)
  }

  /**
   * Отправка SMS уведомления
   */
  private async sendSmsNotification(alert: SecurityAlert): Promise<void> {
    // TODO: Реализовать отправку SMS
    console.log(`📱 SMS notification sent for alert ${alert.id}`)
  }

  /**
   * Отправка Slack уведомления
   */
  private async sendSlackNotification(alert: SecurityAlert): Promise<void> {
    // TODO: Реализовать отправку в Slack
    console.log(`💬 Slack notification sent for alert ${alert.id}`)
  }

  /**
   * Отправка Telegram уведомления
   */
  private async sendTelegramNotification(alert: SecurityAlert): Promise<void> {
    // TODO: Реализовать отправку в Telegram
    console.log(`✈️ Telegram notification sent for alert ${alert.id}`)
  }

  /**
   * Отправка push уведомления
   */
  private async sendPushNotification(alert: SecurityAlert): Promise<void> {
    // TODO: Реализовать отправку push уведомлений
    console.log(`🔔 Push notification sent for alert ${alert.id}`)
  }

  /**
   * Блокировка пользователя
   */
  private async blockUser(userId: string, duration: number): Promise<void> {
    // TODO: Реализовать блокировку пользователя
    console.log(`🚫 User ${userId} blocked for ${duration} seconds`)
  }

  /**
   * Эскалация алерта
   */
  private async escalateAlert(alert: SecurityAlert, level: number): Promise<void> {
    this.emit('escalation_triggered', { alert, level })
  }

  /**
   * Автоматическое разрешение алерта
   */
  private async autoResolveAlert(alertId: string): Promise<void> {
    this.activeAlerts.delete(alertId)

    await this.prisma.securityAlert.update({
      where: { id: alertId },
      data: { resolved: true },
    })
  }

  /**
   * Сохранение алерта в базе данных
   */
  private async saveAlert(alert: SecurityAlert): Promise<void> {
    try {
      await this.prisma.securityAlert.create({
        data: {
          id: alert.id,
          type: alert.type,
          severity: alert.severity,
          userId: alert.userId,
          message: alert.message,
          metadata: alert.metadata as any,
          timestamp: alert.timestamp,
          resolved: alert.resolved,
        },
      })
    } catch (error) {
      SecurityLogger.logSecurityError(error as Error, {
        operation: 'saveAlert',
        alertId: alert.id,
      })
    }
  }

  /**
   * Загрузка конфигурации из базы данных
   */
  private async loadConfigurationFromDatabase(): Promise<void> {
    // TODO: Реализовать загрузку правил из базы данных
    SecurityLogger.logSecurityInfo({
      message: 'Security configuration loaded',
      monitoringRules: this.monitoringRules.length,
      escalationRules: this.escalationRules.length,
    })
  }
}
