import { ClassError, ObjectBase } from '@tomei/general';
import { JointHirerRepository } from './joint-hirer.repository';
import { IJointHirerAttr } from '../../interfaces/joint-hirer-attr.interface';
import { ApplicationConfig } from '@tomei/config';
import { LoginUser } from '@tomei/sso';
import { ActionEnum, Activity } from '@tomei/activity-history';

export class JointHirer extends ObjectBase {
  ObjectId: string;
  ObjectName: string;
  ObjectType: string = 'JointHirer';
  TableName: string = 'rental_JointHirer';
  RentalId: string;
  CustomerId: string;
  CustomerType: string;
  Status = 'Active'; // Default status
  CreatedById: string;
  CreatedAt: Date;
  UpdatedById: string;
  UpdatedAt: Date;

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

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

  protected static _Repository = new JointHirerRepository();

  protected constructor(jointHirerAttr?: IJointHirerAttr) {
    super();
    if (jointHirerAttr) {
      this.HirerId = jointHirerAttr.HirerId;
      this.RentalId = jointHirerAttr.RentalId;
      this.CustomerId = jointHirerAttr.CustomerId;
      this.CustomerType = jointHirerAttr.CustomerType;
      this.Status = jointHirerAttr.Status;
      this.CreatedById = jointHirerAttr.CreatedById;
      this.CreatedAt = jointHirerAttr.CreatedAt;
      this.UpdatedById = jointHirerAttr.UpdatedById;
      this.UpdatedAt = jointHirerAttr.UpdatedAt;
    }
  }

  toJSON(): IJointHirerAttr {
    return {
      HirerId: this.HirerId,
      RentalId: this.RentalId,
      CustomerId: this.CustomerId,
      CustomerType: this.CustomerType,
      Status: this.Status,
      CreatedById: this.CreatedById,
      CreatedAt: this.CreatedAt,
      UpdatedById: this.UpdatedById,
      UpdatedAt: this.UpdatedAt,
    };
  }

  public static async init(hirerId?: string, dbTransaction?: any) {
    try {
      if (hirerId) {
        const jr = await JointHirer._Repository.findByPk(
          hirerId,
          dbTransaction,
        );
        if (jr) {
          return new JointHirer(jr.get({ plain: true }));
        } else {
          throw new ClassError(
            'JointHirer',
            'JointHirerErrMsg01',
            'JointHirer not found',
          );
        }
      }
      return new JointHirer();
    } catch (error) {
      throw error;
    }
  }

  public async create(loginUser: LoginUser, dbTransaction?: any) {
    //This method will create a new joint hirer record.
    try {
      //Part 1: Check Privilege
      const systemCode =
        ApplicationConfig.getComponentConfigValue('system-code');
      const isPrivileged = await loginUser.checkPrivileges(
        systemCode,
        'JointHirer - Create',
      );

      if (!isPrivileged) {
        throw new ClassError(
          'JointHirer',
          'JointHirerErrMsg00',
          "You do not have 'JointHirer - Create' privilege.",
        );
      }

      //Part 2: Insert Joint Hirer Record
      //Check if this.RentalId, this.CustomerId, this.CustomerType have value otherwise throw new ClassError with below params
      if (!this.RentalId || !this.CustomerId || !this.CustomerType) {
        throw new ClassError(
          'JointHirer',
          'JointHirerErrMsg03',
          'RentalId, CustomerId and CustomerType are required.',
        );
      }

      //Set other attributes
      this.ObjectId = this.createId();
      this.CreatedById = loginUser.ObjectId;
      this.CreatedAt = new Date();
      this.UpdatedById = loginUser.ObjectId;
      this.UpdatedAt = new Date();

      const entityValueAfter: IJointHirerAttr = {
        HirerId: this.HirerId,
        RentalId: this.RentalId,
        CustomerId: this.CustomerId,
        CustomerType: this.CustomerType,
        Status: this.Status,
        CreatedById: this.CreatedById,
        CreatedAt: this.CreatedAt,
        UpdatedById: this.UpdatedById,
        UpdatedAt: this.UpdatedAt,
      };

      //Call repo class create method by passing the class attributes and db transaction.
      await JointHirer._Repository.create(entityValueAfter, {
        transaction: dbTransaction,
      });

      //Part 4: Record Create JointHirer Activity
      const activity = new Activity();
      activity.ObjectId = this._createId();
      activity.Action = ActionEnum.CREATE;
      activity.Description = 'Add Joint Hirer';
      activity.EntityId = this.ObjectId;
      activity.EntityType = this.ObjectType;
      activity.EntityValueBefore = JSON.stringify({});
      activity.EntityValueAfter = JSON.stringify(entityValueAfter);

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

      return this;
    } catch (error) {
      throw error;
    }
  }

  public async remove(loginUser: LoginUser, dbTransaction?: any) {
    try {
      //Mark Joint Hirer as Inactive
      const entityValueBefore: IJointHirerAttr = this.toJSON();
      this.Status = 'Inactive'; // Set status to 'Inactive' instead of deleting the record
      this.UpdatedById = loginUser.ObjectId;
      this.UpdatedAt = new Date();
      const entityValueAfter: IJointHirerAttr = this.toJSON();

      // Part 2: Remove Joint Hirer Record
      await JointHirer._Repository.update(entityValueAfter, {
        where: {
          HirerId: this.HirerId,
        },
        transaction: dbTransaction,
      });

      // Part 3: Record Remove JointHirer Activity
      const activity = new Activity();
      activity.ObjectId = this._createId();
      activity.Action = ActionEnum.UPDATE;
      activity.Description = 'Mark Joint Hirer as Inactive';
      activity.EntityId = this.ObjectId;
      activity.EntityType = this.ObjectType;
      activity.EntityValueBefore = JSON.stringify(entityValueBefore);
      activity.EntityValueAfter = JSON.stringify(entityValueAfter);

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

      return this;
    } catch (error) {
      throw error;
    }
  }
}
