/**
 * Audit Logger - Phase 8 Enterprise Pattern
 *
 * Tracks all state changes, user actions, and workflow transitions
 * for compliance, debugging, and analytics.
 */

class AuditLogger {
  constructor() {
    this.logs = [];
    this.maxLogs = 1000;
    this.storageKey = 'dss-audit-logs';
    this.sessionId = this.generateSessionId();
    this.logLevel = 'info'; // 'debug', 'info', 'warn', 'error'
    this.loadFromStorage();
  }

  /**
   * Generate unique session ID
   */
  generateSessionId() {
    return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * Create audit log entry
   */
  createLogEntry(action, category, details = {}, level = 'info') {
    return {
      id: `log-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
      timestamp: new Date().toISOString(),
      sessionId: this.sessionId,
      action,
      category,
      level,
      details,
      userAgent: navigator.userAgent,
    };
  }

  /**
   * Log user action
   */
  logAction(action, details = {}) {
    const entry = this.createLogEntry(action, 'user_action', details, 'info');
    this.addLog(entry);
    return entry.id;
  }

  /**
   * Log state change
   */
  logStateChange(key, oldValue, newValue, details = {}) {
    const entry = this.createLogEntry(
      `state_change`,
      'state',
      {
        key,
        oldValue: this.sanitize(oldValue),
        newValue: this.sanitize(newValue),
        ...details
      },
      'info'
    );
    this.addLog(entry);
    return entry.id;
  }

  /**
   * Log API call
   */
  logApiCall(method, endpoint, status, responseTime = 0, details = {}) {
    const entry = this.createLogEntry(
      `api_${method.toLowerCase()}`,
      'api',
      {
        endpoint,
        method,
        status,
        responseTime,
        ...details
      },
      status >= 400 ? 'warn' : 'info'
    );
    this.addLog(entry);
    return entry.id;
  }

  /**
   * Log error
   */
  logError(error, context = '') {
    const entry = this.createLogEntry(
      'error',
      'error',
      {
        message: error.message,
        stack: error.stack,
        context
      },
      'error'
    );
    this.addLog(entry);
    console.error('[AuditLogger]', error);
    return entry.id;
  }

  /**
   * Log warning
   */
  logWarning(message, details = {}) {
    const entry = this.createLogEntry(
      'warning',
      'warning',
      { message, ...details },
      'warn'
    );
    this.addLog(entry);
    return entry.id;
  }

  /**
   * Log permission check
   */
  logPermissionCheck(action, allowed, user, reason = '') {
    const entry = this.createLogEntry(
      'permission_check',
      'security',
      {
        action,
        allowed,
        user,
        reason
      },
      allowed ? 'info' : 'warn'
    );
    this.addLog(entry);
    return entry.id;
  }

  /**
   * Add log entry to collection
   */
  addLog(entry) {
    this.logs.unshift(entry);
    if (this.logs.length > this.maxLogs) {
      this.logs.pop();
    }
    this.saveToStorage();
  }

  /**
   * Sanitize sensitive data before logging
   */
  sanitize(value) {
    if (typeof value !== 'object') return value;

    const sanitized = { ...value };
    const sensitiveKeys = ['password', 'token', 'apiKey', 'secret', 'key'];

    for (const key of Object.keys(sanitized)) {
      if (sensitiveKeys.some(sk => key.toLowerCase().includes(sk))) {
        sanitized[key] = '***REDACTED***';
      }
    }

    return sanitized;
  }

  /**
   * Get logs filtered by criteria
   */
  getLogs(filters = {}) {
    let result = [...this.logs];

    if (filters.action) {
      result = result.filter(l => l.action === filters.action);
    }
    if (filters.category) {
      result = result.filter(l => l.category === filters.category);
    }
    if (filters.level) {
      result = result.filter(l => l.level === filters.level);
    }
    if (filters.startTime) {
      result = result.filter(l => new Date(l.timestamp) >= new Date(filters.startTime));
    }
    if (filters.endTime) {
      result = result.filter(l => new Date(l.timestamp) <= new Date(filters.endTime));
    }
    if (filters.sessionId) {
      result = result.filter(l => l.sessionId === filters.sessionId);
    }
    if (filters.limit) {
      result = result.slice(0, filters.limit);
    }

    return result;
  }

  /**
   * Get statistics
   */
  getStats() {
    return {
      totalLogs: this.logs.length,
      sessionId: this.sessionId,
      byCategory: this.logs.reduce((acc, log) => {
        acc[log.category] = (acc[log.category] || 0) + 1;
        return acc;
      }, {}),
      byLevel: this.logs.reduce((acc, log) => {
        acc[log.level] = (acc[log.level] || 0) + 1;
        return acc;
      }, {}),
      oldestLog: this.logs[this.logs.length - 1]?.timestamp,
      newestLog: this.logs[0]?.timestamp,
    };
  }

  /**
   * Export logs as JSON
   */
  exportLogs(filters = {}) {
    const logs = this.getLogs(filters);
    return JSON.stringify({
      exportDate: new Date().toISOString(),
      sessionId: this.sessionId,
      count: logs.length,
      logs
    }, null, 2);
  }

  /**
   * Clear all logs
   */
  clearLogs() {
    this.logs = [];
    this.saveToStorage();
  }

  /**
   * Save logs to localStorage
   */
  saveToStorage() {
    try {
      localStorage.setItem(this.storageKey, JSON.stringify(this.logs));
    } catch (e) {
      console.warn('[AuditLogger] Failed to save to storage:', e);
    }
  }

  /**
   * Load logs from localStorage
   */
  loadFromStorage() {
    try {
      const stored = localStorage.getItem(this.storageKey);
      if (stored) {
        this.logs = JSON.parse(stored);
      }
    } catch (e) {
      console.warn('[AuditLogger] Failed to load from storage:', e);
    }
  }
}

// Create and export singleton
const auditLogger = new AuditLogger();

export { AuditLogger };
export default auditLogger;
