import {
  BadRequestException,
  ForbiddenException,
  HttpException,
  HttpStatus,
  NotFoundException,
  UnauthorizedException,
} from '@nestjs/common';
import type { ApiErrorCode, ApiErrorParams } from '@thebet365/shared';

function body(code: ApiErrorCode, params?: ApiErrorParams) {
  const clean = params
    ? Object.fromEntries(
        Object.entries(params)
          .filter(([, v]) => v !== undefined && v !== null)
          .map(([k, v]) => [k, String(v)]),
      )
    : undefined;
  return { code, params: clean };
}

export function appBadRequest(code: ApiErrorCode, params?: ApiErrorParams) {
  return new BadRequestException(body(code, params));
}

export function appNotFound(code: ApiErrorCode, params?: ApiErrorParams) {
  return new NotFoundException(body(code, params));
}

export function appForbidden(code: ApiErrorCode, params?: ApiErrorParams) {
  return new ForbiddenException(body(code, params));
}

export function appConflict(code: ApiErrorCode, data?: unknown, params?: ApiErrorParams) {
  return new HttpException({ ...body(code, params), data: data ?? null }, HttpStatus.CONFLICT);
}

export function appUnauthorized(code: ApiErrorCode, params?: ApiErrorParams) {
  return new UnauthorizedException(body(code, params));
}

export function appTooManyRequests(code: ApiErrorCode, params?: ApiErrorParams) {
  return new HttpException(body(code, params), HttpStatus.TOO_MANY_REQUESTS);
}

export function isCodedExceptionResponse(
  res: unknown,
): res is { code: ApiErrorCode; params?: ApiErrorParams } {
  return (
    typeof res === 'object' &&
    res !== null &&
    'code' in res &&
    typeof (res as { code: unknown }).code === 'string'
  );
}
