import {
  getOpaqueConfig,
  OpaqueID,
  KE3,
  ExpectedAuthResult,
  OpaqueServer
} from '../lib/opaque.mjs'


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


async function auth_finish( request, env ) {

  const requestJSON = await request.json()

  const ke3Serialized = requestJSON[ 'ke3' ]
  const client_identity = requestJSON[ 'username' ].trim()
  const session_key_client = requestJSON[ 'session_key' ]

  // 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, but in an actual implementation there would be no need to respond with that information.' )
  }

  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 ke3 = KE3.deserialize( cfg, ke3Serialized )

  // retrieve session variables from Durable Object
  const id = env.SESSION.idFromName( client_identity )
  const obj = env.SESSION.get( id )
  const session = await ( await obj.fetch( '/restore' ) ).json()
  const expectedJSON = session.expected

  if ( !expectedJSON ) {
    throw new Error( 'auth_init expected values not found for this client' )
  }

  const expected = ExpectedAuthResult.deserialize( cfg, expectedJSON )

  const authFinish = server.authFinish( ke3, expected )
  if ( authFinish instanceof Error ) {
    throw authFinish
  }

  const { session_key: session_key_server } = authFinish
 
  return new Response( JSON.stringify( {
      message: 'login success',
      session_key_client: session_key_client,
      session_key_server: session_key_server
    } ), {
    headers: { 'Content-Type': 'application/json' }
  } )
  
}

export { auth_finish }