import { ErrorSeverity } from '@msfa-enums/error-severity.enum';
import { ErrorType } from '@msfa-enums/error-type.enum';

export class CustomError implements Error {
  id: string;
  name: string;
  message: string;
  stack: string;
  type: ErrorType;
  severity: ErrorSeverity;
  timestamp: Date;
  error: Error;
  removeAfter: number;

  constructor(args: { error: Error; type?: ErrorType; message?: string; severity?: ErrorSeverity; stack?: string }) {
    this.timestamp = new Date();
    this.id = this.timestamp.getTime().toString();
    this.type = this.name = args.type || ErrorType.UNKNOWN;
    this.message = args.message || args.error.message;
    this.severity = args.severity || ErrorSeverity.HIGH;
    this.stack = args.stack || CustomError.getStack(args.error);
    this.error = args.error;
    this.removeAfter =
      this.severity === ErrorSeverity.LOW ? 5000 : this.severity === ErrorSeverity.MEDIUM ? 10000 : 20000;
  }

  static getStack(error: Error | { error: Error }): string {
    if (!error) {
      return '';
    }
    if (typeof error === 'string') {
      return error;
    }

    if ('stack' in error) {
      return error.stack;
    } else if ('error' in error) {
      return this.getStack(error.error);
    } else {
      return error as never;
    }
  }

  static getErrorType(error: Error | (Error & { type: ErrorType })): ErrorType {
    if (typeof error === 'object' && 'type' in error) {
      return error.type;
    } else if (error.name === 'HttpErrorResponse') {
      return ErrorType.API;
    }

    return ErrorType.UNKNOWN;
  }
}

export function errorToCustomError(error: Error & { ngDebugContext: unknown }): CustomError {
  const type = CustomError.getErrorType(error);
  const message = error.message || error;
  const severity = ErrorSeverity.HIGH;

  // this is done to avoid circular references while running in debug mode
  if ('ngDebugContext' in error) {
    error.ngDebugContext = {};
  }

  return new CustomError({
    error,
    type,
    severity,
    message: message as string,
  });
}
