package gw.contact

uses com.guidewire.pc.domain.PCBulkInsertWorkQueueBase
uses entity.AccountContactRole
uses gw.api.archiving.ArchiveDocumentReferencesUtil
uses gw.api.database.IQuery
uses gw.api.database.IQueryBuilder
uses gw.api.database.PCDatabaseReferenceTrackerUtility
uses gw.api.database.Query
uses gw.api.personaldata.DataDestructionParameterCheck
uses gw.api.util.PCDeleteBuilder

/**
 * Delete obsolete {@link AccountContactRole} and {@link AccountContactRoleReplacement} entities.
 *
 * Candidate {@link AccountContactRole} entities are retired. If a retired AccountContactRole entity is not referenced
 * by other entities in the database, nor referenced from any archive then we delete it. If we find an
 * AccountContactRoleReplacement entity related to an AccountContactRole we are deleting, we delete it as well if it is
 * also not referenced within the database nor from any archive.
 */
@ReadOnly
class CleanupAccountContactRoleWorkQueue extends PCBulkInsertWorkQueueBase<AccountContactRole> {
  construct () {
    super(BatchProcessType.TC_CLEANUPACCOUNTCONTACTROLE, StandardWorkItem, AccountContactRole)
  }

  override function findTargets(query: IQueryBuilder) : Iterator {
    DataDestructionParameterCheck.verifyPersonalDataDestructionEnabled();

    query.withFindRetired(true).compare(AccountContactRole.RETIREDVALUE_PROP.get(), NotEquals, 0L)
    return (query as IQuery).withLogSQL(true).select().iterator()
  }

  override function processWorkItem(workItem : StandardWorkItem) {
    var accountContactRole = extractTarget(workItem)

    if (!PCDatabaseReferenceTrackerUtility.isReferencedFromDatabase(accountContactRole) &&
        !ArchiveDocumentReferencesUtil.isReferencedFromArchiveDocument(accountContactRole)) {
      var accountContactRoleReplacement = Query.make(AccountContactRoleReplacement)
          .compare(AccountContactRoleReplacement.MERGEDPUBLICID_PROP.get(), Equals, accountContactRole.PublicID)
          .withFindRetired(true)
          .select()
          .AtMostOneRow

      var accountContactRoleQuery = Query.make(AccountContactRole)
      accountContactRoleQuery
          .withLogSQL(true)
          .withFindRetired(true)
          .compare(AccountContactRole.ID_PROP.get(), Equals, accountContactRole.ID)

      if (accountContactRoleReplacement == null) {
        PCDeleteBuilder.executeDelete(accountContactRoleQuery)
      } else {
        if (!PCDatabaseReferenceTrackerUtility.isReferencedFromDatabase(accountContactRoleReplacement) &&
            !ArchiveDocumentReferencesUtil.isReferencedFromArchiveDocument(accountContactRoleReplacement)) {
          var accountContactRoleReplacementQuery = Query.make(AccountContactRoleReplacement)
          accountContactRoleReplacementQuery
              .withLogSQL(true)
              .withFindRetired(true)
              .compare(AccountContactRoleReplacement.ID_PROP.get(), Equals, accountContactRoleReplacement.ID)
          PCDeleteBuilder.executeDelete(accountContactRoleReplacementQuery)

          PCDeleteBuilder.executeDelete(accountContactRoleQuery)
        }
      }
    }
  }
}