/**
 * 에러 처리 모듈 (ErrorHandler.js)
 * ========================================
 * 에러를 한곳에서 처리하고 로깅합니다.
 *
 * [초보자용]
 *   ErrorHandler.safeExecute(() => 위험한함수(), 기본값)
 *   ErrorHandler.handle(error, { context: '내모듈' })
 *
 * @module ErrorHandler
 */
class ErrorHandler {
  constructor() {
    this.errorLog = [];
    this.maxLogSize = 100;
    this.onErrorCallbacks = [];
  }

  /**
   * 에러 처리
   * @param {Error|string} error - 에러 객체 또는 메시지
   * @param {Object} context - 컨텍스트 정보
   * @param {boolean} showToUser - 사용자에게 표시할지 여부
   */
  static handle(error, context = {}, showToUser = false) {
    const errorInfo = this._normalizeError(error, context);
    
    // 콘솔에 로그
    console.error('[ErrorHandler]', errorInfo);

    // 에러 로그에 추가
    if (this.instance) {
      this.instance._addToLog(errorInfo);
    }

    // 콜백 실행
    if (this.instance) {
      this.instance.onErrorCallbacks.forEach(callback => {
        try {
          callback(errorInfo);
        } catch (e) {
          console.error('[ErrorHandler] Error in callback:', e);
        }
      });
    }

    // 사용자에게 표시
    if (showToUser) {
      this._showToUser(errorInfo);
    }

    return errorInfo;
  }

  /**
   * 에러를 정규화
   * @private
   */
  static _normalizeError(error, context) {
    const errorInfo = {
      message: '',
      stack: '',
      timestamp: new Date().toISOString(),
      context: {},
      ...context,
    };

    if (error instanceof Error) {
      errorInfo.message = error.message;
      errorInfo.stack = error.stack;
      errorInfo.name = error.name;
    } else if (typeof error === 'string') {
      errorInfo.message = error;
    } else {
      errorInfo.message = 'Unknown error';
      errorInfo.originalError = error;
    }

    return errorInfo;
  }

  /**
   * 사용자에게 에러 표시
   * @private
   */
  static _showToUser(errorInfo) {
    // ModalBase가 있으면 사용, 없으면 alert
    if (typeof AlertModal !== 'undefined') {
      const alert = new AlertModal({
        title: '오류 발생',
        message: errorInfo.message || '알 수 없는 오류가 발생했습니다.',
      });
      alert.show();
    } else if (typeof ModalBase !== 'undefined') {
      // 간단한 알림 모달 생성
      const modal = new ModalBase();
      modal.create({
        content: `<div style="padding: 20px;">${errorInfo.message || '오류가 발생했습니다.'}</div>`,
      });
      modal.open();
    } else {
      // 최후의 수단: alert
      alert(errorInfo.message || '오류가 발생했습니다.');
    }
  }

  /**
   * 에러 로그에 추가
   * @private
   */
  _addToLog(errorInfo) {
    this.errorLog.push(errorInfo);
    
    // 최대 크기 초과 시 오래된 항목 제거
    if (this.errorLog.length > this.maxLogSize) {
      this.errorLog.shift();
    }
  }

  /**
   * 에러 콜백 등록
   * @param {Function} callback - 콜백 함수
   */
  onError(callback) {
    if (typeof callback === 'function') {
      this.onErrorCallbacks.push(callback);
    }
  }

  /**
   * 에러 콜백 제거
   * @param {Function} callback - 콜백 함수
   */
  offError(callback) {
    const index = this.onErrorCallbacks.indexOf(callback);
    if (index > -1) {
      this.onErrorCallbacks.splice(index, 1);
    }
  }

  /**
   * 에러 로그 가져오기
   * @param {number} limit - 최대 개수
   * @returns {Array}
   */
  getErrorLog(limit = null) {
    if (limit) {
      return this.errorLog.slice(-limit);
    }
    return [...this.errorLog];
  }

  /**
   * 에러 로그 초기화
   */
  clearErrorLog() {
    this.errorLog = [];
  }

  /**
   * 안전한 함수 실행 (에러 처리 포함)
   * @param {Function} fn - 실행할 함수
   * @param {*} defaultValue - 에러 발생 시 반환할 기본값
   * @param {Object} context - 컨텍스트 정보
   * @returns {*}
   */
  static safeExecute(fn, defaultValue = null, context = {}) {
    try {
      return fn();
    } catch (error) {
      this.handle(error, context, false);
      return defaultValue;
    }
  }

  /**
   * 안전한 비동기 함수 실행 (에러 처리 포함)
   * @param {Function} fn - 실행할 함수
   * @param {*} defaultValue - 에러 발생 시 반환할 기본값
   * @param {Object} context - 컨텍스트 정보
   * @returns {Promise}
   */
  static async safeExecuteAsync(fn, defaultValue = null, context = {}) {
    try {
      return await fn();
    } catch (error) {
      this.handle(error, context, false);
      return defaultValue;
    }
  }

  /**
   * 전역 에러 핸들러 설정
   */
  static setupGlobalHandlers() {
    // 전역 에러 핸들러
    window.addEventListener('error', (event) => {
      this.handle(event.error || event.message, {
        type: 'global',
        filename: event.filename,
        lineno: event.lineno,
        colno: event.colno,
      }, false);
    });

    // Promise rejection 핸들러
    window.addEventListener('unhandledrejection', (event) => {
      this.handle(event.reason, {
        type: 'unhandledRejection',
      }, false);
    });
  }
}

// 싱글톤 인스턴스
ErrorHandler.instance = new ErrorHandler();

// ES6 모듈 내보내기
if (typeof module !== "undefined" && module.exports) {
  module.exports = ErrorHandler;
}
