import {
  DomainError,
  IValueObjectOptions,
  Result,
  RuleValidator,
  ValueObject,
  handleDomainError,
} from "@shared/contexts";
import Joi from "joi";

export enum DEALER_STATUS {
  ACTIVED = "actived",
  BLOQUED = "bloqued",
  DISABLED = "disabled",
}
export interface IDealerStatusOptions extends IValueObjectOptions {}

export class DealerStatus extends ValueObject<string> {
  public static readonly DEALER_STATUS = DEALER_STATUS;

  protected static validate(value: string, options: IValueObjectOptions) {
    const rule = Joi.string()
      .valid(DEALER_STATUS.ACTIVED, DEALER_STATUS.BLOQUED, DEALER_STATUS.DISABLED)
      .label(options.label ? options.label : "status");

    return RuleValidator.validate<string>(rule, value);
  }

  private static sanitize(status: string): string {
    return String(status).trim().toLowerCase();
  }

  public static createActived(): DealerStatus {
    return new DealerStatus(DEALER_STATUS.ACTIVED);
  }

  public static createBloqued(): DealerStatus {
    return new DealerStatus(DEALER_STATUS.BLOQUED);
  }

  public static createDisabled(): DealerStatus {
    return new DealerStatus(DEALER_STATUS.DISABLED);
  }

  public static create(status: string, options: IDealerStatusOptions = {}) {
    const _options = {
      label: "status",
      ...options,
    };
    const validationResult = DealerStatus.validate(status, _options);

    if (validationResult.isFailure) {
      return Result.fail(
        handleDomainError(DomainError.INVALID_INPUT_DATA, validationResult.error.message, _options)
      );
    }

    return Result.ok(new DealerStatus(DealerStatus.sanitize(validationResult.object)));
  }

  get value(): string {
    return String(this.props);
  }

  public toString(): string {
    return String(this.props);
  }

  public toPrimitive(): string {
    return this.toString();
  }

  public isActived(): boolean {
    return this.equals(DealerStatus.createActived());
  }

  public isBloqued(): boolean {
    return this.equals(DealerStatus.createBloqued());
  }

  public isDisabled(): boolean {
    return this.equals(DealerStatus.createDisabled());
  }

  public isEmpty(): boolean {
    return this.props === "undefined";
  }
}
