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

import { INTERNAL_SERVER_ERROR } from '@api/constants/api.constant';
import { AlertSignalService } from '@api/modules/alert/alert-signal.service';

@Catch()
export class AllExceptionFilter implements ExceptionFilter {
  private logger = new Logger(AllExceptionFilter.name);

  //* signals 는 선택 — 미주입이면 카운터만 빠지고 응답 경로는 완전히 동일하다(M2 §D3).
  constructor(
    private readonly httpAdapterHost: HttpAdapterHost,
    private readonly signals?: AlertSignalService,
  ) {}

  catch(exception: unknown, host: ArgumentsHost) {
    const { httpAdapter } = this.httpAdapterHost;

    const ctx = host.switchToHttp();

    const httpStatus =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;

    //* A4 분자 — fire-and-forget. 기존 분기·반환·예외 흐름은 한 글자도 바뀌지 않는다(UI14 · UI17).
    if (httpStatus >= 500)
      void this.signals?.bump5xx().catch(() => {
        /* 신호 수집 실패가 응답에 영향을 주지 않는다 */
      });

    let responseBody = {};

    if (exception instanceof HttpException) {
      responseBody = exception.getResponse();
    } else {
      this.logger.error(exception);
      responseBody = INTERNAL_SERVER_ERROR;
    }

    httpAdapter.reply(ctx.getResponse(), responseBody, httpStatus);
  }
}
