import { ClassError, ObjectBase } from '@tomei/general';
import { HirerChangeRequestSignatureRepository } from './hirer-change-request-signature.repository';
import { LoginUser } from '@tomei/sso';
import { ActionEnum, Activity } from '@tomei/activity-history';
import { HirerChangeRequestHirerRoleEnum } from '../../enum/rental-hirer-change-request-hirer-role';
import { IHirerChangeRequestSignatureAttr } from '../../interfaces';

export class HirerChangeRequestSignature
  extends ObjectBase
  implements IHirerChangeRequestSignatureAttr
{
  ObjectId: string;
  ObjectName: string;
  ObjectType: string = 'HirerChangeRequestSignature';
  TableName: string = 'hirerChangeRequest_Signature';

  RequestId: string;
  CustomerId: string;
  JointHirerId: string;
  HirerType: HirerChangeRequestHirerRoleEnum;
  SignedAt: Date;
  Method: string;
  Remarks: string;
  CreatedAt: Date;
  UpdatedAt: Date;
  UpdatedById: string;

  protected static _Repository = new HirerChangeRequestSignatureRepository();

  protected constructor(attr?: IHirerChangeRequestSignatureAttr) {
    super();
    if (attr) {
      this.SignatureId = attr.SignatureId;
      this.RequestId = attr.RequestId;
      this.CustomerId = attr.CustomerId;
      this.JointHirerId = attr.JointHirerId;
      this.SignedAt = attr.SignedAt;
      this.Method = attr.Method;
      this.HirerType = attr.HirerType;
      this.Remarks = attr.Remarks;
      this.CreatedAt = attr.CreatedAt;
      this.UpdatedAt = attr.UpdatedAt;
      this.UpdatedById = attr.UpdatedById;
    }
  }

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

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

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

  toJSON(): IHirerChangeRequestSignatureAttr {
    return {
      SignatureId: this.SignatureId,
      RequestId: this.RequestId,
      CustomerId: this.CustomerId,
      JointHirerId: this.JointHirerId,
      HirerType: this.HirerType,
      SignedAt: this.SignedAt,
      Method: this.Method,
      Remarks: this.Remarks,
      CreatedAt: this.CreatedAt,
      UpdatedAt: this.UpdatedAt,
      UpdatedById: this.UpdatedById,
    };
  }

  public async create(loginUser: LoginUser, dbTransaction?: any) {
    //This method will create a new Hirer Change Request Signature.
    try {
      // Part 1: Create Hirer Change Request Signature Records
      // 1.1 Set other attributes
      this.ObjectId = this.createId();
      this.CreatedAt = new Date();
      this.UpdatedById = loginUser.ObjectId;
      this.UpdatedAt = new Date();

      // 1.2 Set Entity value after
      const entityValueAfter: IHirerChangeRequestSignatureAttr = {
        SignatureId: this.SignatureId,
        RequestId: this.RequestId,
        CustomerId: this.CustomerId,
        JointHirerId: this.JointHirerId,
        HirerType: this.HirerType,
        SignedAt: this.SignedAt,
        Method: this.Method,
        Remarks: this.Remarks,
        CreatedAt: this.CreatedAt,
        UpdatedAt: this.UpdatedAt,
        UpdatedById: this.UpdatedById,
      };

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

      //Part 2: Record Create Hirer Change Request Signature Activity
      const activity = new Activity();
      activity.ObjectId = this._createId();
      activity.Action = ActionEnum.CREATE;
      activity.Description = 'Add Hirer Change Request Signature';
      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 update(loginUser: LoginUser, dbTransaction: any) {
    try {
      // Part 1: Update Hirer Change Request Signature Records
      // 1.1 Set entityValueBefore
      const entityValueBefore: IHirerChangeRequestSignatureAttr = {
        SignatureId: this.SignatureId,
        RequestId: this.RequestId,
        CustomerId: this.CustomerId,
        JointHirerId: this.JointHirerId,
        HirerType: this.HirerType,
        SignedAt: this.SignedAt,
        Method: this.Method,
        Remarks: this.Remarks,
        CreatedAt: this.CreatedAt,
        UpdatedAt: this.UpdatedAt,
        UpdatedById: this.UpdatedById,
      };

      // 1.2 Update SignedAt UpdatedById, and UpdateAt
      this.SignedAt = new Date();
      this.UpdatedById = loginUser.ObjectId;
      this.UpdatedAt = new Date();

      // 1.3 Set Entity value after
      const entityValueAfter: IHirerChangeRequestSignatureAttr = {
        SignatureId: this.SignatureId,
        RequestId: this.RequestId,
        CustomerId: this.CustomerId,
        JointHirerId: this.JointHirerId,
        HirerType: this.HirerType,
        SignedAt: this.SignedAt,
        Method: this.Method,
        Remarks: this.Remarks,
        CreatedAt: this.CreatedAt,
        UpdatedAt: this.UpdatedAt,
        UpdatedById: this.UpdatedById,
      };

      // 1.3 Call repo class create method by passing the class attributes and db transaction.
      await HirerChangeRequestSignature._Repository.update(entityValueAfter, {
        where: {
          SignatureId: this.SignatureId,
        },
        transaction: dbTransaction,
      });

      //Part 2: Record Create Hirer Change Request Activity
      const activity = new Activity();
      activity.ObjectId = this._createId();
      activity.Action = ActionEnum.UPDATE;
      activity.Description = 'Update Hirer Change Request Signature';
      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;
    }
  }

  public async markSigned(loginUser: LoginUser, dbTransaction: any) {
    try {
      // Part 1: Update Hirer Change Request Signature Records
      // 1.1 Set entityValueBefore
      const entityValueBefore: IHirerChangeRequestSignatureAttr = {
        SignatureId: this.SignatureId,
        RequestId: this.RequestId,
        CustomerId: this.CustomerId,
        JointHirerId: this.JointHirerId,
        HirerType: this.HirerType,
        SignedAt: this.SignedAt,
        Method: this.Method,
        Remarks: this.Remarks,
        CreatedAt: this.CreatedAt,
        UpdatedAt: this.UpdatedAt,
        UpdatedById: this.UpdatedById,
      };

      // 1.2 Update SignedAt UpdatedById, and UpdateAt
      this.SignedAt = new Date();
      this.UpdatedById = loginUser.ObjectId;
      this.UpdatedAt = new Date();

      // 1.3 Set Entity value after
      const entityValueAfter: IHirerChangeRequestSignatureAttr = {
        SignatureId: this.SignatureId,
        RequestId: this.RequestId,
        CustomerId: this.CustomerId,
        JointHirerId: this.JointHirerId,
        HirerType: this.HirerType,
        SignedAt: this.SignedAt,
        Method: this.Method,
        Remarks: this.Remarks,
        CreatedAt: this.CreatedAt,
        UpdatedAt: this.UpdatedAt,
        UpdatedById: this.UpdatedById,
      };

      // 1.3 Call repo class create method by passing the class attributes and db transaction.
      await HirerChangeRequestSignature._Repository.update(entityValueAfter, {
        where: {
          SignatureId: this.SignatureId,
        },
        transaction: dbTransaction,
      });

      //Part 2: Record Create Hirer Change Request Activity
      const activity = new Activity();
      activity.ObjectId = this._createId();
      activity.Action = ActionEnum.UPDATE;
      activity.Description = 'Mark Hirer Change Request Signature as Signed';
      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;
    }
  }
}
