// utils/errorHandler.js - 통합 에러 처리 유틸리티

/**
 * 표준화된 에러 응답 생성
 */
class ApiError extends Error {
  constructor(message, statusCode = 500, errorCode = null) {
    super(message);
    this.statusCode = statusCode;
    this.errorCode = errorCode;
    this.timestamp = new Date().toISOString();
  }
}

/**
 * 에러 응답 포맷터
 */
const formatErrorResponse = (error, req = null) => {
  const response = {
    success: false,
    error: error.message || '알 수 없는 오류가 발생했습니다.',
    timestamp: error.timestamp || new Date().toISOString()
  };

  // 개발 환경에서만 상세 정보 포함
  if (process.env.NODE_ENV === 'development') {
    response.stack = error.stack;
    response.errorCode = error.errorCode;
    if (req) {
      response.requestInfo = {
        method: req.method,
        url: req.originalUrl,
        userAgent: req.get('User-Agent'),
        ip: req.ip
      };
    }
  }

  return response;
};

/**
 * 데이터베이스 에러 처리
 */
const handleDatabaseError = (error, operation = 'database operation') => {
  console.error(`[DB Error] ${operation}:`, error);
  
  // 일반적인 DB 에러 코드 매핑
  const errorMappings = {
    'ER_DUP_ENTRY': { message: '중복된 데이터입니다.', statusCode: 409 },
    'ER_NO_REFERENCED_ROW_2': { message: '참조된 데이터가 존재하지 않습니다.', statusCode: 400 },
    'ER_ROW_IS_REFERENCED_2': { message: '다른 데이터에서 참조되고 있어 삭제할 수 없습니다.', statusCode: 409 },
    'ER_BAD_FIELD_ERROR': { message: '잘못된 필드명입니다.', statusCode: 400 },
    'ER_NO_SUCH_TABLE': { message: '테이블이 존재하지 않습니다.', statusCode: 500 },
    'ECONNREFUSED': { message: '데이터베이스 연결에 실패했습니다.', statusCode: 503 }
  };

  const mapping = errorMappings[error.code] || errorMappings[error.errno];
  if (mapping) {
    throw new ApiError(mapping.message, mapping.statusCode, error.code);
  }

  // 기본 에러
  throw new ApiError(`${operation} 중 오류가 발생했습니다.`, 500, error.code);
};

/**
 * 유효성 검사 에러 처리
 */
const handleValidationError = (field, value, rule) => {
  const message = `${field} 필드가 유효하지 않습니다. (값: ${value}, 규칙: ${rule})`;
  throw new ApiError(message, 400, 'VALIDATION_ERROR');
};

/**
 * 권한 에러 처리
 */
const handleAuthorizationError = (requiredLevel, userLevel) => {
  const message = `접근 권한이 부족합니다. (필요: ${requiredLevel}, 현재: ${userLevel})`;
  throw new ApiError(message, 403, 'AUTHORIZATION_ERROR');
};

/**
 * 리소스 없음 에러 처리
 */
const handleNotFoundError = (resource, identifier = null) => {
  const message = identifier 
    ? `${resource}(${identifier})을(를) 찾을 수 없습니다.`
    : `${resource}을(를) 찾을 수 없습니다.`;
  throw new ApiError(message, 404, 'NOT_FOUND');
};

/**
 * Express 에러 핸들러 미들웨어
 */
const errorMiddleware = (error, req, res, next) => {
  // ApiError가 아닌 경우 변환
  if (!(error instanceof ApiError)) {
    error = new ApiError(error.message || '서버 내부 오류', 500);
  }

  const response = formatErrorResponse(error, req);
  
  // 로깅
  if (error.statusCode >= 500) {
    console.error('[Server Error]', {
      message: error.message,
      stack: error.stack,
      url: req.originalUrl,
      method: req.method,
      user: req.user?.username || 'anonymous'
    });
  } else {
    console.warn('[Client Error]', {
      message: error.message,
      url: req.originalUrl,
      method: req.method,
      user: req.user?.username || 'anonymous'
    });
  }

  res.status(error.statusCode).json(response);
};

/**
 * 비동기 함수 래퍼 (에러 자동 처리)
 */
const asyncHandler = (fn) => {
  return (req, res, next) => {
    Promise.resolve(fn(req, res, next)).catch(next);
  };
};

module.exports = {
  ApiError,
  formatErrorResponse,
  handleDatabaseError,
  handleValidationError,
  handleAuthorizationError,
  handleNotFoundError,
  errorMiddleware,
  asyncHandler
};
