import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
  HttpStatus,
  Logger,
} from '@nestjs/common';
import { Response } from 'express';

// 전역 Exception Filter — CLAUDE.md 에러 코드 맵에 따라 표준 응답으로 변환
@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
  private readonly logger = new Logger(HttpExceptionFilter.name);

  catch(exception: unknown, host: ArgumentsHost): void {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();

    let status: number = HttpStatus.INTERNAL_SERVER_ERROR;
    let code = 'SYS_001';
    let message = '일시적인 시스템 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.';

    if (exception instanceof HttpException) {
      status = exception.getStatus();
      const exceptionResponse = exception.getResponse();

      if (status === HttpStatus.UNAUTHORIZED) {
        code = 'AUTH_001';
        message = '로그인이 필요한 서비스입니다. 로그인 후 이용해 주세요.';
      } else if (status === HttpStatus.FORBIDDEN) {
        code = 'AUTH_003';
        message = '해당 메뉴나 기능에 접근할 수 있는 권한이 없습니다.';
      } else if (status === HttpStatus.NOT_FOUND) {
        code = 'RES_001';
        message = '요청하신 정보나 페이지를 찾을 수 없습니다.';
      } else if (
        status === HttpStatus.BAD_REQUEST ||
        status === HttpStatus.UNPROCESSABLE_ENTITY
      ) {
        code = 'VAL_001';
        message = '입력하신 정보를 다시 확인해 주세요. (필수값 누락 또는 형식 오류)';
      } else {
        code = 'BIZ_001';
        message = '요청하신 작업을 완료하지 못했습니다. 다시 시도해 주세요.';

        // 비즈니스 예외에서는 사용자에게 보일 메시지를 재정의 가능
        if (
          typeof exceptionResponse === 'object' &&
          exceptionResponse !== null &&
          'message' in exceptionResponse
        ) {
          const responseMessage = (exceptionResponse as { message: unknown }).message;
          if (typeof responseMessage === 'string') {
            message = responseMessage;
          }
        }
      }
    } else {
      // 정의되지 않은 예외 → 운영팀이 추적 가능하도록 로그 + SYS_001 응답 유지
      this.logger.error('Unhandled Exception', exception as Error);
    }

    response.status(status).json({
      success: false,
      error: {
        code,
        message,
      },
    });
  }
}
