import { LoginUser } from '@tomei/sso';
import { ProductProductGroupRepository } from './product-group-product.repository';
import { ApplicationConfig } from '@tomei/config';
import { SettingsGroupModel } from '../../entities/settings-group.entity';
import { ProductBase } from '../../base';
import { ProductGroup } from '../group-product/group-product';
import cuid = require('cuid');
import { ActionEnum, Activity } from '@tomei/activity-history';
import { ObjectBase } from '@tomei/general';

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

  get ProductGroupId() {
    return this.ObjectId;
  }

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

  private static _Repo = new ProductProductGroupRepository();

  public static async CheckProductAssignToGroup(
    code: string,
    dbTransaction?: any,
  ): Promise<any> {
    try {
      const options = {
        where: {
          Code: code,
        },
      };
      const productGroup = await this._Repo.findOne({
        ...options,
        transaction: dbTransaction,
      });
      if (productGroup) {
        return true;
      } else {
        return false;
      }
    } catch (error) {
      throw error;
    }
  }

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

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

      const options = {
        where: {
          ProductId: ProductId,
        },
        include: [
          {
            model: SettingsGroupModel,
          },
        ],
        transaction: dbTransaction,
      };
      const productGroup = await this._Repo
        .findAndCountAll(options)
        .then((groups) => {
          const productGroups = [];
          groups.rows.forEach((pg) => {
            productGroups.push(pg.ProductGroup);
          });
          return {
            count: groups.count,
            rows: productGroups,
          };
        });
      return productGroup;
    } catch (error) {
      throw error;
    }
  }

  public static async assignProductToGroup(
    Product: ProductBase,
    ProductGroup: ProductGroup,
    loginUser: LoginUser,
    dbTransaction?: any,
  ): Promise<any> {
    try {
      // Privilege checking
      const systemCode =
        ApplicationConfig.getComponentConfigValue('system-code');

      const isPrivileged = await loginUser.checkPrivileges(
        systemCode,
        'Product - Assign Group',
      );
      if (!isPrivileged) {
        throw new Error('You do not have permission to assign product group.');
      }

      //Assign Product Group
      const ProductGroupId = cuid();
      ProductProductGroup._Repo.create(
        {
          ProductGroupId: ProductGroupId,
          Code: ProductGroup.Code,
          ProductId: Product.ProductId,
        },
        {
          transaction: dbTransaction,
        },
      );

      const entityValueAfter = {
        ProductGroupId: ProductGroupId,
        Code: ProductGroup.Code,
        ProductId: Product.ProductId,
      };

      const activity = new Activity();
      activity.ActivityId = cuid();
      activity.Action = ActionEnum.CREATE;
      activity.Description = 'Assign Product to Product Group';
      activity.EntityType = 'ProductProductGroup';
      activity.EntityId = ProductGroupId;
      activity.EntityValueBefore = JSON.stringify({});
      activity.EntityValueAfter = JSON.stringify(entityValueAfter);
      await activity.create(loginUser.ObjectId, dbTransaction);
      return {
        MessageCode: 'ProductGroupAssigned',
        Message: 'Product added to Product Group.',
      };
    } catch (error) {
      throw error;
    }
  }

  public static async unassignedProductFromGroup(
    Product: ProductBase,
    ProductGroup: ProductGroup,
    loginUser: LoginUser,
    dbTransaction?: any,
  ): Promise<any> {
    try {
      // Privilege checking
      const systemCode =
        ApplicationConfig.getComponentConfigValue('system-code');

      const isPrivileged = await loginUser.checkPrivileges(
        systemCode,
        'Product - Unassigned Group',
      );
      if (!isPrivileged) {
        throw new Error(
          'You do not have permission to unassigned product group.',
        );
      }

      //Unassigned Product Group
      const productGroup = await ProductProductGroup._Repo.findOne({
        where: { ProductId: Product.ProductId, Code: ProductGroup.Code },
        transaction: dbTransaction,
      });
      const ProductGroupId = productGroup.ProductGroupId;
      ProductProductGroup._Repo.delete(ProductGroupId, dbTransaction);

      const EntityValueBefore = {
        ProductGroupId: productGroup.ProductGroupId,
        Code: productGroup.Code,
        ProductId: productGroup.ProductId,
      };

      const activity = new Activity();
      activity.ActivityId = cuid();
      activity.Action = ActionEnum.DELETE;
      activity.Description = 'Unassigned Product from Product Group';
      activity.EntityType = 'ProductProductGroup';
      activity.EntityId = ProductGroupId;
      activity.EntityValueBefore = JSON.stringify(EntityValueBefore);
      activity.EntityValueAfter = JSON.stringify({});
      await activity.create(loginUser.ObjectId, dbTransaction);
      return {
        MessageCode: 'ProductGroupUnassigned',
        Message: 'Product removed to Product Group.',
      };
    } catch (error) {
      throw error;
    }
  }
}
