import cuid = require('cuid');
import { ProductBrandRepository } from './brand-product.repository';
import { LoginUser } from '@tomei/sso';
import { ApplicationConfig } from '@tomei/config';
import { ClassError, ObjectBase } from '@tomei/general';
import { ActionEnum, Activity } from '@tomei/activity-history';
import { IProductBrandAttr } from '../../interfaces/product-brand-attr.interface';

export class ProductBrand extends ObjectBase {
  ObjectId: string;
  ObjectName: string;
  TableName: string;
  ObjectType = 'ProductBrand';
  ProductId: string;

  get Brand(): string {
    return this.ObjectId;
  }

  set Brand(value: string) {
    this.ObjectId = value;
  }

  private static _Repo = new ProductBrandRepository();

  private constructor(brandAttr: IProductBrandAttr) {
    super();
    if (brandAttr) {
      this.Brand = brandAttr.Brand;
      this.ProductId = brandAttr.ProductId;
    }
  }

  static async init(dbTransaction: any, brand?: string) {
    if (brand) {
      const data = await ProductBrand._Repo.findByPk(brand, dbTransaction);

      if (data) {
        return new ProductBrand({
          ProductId: data.ProductId,
          Brand: data.Brand,
        });
      } else {
        throw new ClassError(
          'ProductBrand',
          'ProductBrandErrMsg01',
          'ProductBrand not found.',
        );
      }
    }

    return new ProductBrand(dbTransaction);
  }

  public static async findAll(
    ProductId: string,
    loginUser: LoginUser,
    dbTransaction: any,
  ) {
    try {
      // Privilege checking
      const systemCode =
        ApplicationConfig.getComponentConfigValue('system-code');

      const isPrivileged = await loginUser.checkPrivileges(
        systemCode,
        'ProductBrand - List',
      );
      if (!isPrivileged) {
        throw new Error('You do not have permission to list product brand.');
      }

      const options = {
        where: {
          ProductId: ProductId,
        },
        transaction: dbTransaction,
      };

      const productBrand = await this._Repo.findAndCountAll(options);
      return productBrand;
    } catch (error) {
      throw error;
    }
  }

  public async create(loginUser: LoginUser, dbTransaction: any) {
    try {
      // Privilege checking
      const systemCode =
        ApplicationConfig.getComponentConfigValue('system-code');

      const isPrivileged = await loginUser.checkPrivileges(
        systemCode,
        'ProductBrand - Create',
      );
      if (!isPrivileged) {
        throw new Error('You do not have permission to Create product tag.');
      }

      //Validate Fields
      if (!this.ProductId) {
        throw new ClassError(
          'ProductBrand',
          'ProductBrandErrMsg02',
          'ProductId is missing.',
        );
      }

      if (!this.Brand) {
        throw new ClassError(
          'ProductTag',
          'ProductTagErrMsg03',
          'Brand is missing.',
        );
      }

      const brand = await ProductBrand._Repo.create({
        Brand: this.Brand,
        ProductId: this.ProductId,
      });

      const entityValueAfter = {
        Brand: this.Brand,
        ProductId: this.ProductId,
      };

      const activity = new Activity();
      activity.ActivityId = cuid();
      activity.Action = ActionEnum.CREATE;
      activity.Description = 'Add Product Brand';
      activity.EntityType = 'ProductBrand';
      activity.EntityId = this.Brand;
      activity.EntityValueBefore = JSON.stringify({});
      activity.EntityValueAfter = JSON.stringify(entityValueAfter);
      await activity.create(loginUser.ObjectId, dbTransaction);
      return brand;
    } catch (error) {
      throw error;
    }
  }

  public async delete(loginUser: LoginUser, dbTransaction: any) {
    try {
      // Privilege checking
      const systemCode =
        ApplicationConfig.getComponentConfigValue('system-code');

      const isPrivileged = await loginUser.checkPrivileges(
        systemCode,
        'ProductBrand - Delete',
      );
      if (!isPrivileged) {
        throw new Error('You do not have permission to Delete product brand.');
      }

      //update product tag
      const entityValueBefore = {
        Brand: this.Brand,
        ProductId: this.ProductId,
      };

      await ProductBrand._Repo.delete(this.Brand, dbTransaction);

      const activity = new Activity();
      activity.ActivityId = cuid();
      activity.Action = ActionEnum.DELETE;
      activity.Description = 'Delete Product Brand';
      activity.EntityType = 'ProductBrand';
      activity.EntityId = this.Brand;
      activity.EntityValueBefore = JSON.stringify(entityValueBefore);
      activity.EntityValueAfter = JSON.stringify({});
      await activity.create(loginUser.ObjectId, dbTransaction);
      return {
        MessageCode: 'ProductBrandDeleted',
        Message: 'Product brand is deleted.',
      };
    } catch (error) {
      throw error;
    }
  }
}
