import { ClassError, ObjectBase } from '@tomei/general';
import { AgreementSignatureRepository } from './agreement-signature.repository';
import { IAgreementSignatureAttr } from '../../interfaces/agreemeent-signature-attr.interface';
import { ApplicationConfig } from '@tomei/config';
import { LoginUser } from '@tomei/sso';
import { ActionEnum, Activity } from '@tomei/activity-history';
import { AgreementSignatureStatusEnum } from '../../enum/agreement-signature-status.enum';
import { AgreementSignatureVerificationMethodEnum } from '../../enum/agreement-signature-verification-method.enum';

export class AgreementSignature
  extends ObjectBase
  implements IAgreementSignatureAttr
{
  ObjectId: string;
  ObjectName: string;
  ObjectType: string = 'AgreementSignature';
  TableName: string = 'rental_AgreementSignature';
  AgreementNo: string;
  Party: string;
  PartyId: string;
  PartyType: string;
  SignatureStatus: AgreementSignatureStatusEnum;
  SignedAt: Date;
  VerificationMethod: AgreementSignatureVerificationMethodEnum;
  VerificationJustification: string;
  VerifiedById: string;
  CreatedById: string;
  CreatedAt: Date;
  UpdatedById: string;
  UpdatedAt: Date;

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

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

  protected static _Repository = new AgreementSignatureRepository();

  protected constructor(AgreementSignatureAttr?: IAgreementSignatureAttr) {
    super();
    if (AgreementSignatureAttr) {
      this.SignatureId = AgreementSignatureAttr.SignatureId;
      this.AgreementNo = AgreementSignatureAttr.AgreementNo;
      this.Party = AgreementSignatureAttr.Party;
      this.PartyId = AgreementSignatureAttr.PartyId;
      this.PartyType = AgreementSignatureAttr.PartyType;
      this.SignatureStatus = AgreementSignatureAttr.SignatureStatus;
      this.SignedAt = AgreementSignatureAttr.SignedAt;
      this.VerificationMethod = AgreementSignatureAttr.VerificationMethod;
      this.VerificationJustification =
        AgreementSignatureAttr.VerificationJustification;
      this.VerifiedById = AgreementSignatureAttr.VerifiedById;
      this.CreatedById = AgreementSignatureAttr.CreatedById;
      this.CreatedAt = AgreementSignatureAttr.CreatedAt;
      this.UpdatedById = AgreementSignatureAttr.UpdatedById;
      this.UpdatedAt = AgreementSignatureAttr.UpdatedAt;
    }
  }

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

  public async create(loginUser: LoginUser, dbTransaction?: any) {
    try {
      const systemCode =
        ApplicationConfig.getComponentConfigValue('system-code');
      const isPrivileged = await loginUser.checkPrivileges(
        systemCode,
        'AgreementSignature - Create',
      );

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

      if (!this.AgreementNo || !this.PartyId || !this.PartyType) {
        throw new ClassError(
          'AgreementSignature',
          'AgreementSignatureErrMsg03',
          'AgreementNo, PartyId and PartyType are required.',
        );
      }

      this.ObjectId = this.createId();
      this.VerifiedById = loginUser.ObjectId;
      this.CreatedById = loginUser.ObjectId;
      this.CreatedAt = new Date();
      this.UpdatedById = loginUser.ObjectId;
      this.UpdatedAt = new Date();

      const entityValueAfter: IAgreementSignatureAttr = {
        SignatureId: this.SignatureId,
        AgreementNo: this.AgreementNo,
        Party: this.Party,
        PartyId: this.PartyId,
        PartyType: this.PartyType,
        SignatureStatus: this.SignatureStatus,
        SignedAt: this.SignedAt,
        VerificationMethod: this.VerificationMethod,
        VerificationJustification: this.VerificationJustification,
        VerifiedById: this.VerifiedById,
        CreatedById: this.CreatedById,
        CreatedAt: this.CreatedAt,
        UpdatedById: this.UpdatedById,
        UpdatedAt: this.UpdatedAt,
      };

      await AgreementSignature._Repository.create(entityValueAfter, {
        transaction: dbTransaction,
      });

      const activity = new Activity();
      activity.ObjectId = this.createId();
      activity.Action = ActionEnum.CREATE;
      activity.Description = 'Add Joint Hirer 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;
    }
  }
}
