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

import { CLIENT_INTERNAL_SERVER_ERROR } from '@api/constants/client.constant';
import { CodefException } from '@lib/codef/src/codef.exception';
import {
  ADDITIONAL_AUTHENTICATION,
  ANALYSIS_NOT_AVAILABLE,
  APP_INSTALLATION_REQUIRED,
  INSTITUTIONAL_ERROR,
  INVALID_INFOMATION,
  TARGET_INSTITUTIONAL_ERROR,
} from '@api/constants/api.constant';
import { resolveTreatError, TreatVendor } from '@api/modules/treat/error';

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

  constructor(private readonly httpAdapterHost: HttpAdapterHost) {}

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

    const ctx = host.switchToHttp();

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

    let responseBody = {};

    if (exception instanceof HttpException) {
      responseBody = exception.getResponse();

      //* 해당 키가 없는 케이스가 있으므로 해당 키로 넘어온게 있는지 검증
      if ('type' in responseBody) {
        const type = (responseBody as any).type;
        const codefCode =
          'codefCode' in responseBody
            ? (responseBody as any).codefCode
            : undefined;
        const message =
          'codefMessage' in responseBody
            ? (responseBody as any).codefMessage
            : '';
        //* 처리 벤더(없으면 codef) — coocon/octover/hyphen native코드도 category·retryable 해석
        const vendor = ((responseBody as any).vendor ?? 'codef') as TreatVendor;
        const resolved = resolveTreatError(vendor, codefCode, {
          errMsg: message,
        });

        //* 기존 stage별 응답을 그대로 결정(회귀 방지) — 상수는 부착 시 복제됨
        let mapped: any;
        if (type === 'cert') {
          if (
            codefCode === 'CF-13000' ||
            codefCode === 'CF-12837' ||
            codefCode === 'CF-12835'
          ) {
            //* 잘못된 개인정보입니다.
            mapped = INVALID_INFOMATION;
          } else if (codefCode === 'CF-12871') {
            //* 앱을 설치하지 않았거나 인증서를 발급받지 않으셨습니다.
            mapped = APP_INSTALLATION_REQUIRED;
          } else if (codefCode === 'CF-12100') {
            mapped = INSTITUTIONAL_ERROR;
          } else if (codefCode === 'CF-12200') {
            mapped = TARGET_INSTITUTIONAL_ERROR;
          } else {
            mapped = { code: codefCode, message };
          }
        } else {
          if (codefCode === 'CF-03002') {
            mapped = ADDITIONAL_AUTHENTICATION;
          } else if (
            //* 인증 타임아웃 | 인증 3회 이상 | 이미 응답이 완료된 경우
            codefCode === 'CF-12835' ||
            codefCode === 'CF-12872' ||
            codefCode === 'CF-00025' ||
            codefCode === 'CF-01004' ||
            codefCode === 'CF-12001'
          ) {
            mapped = ANALYSIS_NOT_AVAILABLE;
          } else {
            mapped = { code: codefCode, message };
          }
        }

        //* 기존 응답 형태 유지 + 통합 분류·재시도성 부착
        //*   (프론트가 retryable로 '일시오류 재시도 vs 진짜실패' 분기 — 갭 A 해결)
        responseBody = {
          ...mapped,
          category: resolved.category,
          retryable: resolved.retryable,
        };
      }
    } else {
      this.logger.error(exception);
      responseBody = CLIENT_INTERNAL_SERVER_ERROR;
    }

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