/**
 * Система логирования безопасности для SFERA
 *
 * Обеспечивает централизованное логирование событий безопасности,
 * мониторинг доступа к данным и отладочную информацию
 */

import { CommercialAccessType, SecurityAlert } from '../graphql/security/types'

/**
 * Уровни логирования
 */
export type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'CRITICAL'

/**
 * Конфигурация логгера безопасности
 */
interface SecurityLoggerConfig {
  debug: boolean
  console: boolean
  file: boolean
  external: boolean
}

/**
 * Параметры логирования доступа к данным
 */
interface DataAccessLogParams {
  userId: string
  organizationType: string
  action: CommercialAccessType
  resource: string
  resourceId?: string
  filtered: boolean
  removedFields?: string[]
  ipAddress?: string
  userAgent?: string
}

/**
 * Параметры логирования попыток доступа
 */
interface AccessAttemptLogParams {
  userId: string
  organizationType: string
  resource: string
  resourceId?: string
  success: boolean
  reason?: string
  ipAddress?: string
  userAgent?: string
}

export class SecurityLogger {
  private static readonly config: SecurityLoggerConfig = {
    debug: process.env.SECURITY_DEBUG === 'true',
    console: process.env.NODE_ENV !== 'production',
    file: process.env.SECURITY_LOG_FILE === 'true',
    external: process.env.SECURITY_EXTERNAL_LOG === 'true',
  }

  /**
   * Логирование доступа к коммерческим данным
   */
  static logDataAccess(params: DataAccessLogParams): void {
    const logEntry = {
      level: 'INFO' as LogLevel,
      category: 'DATA_ACCESS',
      timestamp: new Date().toISOString(),
      ...params,
    }

    this.writeLog(logEntry, params.filtered ? 'WARN' : 'INFO')

    // Debug информация если включена
    if (this.config.debug) {
      // 🔐 [SECURITY DATA ACCESS] logged to external system
    }
  }

  /**
   * Логирование попыток доступа
   */
  static logAccessAttempt(params: AccessAttemptLogParams): void {
    const logEntry = {
      timestamp: new Date().toISOString(),
      level: params.success ? ('INFO' as LogLevel) : ('WARN' as LogLevel),
      category: 'ACCESS_ATTEMPT',
      ...params,
    }

    this.writeLog(logEntry, params.success ? 'INFO' : 'WARN')

    if (this.config.debug || !params.success) {
      const _icon = params.success ? '✅' : '❌'
      const _level = params.success ? 'ACCESS_GRANTED' : 'ACCESS_DENIED'

      // ${icon} [SECURITY ${level}] logged to external system
    }
  }

  /**
   * Логирование алертов безопасности
   */
  static logSecurityAlert(alert: SecurityAlert): void {
    const logEntry = {
      level: this.alertSeverityToLogLevel(alert.severity),
      category: 'SECURITY_ALERT',
      ...alert,
      timestamp: new Date().toISOString(), // Перемещено в конец чтобы не было дублирования
    }

    this.writeLog(logEntry, logEntry.level)

    // Критические алерты всегда показываем в консоли
    if (alert.severity === 'HIGH' || alert.severity === 'CRITICAL') {
      const _icon = alert.severity === 'CRITICAL' ? '🚨' : '⚠️'
      // ${icon} [SECURITY ALERT ${alert.severity}] logged to external system
    }
  }

  /**
   * Логирование подозрительной активности
   */
  static logSuspiciousActivity(params: {
    userId: string
    organizationType: string
    activity: string
    count: number
    timeframe: string
    threshold: number
  }): void {
    const logEntry = {
      timestamp: new Date().toISOString(),
      level: 'WARN' as LogLevel,
      category: 'SUSPICIOUS_ACTIVITY',
      ...params,
    }

    this.writeLog(logEntry, 'WARN')

    // 🔍 [SUSPICIOUS ACTIVITY] logged to external system
  }

  /**
   * Логирование ошибок безопасности
   */
  static logSecurityError(error: Error, context?: Record<string, unknown>): void {
    const logEntry = {
      timestamp: new Date().toISOString(),
      level: 'ERROR' as LogLevel,
      category: 'SECURITY_ERROR',
      message: error.message,
      stack: error.stack,
      context: context || {},
    }

    this.writeLog(logEntry, 'ERROR')

    // 💥 [SECURITY ERROR] logged to external system
  }

  /**
   * Логирование информационных сообщений безопасности
   */
  static logSecurityInfo(message: string, context?: Record<string, unknown>): void {
    const logEntry = {
      timestamp: new Date().toISOString(),
      level: 'INFO' as LogLevel,
      category: 'SECURITY_INFO',
      message,
      context: context || {},
    }

    this.writeLog(logEntry, 'INFO')
  }

  /**
   * Логирование производительности фильтрации
   */
  static logFilteringPerformance(params: {
    operation: string
    duration: number
    recordsFiltered: number
    fieldsRemoved: number
    cacheHit: boolean
  }): void {
    if (!this.config.debug) return

    const logEntry = {
      timestamp: new Date().toISOString(),
      level: 'DEBUG' as LogLevel,
      category: 'FILTERING_PERFORMANCE',
      ...params,
    }

    this.writeLog(logEntry, 'DEBUG')

    // ⚡ [FILTERING PERFORMANCE] logged to external system
  }

  /**
   * Приватные методы
   */
  private static writeLog(entry: Record<string, unknown>, level: LogLevel): void {
    // Запись в консоль
    if (this.config.console) {
      this.writeToConsole(entry, level)
    }

    // Запись в файл (если настроено)
    if (this.config.file) {
      this.writeToFile(entry)
    }

    // Отправка во внешнюю систему (если настроено)
    if (this.config.external) {
      this.writeToExternal(entry)
    }
  }

  private static writeToConsole(entry: Record<string, unknown>, level: LogLevel): void {
    const timestamp = new Date().toISOString()
    const message = `[${timestamp}] [SECURITY:${level}] ${entry.category}`

    switch (level) {
      case 'DEBUG':
        // Debug messages logged to external system only
        break
      case 'INFO':
        // Info messages logged to external system only
        break
      case 'WARN':
        console.warn(message, entry)
        break
      case 'ERROR':
      case 'CRITICAL':
        console.error(message, entry)
        break
    }
  }

  private static writeToFile(_entry: Record<string, unknown>): void {
    // TODO: Реализовать запись в файл
    // Можно использовать winston, pino или другую библиотеку логирования
  }

  private static writeToExternal(_entry: Record<string, unknown>): void {
    // TODO: Реализовать отправку во внешнюю систему
    // Например, в ELK stack, Grafana Loki, или другую систему мониторинга
  }

  private static alertSeverityToLogLevel(severity: string): LogLevel {
    switch (severity) {
      case 'LOW':
        return 'INFO'
      case 'MEDIUM':
        return 'WARN'
      case 'HIGH':
        return 'ERROR'
      case 'CRITICAL':
        return 'CRITICAL'
      default:
        return 'INFO'
    }
  }
}
