import groovy.json.JsonBuilder
import groovy.json.JsonGenerator
import groovy.json.JsonSlurper

// we cannot use the name cancel and the -bottom is required in ID Cloud for rendering
if (inargs.containsKey('cancel-bottom')) {
    response.setResult('cancel')
    return
}

if (inargs.containsKey('failed')) {
    response.setResult('failed')
    return
}

def getUserFriendlyName(String userAgent) {
    if (userAgent == null) {
        return null
    }
    def sb = new StringBuilder()

    // Check for browser
    def browser = null
    if (userAgent.contains('Chrome')) {
        browser = 'Chrome'
    }
    else if (userAgent.contains('Firefox')) {
        browser = 'Firefox'
    }
    else if (userAgent.contains('Safari')) {
        browser = 'Safari'
    }
    else {
        browser = 'Unknown browser'
    }

    // Check for operating system
    def os = null
    if (userAgent.contains('Windows')) {
        os = 'Windows'
    }
    else if (userAgent.contains('Linux')) {
        os = 'Linux'
    }
    else if (userAgent.contains('iOS')) {
        os = 'iOS'
    }

    // Build the string
    if (browser != null) {
        sb.append(browser)
    }
    if (os != null) {
        if (sb.length() > 0) {
            sb.append(' on ')
        }
        sb.append(os)
    }

    return sb.toString()
}

def getPath() {
    if (inargs.containsKey('path')) { // form POST
        return inargs['path']
    }
    if (inargs.containsKey('o.path.v')) { // AJAX POST
        return inargs['o.path.v']
    }
    return null
}

def post(requestBuilder, json) {
    def body = json.toString()
    LOG.info("==> Request: ${body}")
    def entity = Http.entity().content(body).build()
    def fidoRequest = requestBuilder.entity(entity).build()
    def httpClient = HttpClients.create()
    return fidoRequest.send(httpClient)
}

def path = getPath()
if (path == null) {
    // POST from JavaScript not received
    return // the AuthEngine will trigger default and thus the GUI will be rendered
}

String usernameVal = session['ch.adnovum.nevisidm.user.extId'] ?: session['ch.nevis.idm.User.extId'] ?: request.getUserId() ?: notes['userid']
if (usernameVal == null) {
    LOG.error("missing username. check your authentication flow.")
}
Objects.requireNonNull(usernameVal) // fatal integration error

String displayNameVal = session['ch.nevis.idm.User.email'] ?: session['ch.nevis.session.loginid'] ?: request.getLoginId()
if (displayNameVal == null) {
    LOG.error("missing displayName. check your authentication flow.")
}
Objects.requireNonNull(displayNameVal) // fatal integration error

def baseUrl = "https://" + parameters.get('fido')
def requestBuilder = Http.post().url(baseUrl + path)
    .header('Accept', 'application/json')
    .header('Content-Type', 'application/json;charset=utf-8')

def generator = new JsonGenerator.Options().excludeNulls().build()
def json = new JsonBuilder(generator)

if (path == '/nevisfido/fido2/attestation/options') {
    def name = session['ch.nevis.idm.User.email'] ?: session['ch.nevis.session.loginid'] ?: request.getLoginId()
    json {
        "username" usernameVal
        "displayName" displayNameVal
        "authenticatorSelection" {
            "authenticatorAttachment" parameters.get('authenticatorAttachment')
            "requireResidentKey" parameters.get('requireResidentKey')
            "residentKey" parameters.get('residentKey')
            "userVerification" parameters.get('userVerification')
        }
        "attestation" parameters.get('attestation')
    }
    def fidoResponse = post(requestBuilder, json)
    def responseCode = fidoResponse.code()
    def responseText = fidoResponse.bodyAsString()
    LOG.info("<== Response: ${responseCode} : ${responseText}")
    response.setContent(responseText) // return response from nevisFIDO "as-is"
    response.setContentType('application/json')
    response.setHttpStatusCode(200)
    response.setIsDirectResponse(true)
    return
}

def userAgentVal = request.getHttpHeader('User-Agent')
def userFriendlyNameVal = getUserFriendlyName(userAgentVal)

if (path == '/nevisfido/fido2/attestation/result') {
    json {
        "id" inargs['id']
        "type" inargs['type']
        response {
            "clientDataJSON" inargs['response.clientDataJSON']
            "attestationObject" inargs['response.attestationObject']
        }
        "userFriendlyName" userFriendlyNameVal
        "userAgent" userAgentVal
    }
    def fidoResponse = post(requestBuilder, json)
    def responseCode = fidoResponse.code()
    def responseText = fidoResponse.bodyAsString()
    LOG.info("<== Response: ${responseCode} : ${responseText}")
    if (responseCode == 200 && new JsonSlurper().parseText(responseText).status == 'ok') {
        response.setResult('ok')
        return
    }
}

response.setError(1, "FIDO2 onboarding failed")