import {
  getOpaqueConfig,
  OpaqueID,
  CredentialFile,
  OpaqueServer,
  KE1
} from '../lib/opaque.mjs'

const cfg = getOpaqueConfig(
  OpaqueID.OPAQUE_P256,
  'OPAQUE demo'
)

  
async function auth_init( request, env, context ) {

  const requestJSON = await request.json()

  const initSerialized = requestJSON[ 'ke1' ]
  const client_identity = requestJSON[ 'username' ].trim()

  // username is also being used for this demo as server-side credential_identifier  
  const credential_identifier = client_identity

  const credentials_u8array = await env.KV.get( credential_identifier, { type: 'arrayBuffer' } )
  if ( credentials_u8array === null ) {
    throw new Error( 'client not found in database' )
  }

  const credential_file = CredentialFile.deserialize( cfg, Array.from( new Uint8Array( credentials_u8array ) ) )

  if ( credential_file.credential_identifier !== credential_identifier ) {
    throw new Error( 'credential identifier does not match KV key it was retrieved from' )
  }
  if ( credential_file.client_identity !== client_identity ) {
	throw new Error( 'stored credentials file does not seem to match client' )
  }

  const oprf_seed = JSON.parse( env.oprf_seed )
  const server_ake_keypair = JSON.parse( env.server_ake_keypair )
  const server_identity = env.server_identity

  const server = new OpaqueServer(
    cfg,
    oprf_seed,
    server_ake_keypair,
    server_identity
  )

  const ke1 = KE1.deserialize( cfg, initSerialized )
 
  const initiated = await server.authInit(
    ke1,
    credential_file.record,
    credential_file.credential_identifier,
    credential_file.client_identity
  )
  if ( initiated instanceof Error ) {
    throw initiated
  } 

  const { ke2, expected } = initiated

  // save expected in Durable Object
  const id = env.SESSION.idFromName( client_identity )
  const obj = env.SESSION.get( id )
  context.waitUntil( obj.fetch( '/save', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify( { username: client_identity, expected: expected.serialize() } )
  } ) )

  return new Response( JSON.stringify( {
      message: 'intermediate authentication key enclosed',
      ke2: ke2.serialize()
    } ), {
    headers: { 'Content-Type': 'application/json' }
  } )

}

export { auth_init }