import { SelfAccountKeyring } from "../keyring/account_self";
import { AbstractSelfAccountKeyring } from "../keyring/account_base";
import { AbstractPrivateKeyring } from "../keyring/private";
import { account_password_change } from "./password";
import { ACCOUNT_ROOT_KEY_CRYPTO_CONTEXT } from "../context/account_key/root/__init__";
import { AccountRootKeyConfigLoadArgs } from "../context/account_key/root/args";
import { Ed25519KeyGenerator } from "../base/key/ec";
import { ACCOUNT_SIGNATURE_CRYPTO_CONTEXT } from "../context/account_signature/__init__";
import { AccountSignatureConfigDumpArgs } from "../context/account_signature/args";
import { base64 } from "rfc4648";
import { concatByteArray, makeInfoByteArray } from "../utility";

export interface create_account_recovery_confirm_request_type {
  recovery_token: string;
  salt: string;
  master_key: string;
  auth_key: string;
  signature: string;
}

/**
 *
 * @param private_kr_cls
 * @param recovery_token acquired from URL fragment, sent to user as email by recover-prepare
 * @param account_id returned by recover-challenge for use here
 * @param encrypted_signing_secret_ec returned by recover-challenge for use here
 * @param recovery_key provided by the user
 * @param new_password provided by the user
 * @param enforce_normalized_password for testing
 */
export async function create_account_recovery_confirm_request(
  private_kr_cls: typeof AbstractPrivateKeyring,
  recovery_token: string,
  account_id: string,
  encrypted_signing_secret_ec: Uint8Array,
  recovery_key: Uint8Array,
  new_password: string,
  enforce_normalized_password?: boolean,
): Promise<create_account_recovery_confirm_request_type> {
  console.log(
    private_kr_cls,
    recovery_token,
    account_id,
    encrypted_signing_secret_ec,
    recovery_key,
    new_password
  );
  let recovery_kr = new SelfAccountKeyring(
    account_id,
    {},
    { [AbstractSelfAccountKeyring.MASTER]: recovery_key }
  );
  let [client_salt_input, encrypted_master_key, hashed_authentication_key] =
    await account_password_change(private_kr_cls, recovery_kr, new_password, enforce_normalized_password);

  let ed25519_key = Ed25519KeyGenerator.regenerate_key_pair(
    await ACCOUNT_ROOT_KEY_CRYPTO_CONTEXT.load(
      new AccountRootKeyConfigLoadArgs(
        encrypted_signing_secret_ec,
        recovery_kr,
        SelfAccountKeyring.ED25519
      )
    )
  );

  recovery_kr.update(
    { [SelfAccountKeyring.ED25519]: ed25519_key.publicKey },
    { [SelfAccountKeyring.ED25519]: ed25519_key.secretKey }
  );
  let signature = await ACCOUNT_SIGNATURE_CRYPTO_CONTEXT.dump(
    new AccountSignatureConfigDumpArgs(
      makeInfoByteArray([
        recovery_token,
        client_salt_input,
        encrypted_master_key,
        hashed_authentication_key,
      ]),
      recovery_kr
    )
  );
  return {
    recovery_token: recovery_token,
    salt: base64.stringify(client_salt_input),
    master_key: base64.stringify(encrypted_master_key),
    auth_key: base64.stringify(hashed_authentication_key),
    signature: base64.stringify(signature),
  };
}
