import { ProductBase } from '../product/product.base';
import { ProductWithInventoryRepository } from './product-with-inventory.repository';
import { ProductWithInventoryModel } from '../../entities/product-with-inventory.entity';
import { IProductWithInventoryAttrBase } from '../../interfaces';
import { LoginUser } from '@tomei/sso';
import { Activity, ActionEnum } from '@tomei/activity-history';
import cuid from '../../helpers/cuid';
export abstract class ProductWithInventoryBase extends ProductBase {
  ObjectType = 'ProductWithInventory';
  private _UOM: string;
  private _TotalUnits = 0;
  private _TotalUnitsAvailable = 0;
  private _TotalUnitsInCurrentOrder = 0;
  private _TotalUnitsSold = 0;
  private _TotalUnitsReserved = 0;
  private _TotalUnitsOnConsignment = 0;
  private _TotalUnitsUnderMaintenance = 0;
  private _TotalUnitsVoid = 0;
  private _TotalUnitsInTransit = 0;
  private _TotalUnitsBackOrdered = 0;
  private _TotalUnitsPreOrdered = 0;
  private _StockLowAlertLevel = 0;
  private _StockReorderLevel = 0;
  private _BufferStockLevel = 0;
  protected static _ProductWithInventoryRepository =
    new ProductWithInventoryRepository();

  constructor(product?: IProductWithInventoryAttrBase) {
    // NOTE: got error if super() is not called first, not sure why happen only in this class
    super(product);
    if (product) {
      this._UOM = product.UOM;
      this._TotalUnits = product.TotalUnits;
      this._TotalUnitsAvailable = product.TotalUnitsAvailable;
      this._TotalUnitsInCurrentOrder = product.TotalUnitsInCurrentOrder;
      this._TotalUnitsSold = product.TotalUnitsSold;
      this._TotalUnitsReserved = product.TotalUnitsReserved;
      this._TotalUnitsOnConsignment = product.TotalUnitsOnConsignment;
      this._TotalUnitsUnderMaintenance = product.TotalUnitsUnderMaintenance;
      this._TotalUnitsVoid = product.TotalUnitsVoid;
      this._TotalUnitsInTransit = product.TotalUnitsInTransit;
      this._TotalUnitsBackOrdered = product.TotalUnitsBackOrdered;
      this._TotalUnitsPreOrdered = product.TotalUnitsPreOrdered;
      this._StockLowAlertLevel = product.StockLowAlertLevel;
      this._StockReorderLevel = product.StockReorderLevel;
      this._BufferStockLevel = product.BufferStockLevel;
    }
  }

  get ProductId(): string {
    return super.ProductId;
  }

  set ProductId(value: string) {
    super.ProductId = value;
  }

  get Name(): string {
    return super.Name;
  }

  set Name(value: string) {
    super.Name = value;
  }

  get Description(): string {
    return super.Description;
  }

  set Description(value: string) {
    super.Description = value;
  }

  get SKU(): string {
    return super.SKU;
  }

  set SKU(value: string) {
    super.SKU = value;
  }

  get Type(): string {
    return super.Type;
  }

  set Type(value: string) {
    super.Type = value;
  }

  get Remark(): string {
    return super.Remark;
  }

  set Remark(value: string) {
    super.Remark = value;
  }

  get IsTaxableYN(): string {
    return super.IsTaxableYN;
  }

  set IsTaxableYN(value: string) {
    super.IsTaxableYN = value;
  }

  get TaxCode(): string {
    return super.TaxCode;
  }

  set TaxCode(value: string) {
    super.TaxCode = value;
  }

  get IsPriceInclusiveTaxYN(): string {
    return super.IsPriceInclusiveTaxYN;
  }

  set IsPriceInclusiveTaxYN(value: string) {
    super.IsPriceInclusiveTaxYN = value;
  }

  get Status(): string {
    return super.Status;
  }

  protected set Status(value: any) {
    super.Status = value;
  }

  get VerifiedYN(): string {
    return super.VerifiedYN;
  }

  protected set VerifiedYN(value: any) {
    super.VerifiedYN = value;
  }

  get VerifiedAt(): Date {
    return super.VerifiedAt;
  }

  protected set VerifiedAt(value: any) {
    super.VerifiedAt = value;
  }

  get VerifiedById(): string {
    return super.VerifiedById;
  }

  protected set VerifiedById(value: any) {
    super.VerifiedById = value;
  }

  get VariantLevels(): number {
    return super.VariantLevels;
  }

  set VariantLevels(value: number) {
    super.VariantLevels = value;
  }

  get VariantTypeLevel1(): string {
    return super.VariantTypeLevel1;
  }

  set VariantTypeLevel1(value: string) {
    super.VariantTypeLevel1 = value;
  }

  get VariantTypeLevel2(): string {
    return super.VariantTypeLevel2;
  }

  set VariantTypeLevel2(value: string) {
    super.VariantTypeLevel2 = value;
  }

  get VariantTypeLevel3(): string {
    return super.VariantTypeLevel3;
  }

  set VariantTypeLevel3(value: string) {
    super.VariantTypeLevel3 = value;
  }

  get CreatedAt(): Date {
    return super.CreatedAt;
  }

  protected set CreatedAt(value: any) {
    super.CreatedAt = value;
  }

  get CreatedById(): string {
    return super.CreatedById;
  }

  protected set CreatedById(value: any) {
    super.CreatedById = value;
  }

  get UpdatedAt(): Date {
    return super.UpdatedAt;
  }

  protected set UpdatedAt(value: any) {
    super.UpdatedAt = value;
  }

  get UpdatedById(): string {
    return super.UpdatedById;
  }

  protected set UpdatedById(value: any) {
    super.UpdatedById = value;
  }

  get UpdatedSSYN(): string {
    return super.UpdatedSSYN;
  }

  protected set UpdatedSSYN(value: any) {
    super.UpdatedSSYN = value;
  }

  get UOM(): string {
    return this._UOM;
  }

  set UOM(value: string) {
    this._UOM = value;
  }

  get TotalUnits(): number {
    return this._TotalUnits;
  }

  set TotalUnits(value: number) {
    this._TotalUnits = value;
  }

  get TotalUnitsAvailable(): number {
    return this._TotalUnitsAvailable;
  }

  protected set TotalUnitsAvailable(value: number) {
    this._TotalUnitsAvailable = value;
  }

  get TotalUnitsInCurrentOrder(): number {
    return this._TotalUnitsInCurrentOrder;
  }

  protected set TotalUnitsInCurrentOrder(value: number) {
    this._TotalUnitsInCurrentOrder = value;
  }

  get TotalUnitsSold(): number {
    return this._TotalUnitsSold;
  }

  protected set TotalUnitsSold(value: number) {
    this._TotalUnitsSold = value;
  }

  get TotalUnitsReserved(): number {
    return this._TotalUnitsReserved;
  }

  protected set TotalUnitsReserved(value: number) {
    this._TotalUnitsReserved = value;
  }

  get TotalUnitsOnConsignment(): number {
    return this._TotalUnitsOnConsignment;
  }

  protected set TotalUnitsOnConsignment(value: number) {
    this._TotalUnitsOnConsignment = value;
  }

  get TotalUnitsUnderMaintenance(): number {
    return this._TotalUnitsUnderMaintenance;
  }

  protected set TotalUnitsUnderMaintenance(value: number) {
    this._TotalUnitsUnderMaintenance = value;
  }

  get TotalUnitsVoid(): number {
    return this._TotalUnitsVoid;
  }

  protected set TotalUnitsVoid(value: number) {
    this._TotalUnitsVoid = value;
  }

  get TotalUnitsInTransit(): number {
    return this._TotalUnitsInTransit;
  }

  protected set TotalUnitsInTransit(value: number) {
    this._TotalUnitsInTransit = value;
  }

  get TotalUnitsBackOrdered(): number {
    return this._TotalUnitsBackOrdered;
  }

  protected set TotalUnitsBackOrdered(value: number) {
    this._TotalUnitsBackOrdered = value;
  }

  get TotalUnitsPreOrdered(): number {
    return this._TotalUnitsPreOrdered;
  }

  protected set TotalUnitsPreOrdered(value: number) {
    this._TotalUnitsPreOrdered = value;
  }

  get StockLowAlertLevel(): number {
    return this._StockLowAlertLevel;
  }

  set StockLowAlertLevel(value: number) {
    this._StockLowAlertLevel = value;
  }

  get StockReorderLevel(): number {
    return this._StockReorderLevel;
  }

  set StockReorderLevel(value: number) {
    this._StockReorderLevel = value;
  }

  get BufferStockLevel(): number {
    return this._BufferStockLevel;
  }

  set BufferStockLevel(value: number) {
    this._BufferStockLevel = value;
  }

  async create(
    loginUser: LoginUser,
    dbTransaction?: any,
  ): Promise<ProductWithInventoryModel | any> {
    try {
      const productCreated = await super.create(loginUser, dbTransaction);
      const data = {
        ProductId: productCreated.ProductId,
        UOM: this.UOM,
        TotalUnits: this.TotalUnits,
        TotalUnitsAvailable: this.TotalUnitsAvailable,
        TotalUnitsInCurrentOrder: this.TotalUnitsInCurrentOrder,
        TotalUnitsSold: this.TotalUnitsSold,
        TotalUnitsReserved: this.TotalUnitsReserved,
        TotalUnitsOnConsignment: this.TotalUnitsOnConsignment,
        TotalUnitsUnderMaintenance: this.TotalUnitsUnderMaintenance,
        TotalUnitsVoid: this.TotalUnitsVoid,
        TotalUnitsInTransit: this.TotalUnitsInTransit,
        TotalUnitsBackOrdered: this.TotalUnitsBackOrdered,
        TotalUnitsPreOrdered: this.TotalUnitsPreOrdered,
        StockLowAlertLevel: this.StockLowAlertLevel,
        StockReorderLevel: this.StockReorderLevel,
        BufferStockLevel: this.BufferStockLevel,
      };
      const productWithInventoryCreated =
        await ProductWithInventoryBase._ProductWithInventoryRepository.create(
          data,
          {
            transaction: dbTransaction,
          },
        );

      const activity = new Activity();
      activity.ActivityId = cuid();
      activity.Action = ActionEnum.CREATE;
      activity.Description = 'Add new product with inventory';
      activity.EntityType = 'ProductWithInventory';
      activity.EntityId = data.ProductId;
      activity.EntityValueBefore = JSON.stringify({});
      activity.EntityValueAfter = JSON.stringify(
        productWithInventoryCreated.get({ plain: true }),
      );

      await activity.create(loginUser.ObjectId, dbTransaction);

      return {
        ...productCreated.get({ plain: true }),
        ...productWithInventoryCreated.get({ plain: true }),
      };
    } catch (err) {
      throw err;
    }
  }

  public async deactivate(
    loginUser: LoginUser,
    dbTransaction?: any,
  ): Promise<void> {
    super.deactivate(loginUser, dbTransaction);
  }

  public async verify(
    loginUser: LoginUser,
    dbTransaction?: any,
  ): Promise<void> {
    try {
      await super.verify(loginUser, dbTransaction);
    } catch (error) {
      throw error;
    }
  }

  public async delete(
    loginUser: LoginUser,
    dbTransaction?: any,
  ): Promise<void> {
    try {
      await super.delete(loginUser, dbTransaction);
    } catch (error) {
      throw error;
    }
  }

  public async activate(
    loginUser: LoginUser,
    dbTransaction?: any,
  ): Promise<void> {
    try {
      await super.activate(loginUser, dbTransaction);
    } catch (error) {
      throw error;
    }
  }
}
