/**
 * Sistema de Auditoria de Segurança
 * 
 * Registra eventos de segurança sem armazenar dados sensíveis.
 * Mantém histórico limitado de eventos para análise.
 */

const MAX_EVENTS = 100;
const AUDIT_KEY = 'security_audit_log';

/**
 * Tipos de eventos de segurança
 */
export const AuditEventType = {
  LOGIN_SUCCESS: 'LOGIN_SUCCESS',
  LOGIN_FAILED: 'LOGIN_FAILED',
  LOGOUT: 'LOGOUT',
  TOKEN_EXPIRED: 'TOKEN_EXPIRED',
  TOKEN_INVALID: 'TOKEN_INVALID',
  RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',
  SUSPICIOUS_ACTIVITY: 'SUSPICIOUS_ACTIVITY',
  UNAUTHORIZED_ACCESS: 'UNAUTHORIZED_ACCESS',
  CSRF_VIOLATION: 'CSRF_VIOLATION',
  DATA_ACCESS: 'DATA_ACCESS'
};

/**
 * Registra um evento de segurança
 * @param {string} type - Tipo do evento (AuditEventType)
 * @param {Object} details - Detalhes do evento (sem dados sensíveis)
 * @returns {void}
 */
export const logSecurityEvent = (type, details = {}) => {
  if (typeof window === 'undefined') {
    return;
  }
  
  const event = {
    type,
    timestamp: Date.now(),
    details: sanitizeEventDetails(details),
    userAgent: navigator.userAgent,
    origin: window.location.origin,
    path: window.location.pathname
  };
  
  // Obtém eventos existentes
  const existingEvents = getSecurityEvents();
  
  // Adiciona novo evento
  existingEvents.push(event);
  
  // Mantém apenas os últimos MAX_EVENTS
  if (existingEvents.length > MAX_EVENTS) {
    existingEvents.shift();
  }
  
  // Salva eventos
  try {
    sessionStorage.setItem(AUDIT_KEY, JSON.stringify(existingEvents));
  } catch (e) {
    // Se sessionStorage estiver cheio, remove eventos mais antigos
    const half = Math.floor(existingEvents.length / 2);
    const recentEvents = existingEvents.slice(half);
    try {
      sessionStorage.setItem(AUDIT_KEY, JSON.stringify(recentEvents));
    } catch (e2) {
      // Se ainda falhar, limpa tudo
      sessionStorage.removeItem(AUDIT_KEY);
    }
  }
};

/**
 * Sanitiza detalhes do evento removendo dados sensíveis
 * @param {Object} details - Detalhes do evento
 * @returns {Object} Detalhes sanitizados
 */
const sanitizeEventDetails = (details) => {
  if (!details || typeof details !== 'object') {
    return {};
  }
  
  const sanitized = { ...details };
  
  // Remove campos sensíveis
  const sensitiveFields = [
    'token',
    'password',
    'senha',
    'secret',
    'apiKey',
    'accessToken',
    'refreshToken',
    'csrfToken'
  ];
  
  sensitiveFields.forEach(field => {
    if (sanitized[field]) {
      delete sanitized[field];
      sanitized[`${field}_present`] = true; // Indica que estava presente, mas não armazena valor
    }
  });
  
  // Mascara emails (mostra apenas domínio)
  if (sanitized.email) {
    const email = sanitized.email;
    const [local, domain] = email.split('@');
    if (local && domain) {
      sanitized.email = `${local.substring(0, 2)}***@${domain}`;
    }
  }
  
  // Limita tamanho de strings
  Object.keys(sanitized).forEach(key => {
    if (typeof sanitized[key] === 'string' && sanitized[key].length > 200) {
      sanitized[key] = sanitized[key].substring(0, 200) + '...';
    }
  });
  
  return sanitized;
};

/**
 * Obtém todos os eventos de segurança
 * @returns {Array} Array de eventos
 */
export const getSecurityEvents = () => {
  if (typeof window === 'undefined') {
    return [];
  }
  
  try {
    const eventsJson = sessionStorage.getItem(AUDIT_KEY);
    if (!eventsJson) {
      return [];
    }
    
    return JSON.parse(eventsJson);
  } catch (e) {
    return [];
  }
};

/**
 * Obtém eventos de um tipo específico
 * @param {string} type - Tipo do evento
 * @param {number} limit - Limite de eventos (padrão: 10)
 * @returns {Array} Array de eventos
 */
export const getEventsByType = (type, limit = 10) => {
  const events = getSecurityEvents();
  return events
    .filter(event => event.type === type)
    .slice(-limit)
    .reverse();
};

/**
 * Detecta padrões suspeitos nos eventos
 * @returns {Array} Array de alertas de segurança
 */
export const detectSuspiciousPatterns = () => {
  const events = getSecurityEvents();
  const alerts = [];
  
  // Detecta múltiplas tentativas de login falhadas
  const failedLogins = events.filter(e => e.type === AuditEventType.LOGIN_FAILED);
  if (failedLogins.length >= 5) {
    const recentFailures = failedLogins.filter(e => (Date.now() - e.timestamp) < 15 * 60 * 1000);
    if (recentFailures.length >= 5) {
      alerts.push({
        level: 'high',
        type: 'MULTIPLE_FAILED_LOGINS',
        message: `${recentFailures.length} tentativas de login falhadas nos últimos 15 minutos`,
        timestamp: Date.now()
      });
    }
  }
  
  // Detecta múltiplos tokens expirados
  const expiredTokens = events.filter(e => e.type === AuditEventType.TOKEN_EXPIRED);
  if (expiredTokens.length >= 10) {
    alerts.push({
      level: 'medium',
      type: 'MULTIPLE_TOKEN_EXPIRATIONS',
      message: `${expiredTokens.length} tokens expirados detectados`,
      timestamp: Date.now()
    });
  }
  
  // Detecta tentativas de acesso não autorizado
  const unauthorized = events.filter(e => e.type === AuditEventType.UNAUTHORIZED_ACCESS);
  if (unauthorized.length >= 3) {
    alerts.push({
      level: 'high',
      type: 'UNAUTHORIZED_ACCESS_ATTEMPTS',
      message: `${unauthorized.length} tentativas de acesso não autorizado`,
      timestamp: Date.now()
    });
  }
  
  return alerts;
};

/**
 * Limpa eventos antigos (mais de 24 horas)
 */
export const cleanOldEvents = () => {
  if (typeof window === 'undefined') {
    return;
  }
  
  const events = getSecurityEvents();
  const now = Date.now();
  const oneDayMs = 24 * 60 * 60 * 1000;
  
  const recentEvents = events.filter(event => (now - event.timestamp) < oneDayMs);
  
  try {
    if (recentEvents.length < events.length) {
      sessionStorage.setItem(AUDIT_KEY, JSON.stringify(recentEvents));
    }
  } catch (e) {
    // Se falhar, limpa tudo
    sessionStorage.removeItem(AUDIT_KEY);
  }
};

/**
 * Limpa todos os eventos de segurança
 */
export const clearAllEvents = () => {
  if (typeof window === 'undefined') {
    return;
  }
  
  sessionStorage.removeItem(AUDIT_KEY);
};
