import { GenericError, IGenericError } from "@shared/contexts";
import { BaseError } from "sequelize";

export interface IServerError extends IGenericError {}

export class ServerError extends GenericError implements IServerError {}

export class InternalServerError extends ServerError {
  public static create(code: string, message: string) {
    return new InternalServerError(code, message);
  }
}

export class RepositoryError extends ServerError {
  public static isRepositoryError = (error: unknown) => {
    return error instanceof BaseError;
  };

  public static create(error: unknown): ServerError {
    const _error = error as BaseError;

    return new GenericError("", _error.message, {
      name: _error.name,
    });
  }
}

export class NotFoundError extends ServerError {
  public static create(id: string, resource: string): NotFoundError {
    return new NotFoundError(`${resource} not found`, id, resource);
  }

  public readonly id: string;
  public readonly resource: string;

  constructor(message: string, id: string, resource: string) {
    super(message, `${resource} with id '${id}' not found`);
    this.id = id;
    this.resource = resource;
  }
}

export class RequiredFieldMissingError extends ServerError {
  public static field(
    fieldName: string,
    message?: string
  ): RequiredFieldMissingError {
    return new RequiredFieldMissingError(
      "",
      `Required field '${fieldName}' is missing`,
      message
    );
  }
}

export class FieldValueError extends ServerError {
  public static field(
    fieldName: string,
    value: any,
    message?: string
  ): FieldValueError {
    return new RequiredFieldMissingError(
      "",
      `Incorrect value '${String(value)}' for field '${fieldName}'`,
      message
    );
  }
}
