import groovy.xml.XmlSlurper

def getUserAGOVLoiRoles() {
  // set attibutes from DTO: -> AGOVaq
  def list = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
  return list.'**'.findAll { node -> node.name() == 'roles' && node.applicationName.text() == 'AGOV-Loi' }.collect({ node -> node.name.text() })
}

def getUserAGOVLoiIdVerification() {
  // set attibutes from DTO: -> idVerification
  def list = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
  return list.'**'.findAll {node -> node.name() == 'properties' && node.name.text() == 'idVerification' }.collect({ node -> node.value.text()})
}

def getUserAGOVLoiValidFrom(level) {
  // set attibutes from DTO: -> validFrom
  def payload = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
  return payload.'**'.find {node -> node.name() == 'authorizations' && node.role.name.text() == level}.getProperty("validFrom")
}

def getUserAGOVLoiValidTo(level) {
  // set attibutes from DTO: -> validTo
  def payload = new XmlSlurper().parseText(session.get('ch.adnovum.nevisidm.userDto'))
  return payload.'**'.find {node -> node.name() == 'authorizations' && node.role.name.text() == level}.getProperty("validTo")
}

// Accounting
def requester = session['ch.nevis.auth.saml.request.scoping.requesterId'] ?: 'unknown'
def requestId = session['ch.nevis.auth.saml.request.id'] ?: 'unknown'
def requestedAq = session['agov.requestedRoleLevel'] ?: 'unknown'
def user = session['ch.adnovum.nevisidm.user.extId'] ?: 'unknown'
def credentialType = session['authenticatedWith'] ?: 'unknown'
def sourceIp = request.getLoginContext()['connection.HttpHeader.X-Real-IP'] ?: 'unknown'
def userAgent = request.getLoginContext()['connection.HttpHeader.user-agent'] ?: request.getLoginContext()['connection.HttpHeader.User-Agent'] ?: 'unknown'

try {
  // beef
  def session = request.getAuthSession(true)
  def highestRoleLevelNumber = 0
  def requestedRoleLevelNumber = session.get('agov.requestedRoleLevel').toInteger()
  def hasValidatedAddress = Arrays.stream(response.getActualRoles()).filter(s -> s == 'AGOV-Loi.level200').findAny().isPresent()

  LOG.debug('Requested role level '+ requestedRoleLevelNumber)
  LOG.debug('idVerification: ' + getUserAGOVLoiIdVerification())
  LOG.debug('hasValidatedAddress : ' + hasValidatedAddress)

  session.setAttribute('idVerification', getUserAGOVLoiIdVerification().last())
  session.setAttribute('agov.hasValidatedAddress', '' + hasValidatedAddress)


  if (requestedRoleLevelNumber == 0) {
    // AuthnFailed_Zero_RoleLvl
    response.setResult('noRoleLevel');
    return
  }

  if (session.get('ch.adnovum.nevisidm.profileExtId') == '') {
    LOG.error("Event='DATAERROR', Requester='${requester}', RequestId='${requestId}', RequestedAq=${requestedAq}, User=${user}, CredentialType='${credentialType}', errorMessage='Account without Profile', SourceIp=${sourceIp}, UserAgent='${userAgent}'")

    session.setAttribute('contextClassRefToSet', 'urn:qa.agov.ch:names:tc:ac:classes:100')
    response.setResult('ok')
    return
  }

  // Transform sex to number
  if(session.get('ch.nevis.idm.User.gender') == 'MALE'){
          session.setAttribute('ch.nevis.idm.User.gender', '1')
  }
  if(session.get('ch.nevis.idm.User.gender') == 'FEMALE'){
          session.setAttribute('ch.nevis.idm.User.gender', '2')
  }
  if(session.get('ch.nevis.idm.User.gender') == 'OTHER'){
          session.setAttribute('ch.nevis.idm.User.gender', '3')
  }


  for (String role : getUserAGOVLoiRoles()) {
  if (role.startsWith('level')) {
    def roleLevel = role.substring(5)
    int roleLevelNumber = Integer.parseInt(roleLevel)
    if (highestRoleLevelNumber == 0) {
      highestRoleLevelNumber = roleLevelNumber
    }
    if (highestRoleLevelNumber< roleLevelNumber) { 
      highestRoleLevelNumber=roleLevelNumber 
    } 
  } 
  } 
  LOG.debug('Highest role Level' + highestRoleLevelNumber.toString() +' contextclassref' + requestedRoleLevelNumber.toString()) 
  LOG.debug(' Compare' + (highestRoleLevelNumber>=requestedRoleLevelNumber)) 

  //set attribute Actual Role Level
  session.setAttribute('agov.actualRoleLevel', '' + highestRoleLevelNumber)
  LOG.info('actual role level (agov) '+ highestRoleLevelNumber)

  if (highestRoleLevelNumber > 0) {
    // set attribute contextClassRefToSet
    session.setAttribute('contextClassRefToSet','urn:qa.agov.ch:names:tc:ac:classes:' .concat(highestRoleLevelNumber.toString()))
  } else {
    // by default 100
    session.setAttribute('contextClassRefToSet','urn:qa.agov.ch:names:tc:ac:classes:100' ) 
  }

  if (highestRoleLevelNumber>=requestedRoleLevelNumber) { 

    // set attribute ValidFrom and ValidTo (only for higher than 100)
    if (highestRoleLevelNumber > 100) {
      def validFrom = getUserAGOVLoiValidFrom('level'.concat(highestRoleLevelNumber.toString()))
      def validTo = getUserAGOVLoiValidTo('level'.concat(highestRoleLevelNumber.toString()))

      LOG.debug('ValidFrom :' + validFrom)
      LOG.debug('ValidTo :' + validTo)

      if(validFrom != '') {
        session.setAttribute('ValidFrom', '' + validFrom) 
      }
      if(validTo != '') {
        session.setAttribute('ValidTo', '' + validTo) 
      }
    }
    response.setResult('ok')
    return; 
  } else { 
    // Insufficient_LoaInfo
    response.setResult('insufficientLoa'); 
    return; 
  }
} catch (Exception ex) {
  LOG.error("Event='DATAERROR', Requester='${requester}', RequestId='${requestId}', RequestedAq=${requestedAq}, User=${user}, CredentialType='${credentialType}', errorMessage='exception occured: ${ex}', SourceIp=${sourceIp}, UserAgent='${userAgent}'")
  // AuthnFailed_Zero_RoleLvl
  response.setResult('noRoleLevel');
  return;
}