import { HttpCode, Type, applyDecorators } from '@nestjs/common';
import { ApiResponse } from '@nestjs/swagger';
import {
  STATUS_CODE as RequestHeaderFieldsTooLarge_STATUS_CODE,
  STATUS_MESSAGE as RequestHeaderFieldsTooLarge_STATUS_MESSAGE,
} from '../../../shared/exceptions/http/request-header-fields-too-large.exception';

const defaultDescriptions = {
  200: 'OK',
  201: 'Created',
  400: 'Bad Request',
  401: 'Unauthorized',
  403: 'Forbidden',
  404: 'Not Found',
  409: 'Conflict',
  429: 'Too Many Requests',
  500: 'Internal Server Error',
  502: 'Bad Gateway',
  [RequestHeaderFieldsTooLarge_STATUS_CODE]:
    RequestHeaderFieldsTooLarge_STATUS_MESSAGE,
};

export type StatusCode = keyof typeof defaultDescriptions;

export interface StatusCodeWithSchema {
  code: StatusCode;
  responseType: Type<unknown>;
}

export function ApiDefaultResponseStatus(
  status: StatusCode,
  responseType?: Type<unknown>,
) {
  const httpCode = HttpCode(status);

  const apiResponse = ApiResponse({
    status,
    description: defaultDescriptions[status],
    type: responseType,
  });

  return applyDecorators(httpCode, apiResponse);
}

export function ApiResponseStatuses(
  ...statuses: Array<StatusCode | StatusCodeWithSchema>
) {
  if (statuses.length === 0) return;

  const decorators = statuses.flatMap((status) => {
    if (typeof status === 'number') {
      const apiResponse = ApiResponse({
        status,
        description: defaultDescriptions[status],
      });

      return [apiResponse];
    }

    const apiResponse = ApiResponse({
      status: status.code,
      description: defaultDescriptions[status.code],
      type: status.responseType,
    });

    return [apiResponse];
  });

  return applyDecorators(...decorators);
}
