import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';

// Configuration Sentry
const SENTRY_DSN = process.env.REACT_APP_SENTRY_DSN || '';

export class MonitoringService {
  private static instance: MonitoringService;
  private isInitialized = false;

  private constructor() {}

  static getInstance(): MonitoringService {
    if (!MonitoringService.instance) {
      MonitoringService.instance = new MonitoringService();
    }
    return MonitoringService.instance;
  }

  // Initialiser Sentry
  initializeSentry(): void {
    if (this.isInitialized || !SENTRY_DSN) {
      return;
    }

    Sentry.init({
      dsn: SENTRY_DSN,
      integrations: [
        new BrowserTracing({
          tracePropagationTargets: ['localhost', 'veza-platform.com'],
        }),
      ],
      tracesSampleRate: 1.0,
      environment: process.env.NODE_ENV,
      release: process.env.REACT_APP_VERSION || '1.0.0',
      beforeSend(event) {
        // Filtrer les erreurs sensibles
        if (event.exception) {
          const exception = event.exception.values?.[0];
          if (exception?.value?.includes('password') || 
              exception?.value?.includes('token') ||
              exception?.value?.includes('key')) {
            return null;
          }
        }
        return event;
      },
    });

    this.isInitialized = true;
  }

  // Capturer une erreur
  captureException(error: Error, context?: Record<string, any>): void {
    if (!this.isInitialized) {
      console.error('Sentry not initialized');
      return;
    }

    Sentry.captureException(error, {
      extra: context,
    });
  }

  // Capturer un message
  captureMessage(message: string, level: Sentry.SeverityLevel = 'info'): void {
    if (!this.isInitialized) {
      console.log(message);
      return;
    }

    Sentry.captureMessage(message, {
      level,
    });
  }

  // Ajouter du contexte utilisateur
  setUser(user: {
    id: string;
    email: string;
    username?: string;
  }): void {
    if (!this.isInitialized) {
      return;
    }

    Sentry.setUser({
      id: user.id,
      email: user.email,
      username: user.username,
    });
  }

  // Ajouter des tags
  setTag(key: string, value: string): void {
    if (!this.isInitialized) {
      return;
    }

    Sentry.setTag(key, value);
  }

  // Ajouter du contexte
  setContext(name: string, context: Record<string, any>): void {
    if (!this.isInitialized) {
      return;
    }

    Sentry.setContext(name, context);
  }

  // Créer une transaction de performance
  startTransaction(name: string, operation: string): Sentry.Transaction {
    if (!this.isInitialized) {
      return null as any;
    }

    return Sentry.startTransaction({
      name,
      op: operation,
    });
  }

  // Ajouter une span à une transaction
  addSpan(transaction: Sentry.Transaction, name: string, operation: string): Sentry.Span {
    if (!this.isInitialized || !transaction) {
      return null as any;
    }

    return transaction.startChild({
      op: operation,
      description: name,
    });
  }

  // Mesurer les performances d'une fonction
  async measurePerformance<T>(
    name: string,
    operation: string,
    fn: () => Promise<T>
  ): Promise<T> {
    const transaction = this.startTransaction(name, operation);
    
    try {
      const result = await fn();
      transaction.setStatus('ok');
      return result;
    } catch (error) {
      transaction.setStatus('error');
      this.captureException(error as Error);
      throw error;
    } finally {
      transaction.finish();
    }
  }

  // Mesurer les performances d'une fonction synchrone
  measurePerformanceSync<T>(
    name: string,
    operation: string,
    fn: () => T
  ): T {
    const transaction = this.startTransaction(name, operation);
    
    try {
      const result = fn();
      transaction.setStatus('ok');
      return result;
    } catch (error) {
      transaction.setStatus('error');
      this.captureException(error as Error);
      throw error;
    } finally {
      transaction.finish();
    }
  }

  // Capturer les métriques de performance
  capturePerformanceMetrics(metrics: {
    name: string;
    value: number;
    unit: string;
    tags?: Record<string, string>;
  }): void {
    if (!this.isInitialized) {
      return;
    }

    Sentry.metrics.gauge(metrics.name, metrics.value, {
      unit: metrics.unit,
      tags: metrics.tags,
    });
  }

  // Capturer les métriques de navigation
  captureNavigationMetrics(route: string, duration: number): void {
    this.capturePerformanceMetrics({
      name: 'navigation.duration',
      value: duration,
      unit: 'millisecond',
      tags: { route },
    });
  }

  // Capturer les métriques d'API
  captureAPIMetrics(endpoint: string, duration: number, status: number): void {
    this.capturePerformanceMetrics({
      name: 'api.request.duration',
      value: duration,
      unit: 'millisecond',
      tags: { endpoint, status: status.toString() },
    });
  }

  // Capturer les métriques de rendu
  captureRenderMetrics(component: string, duration: number): void {
    this.capturePerformanceMetrics({
      name: 'render.duration',
      value: duration,
      unit: 'millisecond',
      tags: { component },
    });
  }

  // Capturer les métriques d'interaction
  captureInteractionMetrics(action: string, duration: number): void {
    this.capturePerformanceMetrics({
      name: 'interaction.duration',
      value: duration,
      unit: 'millisecond',
      tags: { action },
    });
  }

  // Capturer les erreurs de réseau
  captureNetworkError(url: string, status: number, message: string): void {
    this.captureException(new Error(`Network error: ${status} - ${message}`), {
      url,
      status,
      type: 'network',
    });
  }

  // Capturer les erreurs de validation
  captureValidationError(field: string, value: any, rule: string): void {
    this.captureException(new Error(`Validation error: ${field} - ${rule}`), {
      field,
      value: String(value),
      rule,
      type: 'validation',
    });
  }

  // Capturer les erreurs d'authentification
  captureAuthError(action: string, reason: string): void {
    this.captureException(new Error(`Authentication error: ${action} - ${reason}`), {
      action,
      reason,
      type: 'authentication',
    });
  }

  // Capturer les erreurs de fonctionnalité
  captureFeatureError(feature: string, action: string, error: Error): void {
    this.captureException(error, {
      feature,
      action,
      type: 'feature',
    });
  }

  // Nettoyer le contexte
  clearContext(): void {
    if (!this.isInitialized) {
      return;
    }

    Sentry.setUser(null);
    Sentry.setContext('app', {});
  }

  // Fermer Sentry
  close(): void {
    if (!this.isInitialized) {
      return;
    }

    Sentry.close();
    this.isInitialized = false;
  }
}

// Instance singleton
export const monitoringService = MonitoringService.getInstance();

// Hook React pour le monitoring
export const useMonitoring = () => {
  return {
    captureException: monitoringService.captureException.bind(monitoringService),
    captureMessage: monitoringService.captureMessage.bind(monitoringService),
    setUser: monitoringService.setUser.bind(monitoringService),
    setTag: monitoringService.setTag.bind(monitoringService),
    setContext: monitoringService.setContext.bind(monitoringService),
    measurePerformance: monitoringService.measurePerformance.bind(monitoringService),
    measurePerformanceSync: monitoringService.measurePerformanceSync.bind(monitoringService),
  };
}; 