/**
 * Moniteur de performance React avec métriques temps réel
 */

import React, { memo, useEffect, useState, useCallback } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Activity, Clock, Cpu, Zap, AlertTriangle, CheckCircle } from 'lucide-react';

interface PerformanceMetrics {
  renderTime: number;
  memoryUsage: number;
  componentCount: number;
  reRenderCount: number;
  apiCalls: number;
  averageResponseTime: number;
  cacheHitRate: number;
  errors: number;
}

interface PerformanceAlert {
  id: string;
  type: 'warning' | 'error' | 'info';
  message: string;
  timestamp: Date;
  metric?: keyof PerformanceMetrics;
}

// Gestionnaire global des métriques de performance
class PerformanceManager {
  private metrics: PerformanceMetrics = {
    renderTime: 0,
    memoryUsage: 0,
    componentCount: 0,
    reRenderCount: 0,
    apiCalls: 0,
    averageResponseTime: 0,
    cacheHitRate: 0,
    errors: 0
  };
  
  private listeners: ((metrics: PerformanceMetrics) => void)[] = [];
  private alerts: PerformanceAlert[] = [];
  private alertListeners: ((alerts: PerformanceAlert[]) => void)[] = [];

  // Singletons pattern
  private static instance: PerformanceManager;
  
  static getInstance(): PerformanceManager {
    if (!PerformanceManager.instance) {
      PerformanceManager.instance = new PerformanceManager();
    }
    return PerformanceManager.instance;
  }

  subscribe(callback: (metrics: PerformanceMetrics) => void) {
    this.listeners.push(callback);
    return () => {
      this.listeners = this.listeners.filter(l => l !== callback);
    };
  }

  subscribeToAlerts(callback: (alerts: PerformanceAlert[]) => void) {
    this.alertListeners.push(callback);
    return () => {
      this.alertListeners = this.alertListeners.filter(l => l !== callback);
    };
  }

  updateMetric(key: keyof PerformanceMetrics, value: number) {
    this.metrics[key] = value;
    this.checkThresholds(key, value);
    this.notifyListeners();
  }

  incrementMetric(key: keyof PerformanceMetrics, increment: number = 1) {
    this.metrics[key] += increment;
    this.checkThresholds(key, this.metrics[key]);
    this.notifyListeners();
  }

  recordApiCall(responseTime: number) {
    this.metrics.apiCalls++;
    
    // Calcul de la moyenne mobile
    const newAverage = (this.metrics.averageResponseTime + responseTime) / 2;
    this.metrics.averageResponseTime = newAverage;
    
    this.notifyListeners();
  }

  recordCacheHit(isHit: boolean) {
    // Calcul simple du taux de cache hit
    const totalRequests = this.metrics.apiCalls + 1;
    const currentHits = this.metrics.cacheHitRate * this.metrics.apiCalls;
    this.metrics.cacheHitRate = (currentHits + (isHit ? 1 : 0)) / totalRequests;
    
    this.notifyListeners();
  }

  private checkThresholds(key: keyof PerformanceMetrics, value: number) {
    const thresholds = {
      renderTime: { warning: 500, error: 1000 },
      memoryUsage: { warning: 50, error: 80 },
      averageResponseTime: { warning: 1000, error: 3000 },
      cacheHitRate: { warning: 0.7, error: 0.5 },
      reRenderCount: { warning: 10, error: 20 }
    };

    const threshold = thresholds[key as keyof typeof thresholds];
    if (!threshold) return;

    let alertType: 'warning' | 'error' | 'info' = 'info';
    let message = '';

    if (value >= threshold.error) {
      alertType = 'error';
      message = `${key} critique: ${value}${key === 'cacheHitRate' ? '%' : ''}`;
    } else if (value >= threshold.warning) {
      alertType = 'warning';
      message = `${key} élevé: ${value}${key === 'cacheHitRate' ? '%' : ''}`;
    }

    if (message) {
      this.addAlert({
        id: `${key}-${Date.now()}`,
        type: alertType,
        message,
        timestamp: new Date(),
        metric: key
      });
    }
  }

  private addAlert(alert: PerformanceAlert) {
    this.alerts.unshift(alert);
    // Garder seulement les 10 dernières alertes
    this.alerts = this.alerts.slice(0, 10);
    this.alertListeners.forEach(listener => listener([...this.alerts]));
  }

  private notifyListeners() {
    this.listeners.forEach(listener => listener({ ...this.metrics }));
  }

  getMetrics(): PerformanceMetrics {
    return { ...this.metrics };
  }

  getAlerts(): PerformanceAlert[] {
    return [...this.alerts];
  }

  reset() {
    this.metrics = {
      renderTime: 0,
      memoryUsage: 0,
      componentCount: 0,
      reRenderCount: 0,
      apiCalls: 0,
      averageResponseTime: 0,
      cacheHitRate: 0,
      errors: 0
    };
    this.alerts = [];
    this.notifyListeners();
    this.alertListeners.forEach(listener => listener([]));
  }
}

// Hook pour utiliser les métriques de performance
export function usePerformanceMetrics() {
  const [metrics, setMetrics] = useState<PerformanceMetrics>(() => 
    PerformanceManager.getInstance().getMetrics()
  );
  
  useEffect(() => {
    const unsubscribe = PerformanceManager.getInstance().subscribe(setMetrics);
    return unsubscribe;
  }, []);

  return {
    metrics,
    recordApiCall: PerformanceManager.getInstance().recordApiCall.bind(PerformanceManager.getInstance()),
    recordCacheHit: PerformanceManager.getInstance().recordCacheHit.bind(PerformanceManager.getInstance()),
    updateMetric: PerformanceManager.getInstance().updateMetric.bind(PerformanceManager.getInstance()),
    incrementMetric: PerformanceManager.getInstance().incrementMetric.bind(PerformanceManager.getInstance()),
    reset: PerformanceManager.getInstance().reset.bind(PerformanceManager.getInstance())
  };
}

// Hook pour les alertes de performance
export function usePerformanceAlerts() {
  const [alerts, setAlerts] = useState<PerformanceAlert[]>(() =>
    PerformanceManager.getInstance().getAlerts()
  );

  useEffect(() => {
    const unsubscribe = PerformanceManager.getInstance().subscribeToAlerts(setAlerts);
    return unsubscribe;
  }, []);

  return alerts;
}

// Hook pour mesurer les re-renders d'un composant
export function useRenderTracker(componentName: string) {
  const { incrementMetric } = usePerformanceMetrics();
  
  useEffect(() => {
    incrementMetric('reRenderCount');
    console.log(`[RENDER] ${componentName} rendered`);
  });

  const trackRender = useCallback(() => {
    incrementMetric('reRenderCount');
  }, [incrementMetric]);

  return trackRender;
}

// Composant moniteur de performance
interface PerformanceMonitorProps {
  className?: string;
  showAlerts?: boolean;
  compact?: boolean;
}

export const PerformanceMonitor = memo(({ 
  className = "", 
  showAlerts = true, 
  compact = false 
}: PerformanceMonitorProps) => {
  const { metrics, reset } = usePerformanceMetrics();
  const alerts = usePerformanceAlerts();

  const getMetricStatus = (value: number, thresholds: { good: number; warning: number }) => {
    if (value <= thresholds.good) return 'good';
    if (value <= thresholds.warning) return 'warning';
    return 'error';
  };

  const getStatusColor = (status: 'good' | 'warning' | 'error') => {
    switch (status) {
      case 'good': return 'text-green-600';
      case 'warning': return 'text-yellow-600';
      case 'error': return 'text-red-600';
      default: return 'text-gray-600';
    }
  };

  const getStatusIcon = (status: 'good' | 'warning' | 'error') => {
    switch (status) {
      case 'good': return CheckCircle;
      case 'warning': return AlertTriangle;
      case 'error': return AlertTriangle;
      default: return Activity;
    }
  };

  if (compact) {
    return (
      <div className={`flex items-center space-x-4 p-2 bg-gray-50 rounded ${className}`}>
        <div className="flex items-center space-x-2">
          <Activity className="h-4 w-4 text-blue-600" />
          <span className="text-sm font-medium">Performance</span>
        </div>
        <div className="flex space-x-3 text-sm">
          <span>API: {metrics.apiCalls}</span>
          <span>Cache: {Math.round(metrics.cacheHitRate * 100)}%</span>
          <span>Temps: {Math.round(metrics.averageResponseTime)}ms</span>
        </div>
        {alerts.length > 0 && (
          <Badge variant="destructive" className="text-xs">
            {alerts.length} alertes
          </Badge>
        )}
      </div>
    );
  }

  return (
    <div className={className}>
      <Card>
        <CardHeader>
          <div className="flex items-center justify-between">
            <CardTitle className="flex items-center gap-2">
              <Activity className="h-5 w-5" />
              Moniteur Performance
            </CardTitle>
            <Button variant="outline" size="sm" onClick={reset}>
              Reset
            </Button>
          </div>
        </CardHeader>
        <CardContent>
          <div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
            {/* Temps de réponse API */}
            <div className="text-center">
              <div className="flex items-center justify-center mb-1">
                <Clock className={`h-4 w-4 mr-1 ${getStatusColor(
                  getMetricStatus(metrics.averageResponseTime, { good: 500, warning: 1000 })
                )}`} />
                <span className="text-xs text-gray-600">Réponse API</span>
              </div>
              <div className="text-lg font-semibold">
                {Math.round(metrics.averageResponseTime)}ms
              </div>
            </div>

            {/* Appels API */}
            <div className="text-center">
              <div className="flex items-center justify-center mb-1">
                <Zap className="h-4 w-4 mr-1 text-blue-600" />
                <span className="text-xs text-gray-600">Appels API</span>
              </div>
              <div className="text-lg font-semibold">
                {metrics.apiCalls}
              </div>
            </div>

            {/* Taux de cache */}
            <div className="text-center">
              <div className="flex items-center justify-center mb-1">
                <Cpu className={`h-4 w-4 mr-1 ${getStatusColor(
                  getMetricStatus(metrics.cacheHitRate, { good: 0.8, warning: 0.6 })
                )}`} />
                <span className="text-xs text-gray-600">Cache Hit</span>
              </div>
              <div className="text-lg font-semibold">
                {Math.round(metrics.cacheHitRate * 100)}%
              </div>
            </div>

            {/* Re-renders */}
            <div className="text-center">
              <div className="flex items-center justify-center mb-1">
                <Activity className={`h-4 w-4 mr-1 ${getStatusColor(
                  getMetricStatus(metrics.reRenderCount, { good: 5, warning: 15 })
                )}`} />
                <span className="text-xs text-gray-600">Re-renders</span>
              </div>
              <div className="text-lg font-semibold">
                {metrics.reRenderCount}
              </div>
            </div>
          </div>

          {/* Alertes */}
          {showAlerts && alerts.length > 0 && (
            <div className="border-t pt-4">
              <h4 className="font-medium mb-2 flex items-center gap-2">
                <AlertTriangle className="h-4 w-4 text-yellow-600" />
                Alertes Performance
              </h4>
              <div className="space-y-2 max-h-32 overflow-y-auto">
                {alerts.slice(0, 5).map((alert) => (
                  <div 
                    key={alert.id}
                    className={`text-xs p-2 rounded flex items-start gap-2 ${
                      alert.type === 'error' 
                        ? 'bg-red-50 text-red-700' 
                        : alert.type === 'warning'
                        ? 'bg-yellow-50 text-yellow-700'
                        : 'bg-blue-50 text-blue-700'
                    }`}
                  >
                    <span className="font-medium">
                      {alert.timestamp.toLocaleTimeString()}:
                    </span>
                    <span>{alert.message}</span>
                  </div>
                ))}
              </div>
            </div>
          )}
        </CardContent>
      </Card>
    </div>
  );
});

PerformanceMonitor.displayName = 'PerformanceMonitor';