// API 호출 로깅 유틸리티
// 개발 중 API 요청/응답을 추적하고 디버깅하기 위한 로거

/**
 * 로그 레벨
 */
export enum LogLevel {
  DEBUG = 'DEBUG',
  INFO = 'INFO',
  WARN = 'WARN',
  ERROR = 'ERROR',
}

/**
 * API 로그 항목 인터페이스
 */
interface ApiLogEntry {
  timestamp: string;
  level: LogLevel;
  method: string;
  url: string;
  requestData?: unknown;
  responseData?: unknown;
  statusCode?: number;
  error?: Error;
  duration?: number;
}

/**
 * API Logger 클래스
 */
class ApiLogger {
  private enabled: boolean;
  private logs: ApiLogEntry[] = [];
  private maxLogs: number = 100;

  constructor() {
    // 개발 환경에서만 로깅 활성화
    this.enabled =
      process.env.NODE_ENV === 'development' ||
      process.env.NEXT_PUBLIC_API_LOGGING === 'true';
  }

  /**
   * 로깅 활성화 여부 설정
   */
  setEnabled(enabled: boolean) {
    this.enabled = enabled;
  }

  /**
   * 로그 최대 개수 설정
   */
  setMaxLogs(max: number) {
    this.maxLogs = max;
  }

  /**
   * API 요청 시작 로그
   */
  logRequest(method: string, url: string, data?: unknown): number {
    if (!this.enabled) return Date.now();

    const startTime = Date.now();
    const entry: ApiLogEntry = {
      timestamp: new Date().toISOString(),
      level: LogLevel.INFO,
      method,
      url,
      requestData: data,
    };

    console.group(`🚀 API Request: ${method} ${url}`);
    console.log('⏰ Time:', entry.timestamp);
    if (data) {
      console.log('📤 Request Data:', data);
    }
    console.groupEnd();

    this.addLog(entry);
    return startTime;
  }

  /**
   * API 응답 성공 로그
   */
  logResponse(
    method: string,
    url: string,
    statusCode: number,
    data: unknown,
    startTime: number
  ) {
    if (!this.enabled) return;

    const duration = Date.now() - startTime;
    const entry: ApiLogEntry = {
      timestamp: new Date().toISOString(),
      level: LogLevel.INFO,
      method,
      url,
      responseData: data,
      statusCode,
      duration,
    };

    console.group(`✅ API Response: ${method} ${url}`);
    console.log('⏰ Time:', entry.timestamp);
    console.log('📊 Status:', statusCode);
    console.log('⏱️ Duration:', `${duration}ms`);
    console.log('📥 Response Data:', data);
    console.groupEnd();

    this.addLog(entry);
  }

  /**
   * API 에러 로그
   */
  logError(
    method: string,
    url: string,
    error: Error,
    statusCode?: number,
    startTime?: number
  ) {
    if (!this.enabled) return;

    const duration = startTime ? Date.now() - startTime : undefined;
    const entry: ApiLogEntry = {
      timestamp: new Date().toISOString(),
      level: LogLevel.ERROR,
      method,
      url,
      error,
      statusCode,
      duration,
    };

    console.group(`❌ API Error: ${method} ${url}`);
    console.log('⏰ Time:', entry.timestamp);
    if (statusCode) {
      console.log('📊 Status:', statusCode);
    }
    if (duration) {
      console.log('⏱️ Duration:', `${duration}ms`);
    }
    console.error('💥 Error:', error);
    console.groupEnd();

    this.addLog(entry);
  }

  /**
   * 경고 로그
   */
  logWarning(message: string, data?: unknown) {
    if (!this.enabled) return;

    const entry: ApiLogEntry = {
      timestamp: new Date().toISOString(),
      level: LogLevel.WARN,
      method: 'WARN',
      url: message,
      requestData: data,
    };

    console.warn(`⚠️ API Warning: ${message}`, data);
    this.addLog(entry);
  }

  /**
   * 디버그 로그
   */
  logDebug(message: string, data?: unknown) {
    if (!this.enabled) return;

    const entry: ApiLogEntry = {
      timestamp: new Date().toISOString(),
      level: LogLevel.DEBUG,
      method: 'DEBUG',
      url: message,
      requestData: data,
    };

    console.debug(`🔍 API Debug: ${message}`, data);
    this.addLog(entry);
  }

  /**
   * 로그 추가 및 최대 개수 관리
   */
  private addLog(entry: ApiLogEntry) {
    this.logs.push(entry);
    if (this.logs.length > this.maxLogs) {
      this.logs.shift(); // 가장 오래된 로그 제거
    }
  }

  /**
   * 모든 로그 조회
   */
  getLogs(): ApiLogEntry[] {
    return [...this.logs];
  }

  /**
   * 특정 레벨의 로그만 조회
   */
  getLogsByLevel(level: LogLevel): ApiLogEntry[] {
    return this.logs.filter((log) => log.level === level);
  }

  /**
   * 에러 로그만 조회
   */
  getErrors(): ApiLogEntry[] {
    return this.getLogsByLevel(LogLevel.ERROR);
  }

  /**
   * 모든 로그 삭제
   */
  clearLogs() {
    this.logs = [];
    console.log('🗑️ API logs cleared');
  }

  /**
   * 로그 통계 조회
   */
  getStats() {
    const stats = {
      total: this.logs.length,
      byLevel: {
        [LogLevel.DEBUG]: 0,
        [LogLevel.INFO]: 0,
        [LogLevel.WARN]: 0,
        [LogLevel.ERROR]: 0,
      },
      averageDuration: 0,
      errorRate: 0,
    };

    let totalDuration = 0;
    let countWithDuration = 0;

    this.logs.forEach((log) => {
      stats.byLevel[log.level]++;
      if (log.duration) {
        totalDuration += log.duration;
        countWithDuration++;
      }
    });

    if (countWithDuration > 0) {
      stats.averageDuration = totalDuration / countWithDuration;
    }

    if (stats.total > 0) {
      stats.errorRate =
        (stats.byLevel[LogLevel.ERROR] / stats.total) * 100;
    }

    return stats;
  }

  /**
   * 로그 통계 출력
   */
  printStats() {
    const stats = this.getStats();
    console.group('📊 API Logger Statistics');
    console.log('Total Logs:', stats.total);
    console.log('By Level:', stats.byLevel);
    console.log(
      'Average Duration:',
      `${stats.averageDuration.toFixed(2)}ms`
    );
    console.log('Error Rate:', `${stats.errorRate.toFixed(2)}%`);
    console.groupEnd();
  }

  /**
   * 로그를 JSON으로 내보내기
   */
  exportLogs(): string {
    return JSON.stringify(this.logs, null, 2);
  }

  /**
   * 로그를 콘솔에 테이블로 출력
   */
  printLogsAsTable() {
    if (this.logs.length === 0) {
      console.log('📭 No logs available');
      return;
    }

    const tableData = this.logs.map((log) => ({
      Timestamp: log.timestamp,
      Level: log.level,
      Method: log.method,
      URL: log.url,
      Status: log.statusCode || '-',
      Duration: log.duration ? `${log.duration}ms` : '-',
      Error: log.error?.message || '-',
    }));

    console.table(tableData);
  }
}

// 싱글톤 인스턴스 생성
export const apiLogger = new ApiLogger();

/**
 * API 호출 래퍼 함수
 * 자동으로 요청/응답을 로깅합니다
 */
export async function loggedFetch<T>(
  method: string,
  url: string,
  options?: RequestInit
): Promise<T> {
  const startTime = apiLogger.logRequest(method, url, options?.body);

  try {
    const response = await fetch(url, {
      ...options,
      method,
    });

    const data = await response.json();

    apiLogger.logResponse(method, url, response.status, data, startTime);

    if (!response.ok) {
      throw new Error(data.message || 'API request failed');
    }

    return data;
  } catch (error) {
    apiLogger.logError(method, url, error as Error, undefined, startTime);
    throw error;
  }
}

// 개발 도구를 window에 노출 (브라우저 콘솔에서 사용 가능)
if (typeof window !== 'undefined' && process.env.NODE_ENV === 'development') {
  (window as unknown as Record<string, unknown>).apiLogger = apiLogger;
  console.log(
    '💡 API Logger is available in console as "apiLogger"\n' +
      '   - apiLogger.getLogs() - View all logs\n' +
      '   - apiLogger.getErrors() - View errors only\n' +
      '   - apiLogger.printStats() - View statistics\n' +
      '   - apiLogger.printLogsAsTable() - View logs as table\n' +
      '   - apiLogger.clearLogs() - Clear all logs'
  );
}
