/**
 * 성능 모니터링 유틸리티
 * - 컴포넌트 렌더링 시간 측정
 * - API 호출 시간 측정
 * - 메모리 사용량 모니터링
 */

import React from 'react';

interface PerformanceMetric {
  name: string;
  startTime: number;
  endTime?: number;
  duration?: number;
  type: 'render' | 'api' | 'compute' | 'other';
}

class PerformanceMonitor {
  private metrics: Map<string, PerformanceMetric> = new Map();
  private enabled: boolean = process.env.NODE_ENV === 'development';

  /**
   * 측정 시작
   */
  start(name: string, type: PerformanceMetric['type'] = 'other'): void {
    if (!this.enabled) return;

    this.metrics.set(name, {
      name,
      startTime: performance.now(),
      type,
    });

    console.log(`⏱️ [Performance] ${name} 시작`);
  }

  /**
   * 측정 종료
   */
  end(name: string): number | null {
    if (!this.enabled) return null;

    const metric = this.metrics.get(name);
    if (!metric) {
      console.warn(`⚠️ [Performance] "${name}" 측정이 시작되지 않았습니다`);
      return null;
    }

    const endTime = performance.now();
    const duration = endTime - metric.startTime;

    metric.endTime = endTime;
    metric.duration = duration;

    const emoji = duration < 100 ? '✅' : duration < 500 ? '⚠️' : '❌';
    console.log(`${emoji} [Performance] ${name} 완료: ${duration.toFixed(2)}ms`);

    return duration;
  }

  /**
   * 측정 및 실행 (함수 래퍼)
   */
  async measure<T>(
    name: string,
    fn: () => T | Promise<T>,
    type: PerformanceMetric['type'] = 'other'
  ): Promise<T> {
    this.start(name, type);
    try {
      const result = await fn();
      this.end(name);
      return result;
    } catch (error) {
      this.end(name);
      throw error;
    }
  }

  /**
   * React 컴포넌트 렌더링 측정 HOC
   */
  measureRender<P extends object>(
    Component: React.ComponentType<P>,
    componentName: string
  ): React.ComponentType<P> {
    if (!this.enabled) return Component;

    return (props: P) => {
      const renderStart = performance.now();

      React.useEffect(() => {
        const renderEnd = performance.now();
        const duration = renderEnd - renderStart;
        
        const emoji = duration < 16 ? '✅' : duration < 50 ? '⚠️' : '❌';
        console.log(`${emoji} [Render] ${componentName}: ${duration.toFixed(2)}ms`);
      });

      return React.createElement(Component, props);
    };
  }

  /**
   * 모든 메트릭 조회
   */
  getMetrics(): PerformanceMetric[] {
    return Array.from(this.metrics.values());
  }

  /**
   * 메트릭 요약
   */
  getSummary(): Record<string, any> {
    const metrics = this.getMetrics();
    const summary: Record<string, any> = {
      total: metrics.length,
      byType: {} as Record<string, number>,
      avgDuration: {} as Record<string, number>,
    };

    metrics.forEach((metric) => {
      if (!metric.duration) return;

      // 타입별 카운트
      summary.byType[metric.type] = (summary.byType[metric.type] || 0) + 1;

      // 타입별 평균 시간
      if (!summary.avgDuration[metric.type]) {
        summary.avgDuration[metric.type] = [];
      }
      summary.avgDuration[metric.type].push(metric.duration);
    });

    // 평균 계산
    Object.keys(summary.avgDuration).forEach((type) => {
      const durations = summary.avgDuration[type];
      summary.avgDuration[type] = durations.reduce((a: number, b: number) => a + b, 0) / durations.length;
    });

    return summary;
  }

  /**
   * 메모리 사용량 측정
   */
  getMemoryUsage(): Record<string, number> | null {
    if (!this.enabled) return null;

    // @ts-ignore - performance.memory는 Chrome에서만 사용 가능
    if (typeof performance.memory !== 'undefined') {
      // @ts-ignore
      const { usedJSHeapSize, totalJSHeapSize, jsHeapSizeLimit } = performance.memory;
      
      return {
        used: Math.round(usedJSHeapSize / 1024 / 1024), // MB
        total: Math.round(totalJSHeapSize / 1024 / 1024), // MB
        limit: Math.round(jsHeapSizeLimit / 1024 / 1024), // MB
        percentage: Math.round((usedJSHeapSize / jsHeapSizeLimit) * 100),
      };
    }

    return null;
  }

  /**
   * 메모리 사용량 로깅
   */
  logMemoryUsage(): void {
    const memory = this.getMemoryUsage();
    if (memory) {
      console.log(`💾 [Memory] ${memory.used}MB / ${memory.limit}MB (${memory.percentage}%)`);
    }
  }

  /**
   * 메트릭 초기화
   */
  clear(): void {
    this.metrics.clear();
    console.log('🧹 [Performance] 메트릭 초기화');
  }

  /**
   * 성능 모니터링 활성화/비활성화
   */
  setEnabled(enabled: boolean): void {
    this.enabled = enabled;
  }

  /**
   * React DevTools Profiler 연동
   */
  onRenderCallback(
    id: string,
    phase: 'mount' | 'update',
    actualDuration: number,
    baseDuration: number,
    startTime: number,
    commitTime: number
  ): void {
    if (!this.enabled) return;

    const emoji = actualDuration < 16 ? '✅' : actualDuration < 50 ? '⚠️' : '❌';
    console.log(
      `${emoji} [Profiler] ${id} (${phase}): ${actualDuration.toFixed(2)}ms (base: ${baseDuration.toFixed(2)}ms)`
    );
  }
}

// 싱글톤 인스턴스
export const performanceMonitor = new PerformanceMonitor();

// React 훅
export function usePerformanceMonitor(componentName: string) {
  React.useEffect(() => {
    performanceMonitor.start(`${componentName}_mount`, 'render');
    return () => {
      performanceMonitor.end(`${componentName}_mount`);
    };
  }, [componentName]);
}

// 전역으로 노출 (디버깅용)
if (typeof window !== 'undefined') {
  (window as any).__performanceMonitor = performanceMonitor;
}
