export enum LogLevel {
  DEBUG = 'debug',
  INFO = 'info',
  WARN = 'warn',
  ERROR = 'error'
}

export interface LogEntry {
  timestamp: string;
  level: LogLevel;
  message: string;
  data?: any;
  userId?: string;
  sessionId?: string;
  userAgent?: string;
  url?: string;
}

export interface UserAction {
  action: string;
  component: string;
  data?: any;
  timestamp: string;
  sessionId: string;
}

class Logger {
  private logs: LogEntry[] = [];
  private userActions: UserAction[] = [];
  private maxLogs = 1000;
  private sessionId: string;

  constructor() {
    this.sessionId = this.generateSessionId();
    this.setupGlobalErrorHandler();
  }

  private generateSessionId(): string {
    return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  private setupGlobalErrorHandler() {
    window.addEventListener('error', (event) => {
      this.error('Global error', {
        message: event.message,
        filename: event.filename,
        lineno: event.lineno,
        colno: event.colno,
        error: event.error?.stack
      });
    });

    window.addEventListener('unhandledrejection', (event) => {
      this.error('Unhandled promise rejection', {
        reason: event.reason,
        promise: event.promise
      });
    });
  }

  private addLog(level: LogLevel, message: string, data?: any) {
    const logEntry: LogEntry = {
      timestamp: new Date().toISOString(),
      level,
      message,
      data,
      sessionId: this.sessionId,
      userAgent: navigator.userAgent,
      url: window.location.href
    };

    this.logs.push(logEntry);

    // 로그 개수 제한
    if (this.logs.length > this.maxLogs) {
      this.logs = this.logs.slice(-this.maxLogs);
    }

    // 콘솔에 출력
    console[level](`[${level.toUpperCase()}] ${message}`, data || '');

    // 에러 로그는 서버로 전송
    if (level === LogLevel.ERROR) {
      this.sendErrorToServer(logEntry);
    }
  }

  private async sendErrorToServer(logEntry: LogEntry) {
    try {
      await fetch('/api/logs/error', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(logEntry)
      });
    } catch (error) {
      console.error('Failed to send error log to server:', error);
    }
  }

  debug(message: string, data?: any) {
    this.addLog(LogLevel.DEBUG, message, data);
  }

  info(message: string, data?: any) {
    this.addLog(LogLevel.INFO, message, data);
  }

  warn(message: string, data?: any) {
    this.addLog(LogLevel.WARN, message, data);
  }

  error(message: string, data?: any) {
    this.addLog(LogLevel.ERROR, message, data);
  }

  // 사용자 행동 추적
  trackUserAction(action: string, component: string, data?: any) {
    const userAction: UserAction = {
      action,
      component,
      data,
      timestamp: new Date().toISOString(),
      sessionId: this.sessionId
    };

    this.userActions.push(userAction);

    // 사용자 행동 개수 제한
    if (this.userActions.length > this.maxLogs) {
      this.userActions = this.userActions.slice(-this.maxLogs);
    }

    this.debug(`User action: ${action}`, { component, data });
  }

  // 로그 내보내기
  exportLogs(): LogEntry[] {
    return [...this.logs];
  }

  // 사용자 행동 내보내기
  exportUserActions(): UserAction[] {
    return [...this.userActions];
  }

  // 로그 초기화
  clearLogs() {
    this.logs = [];
    this.userActions = [];
  }

  // 세션 ID 가져오기
  getSessionId(): string {
    return this.sessionId;
  }

  // 로그 통계
  getLogStats() {
    const stats = {
      total: this.logs.length,
      byLevel: {
        debug: 0,
        info: 0,
        warn: 0,
        error: 0
      },
      userActions: this.userActions.length
    };

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

    return stats;
  }
}

export const logger = new Logger(); 