/**
 * 로깅 유틸리티
 *
 * 애플리케이션 전체에서 사용하는 통합 로거
 *
 * @author TK-FB-Project
 * @since 2025-12-11
 */

const fs = require('fs');
const path = require('path');

/**
 * 로그 레벨 정의
 */
const LogLevel = {
  ERROR: 'ERROR',
  WARN: 'WARN',
  INFO: 'INFO',
  DEBUG: 'DEBUG'
};

/**
 * 로그 레벨별 이모지
 */
const LogEmoji = {
  ERROR: '❌',
  WARN: '⚠️',
  INFO: 'ℹ️',
  DEBUG: '🔍'
};

/**
 * 로그 레벨별 색상 (콘솔)
 */
const LogColor = {
  ERROR: '\x1b[31m', // Red
  WARN: '\x1b[33m',  // Yellow
  INFO: '\x1b[36m',  // Cyan
  DEBUG: '\x1b[90m', // Gray
  RESET: '\x1b[0m'
};

class Logger {
  constructor() {
    // process.cwd() = /usr/src/app (컨테이너 WORKDIR)
    // __dirname 대신 사용하여 shared/ 위치와 무관하게 서비스의 logs/ 디렉토리에 기록
    this.logDir = path.join(process.cwd(), 'logs');
    this.logFile = path.join(this.logDir, 'app.log');
    this.errorFile = path.join(this.logDir, 'error.log');
    this.ensureLogDirectory();
  }

  /**
   * 로그 디렉토리 생성
   */
  ensureLogDirectory() {
    if (!fs.existsSync(this.logDir)) {
      fs.mkdirSync(this.logDir, { recursive: true });
    }
  }

  /**
   * 타임스탬프 생성
   */
  getTimestamp() {
    return new Date().toISOString();
  }

  /**
   * 로그 포맷팅
   */
  formatLog(level, message, context = {}) {
    const timestamp = this.getTimestamp();
    const emoji = LogEmoji[level] || '';
    const contextStr = Object.keys(context).length > 0
      ? `\n  Context: ${JSON.stringify(context, null, 2)}`
      : '';

    return `[${timestamp}] [${level}] ${emoji} ${message}${contextStr}`;
  }

  /**
   * 콘솔에 컬러 로그 출력
   */
  logToConsole(level, message, context = {}) {
    const color = LogColor[level] || LogColor.RESET;
    const formattedLog = this.formatLog(level, message, context);

    if (level === LogLevel.ERROR) {
      console.error(`${color}${formattedLog}${LogColor.RESET}`);
    } else if (level === LogLevel.WARN) {
      console.warn(`${color}${formattedLog}${LogColor.RESET}`);
    } else {
      console.log(`${color}${formattedLog}${LogColor.RESET}`);
    }
  }

  /**
   * 파일에 로그 기록
   */
  logToFile(level, message, context = {}) {
    const formattedLog = this.formatLog(level, message, context);
    const logEntry = `${formattedLog}\n`;

    try {
      // 모든 로그를 app.log에 기록
      fs.appendFileSync(this.logFile, logEntry, 'utf8');

      // 에러는 error.log에도 기록
      if (level === LogLevel.ERROR) {
        fs.appendFileSync(this.errorFile, logEntry, 'utf8');
      }
    } catch (err) {
      console.error('로그 파일 기록 실패:', err);
    }
  }

  /**
   * 로그 기록 메인 함수
   */
  log(level, message, context = {}) {
    // 개발 환경에서는 콘솔에 출력
    if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV !== 'production') {
      this.logToConsole(level, message, context);
    }

    // 프로덕션에서는 파일에만 기록
    if (process.env.NODE_ENV === 'production') {
      this.logToFile(level, message, context);
    }
  }

  /**
   * 에러 로그
   */
  error(message, context = {}) {
    this.log(LogLevel.ERROR, message, context);
  }

  /**
   * 경고 로그
   */
  warn(message, context = {}) {
    this.log(LogLevel.WARN, message, context);
  }

  /**
   * 정보 로그
   */
  info(message, context = {}) {
    this.log(LogLevel.INFO, message, context);
  }

  /**
   * 디버그 로그
   */
  debug(message, context = {}) {
    // DEBUG 로그는 개발 환경에서만 출력
    if (process.env.NODE_ENV === 'development') {
      this.log(LogLevel.DEBUG, message, context);
    }
  }

  /**
   * HTTP 요청 로그
   */
  http(method, url, statusCode, duration, user = 'anonymous') {
    const level = statusCode >= 400 ? LogLevel.ERROR : LogLevel.INFO;
    const message = `${method} ${url} - ${statusCode} (${duration}ms)`;
    const context = {
      method,
      url,
      statusCode,
      duration,
      user
    };

    this.log(level, message, context);
  }

  /**
   * 데이터베이스 쿼리 로그
   */
  query(sql, params = [], duration = 0) {
    if (process.env.NODE_ENV === 'development') {
      this.debug('DB Query', {
        sql,
        params,
        duration: `${duration}ms`
      });
    }
  }
}

// 싱글톤 인스턴스 생성 및 내보내기
const logger = new Logger();

module.exports = logger;
