/*
 This file is part of GNU Taler
 (C) 2020 Taler Systems S.A.

 GNU Taler is free software; you can redistribute it and/or modify it under the
 terms of the GNU General Public License as published by the Free Software
 Foundation; either version 3, or (at your option) any later version.

 GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with
 GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */

/**
 * Imports.
 */
import {
  encodeCrock,
  getRandomBytes,
  j2s,
  TalerWireGatewayHttpClient,
  TransactionMajorState,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { WithdrawalGroupStatus } from "../../../taler-wallet-core/src/db.js";
import { createSimpleTestkudosEnvironmentV3 } from "../harness/environments.js";
import {
  getTestHarnessPaytoForLabel,
  GlobalTestState,
} from "../harness/harness.js";

/**
 * Run test re-denominating a withdrawal group
 * after the exchange loses its denomination private keys.
 *
 * This test is for a particularly complex scenario,
 * where exchange doesn't offer any good denomination for a while.
 */
export async function runDenomLostComplexTest(t: GlobalTestState) {
  // Set up test environment

  const { walletClient, bankClient, exchangeBankAccount, exchange } =
    await createSimpleTestkudosEnvironmentV3(t);

  const acctName = "my-acct";
  const myPayto = getTestHarnessPaytoForLabel(acctName);

  await bankClient.registerAccountExtended({
    name: acctName,
    password: encodeCrock(getRandomBytes(32)),
    username: acctName,
    payto_uri: myPayto,
  });

  // Withdraw digital cash into the wallet.

  const wres = await walletClient.call(
    WalletApiOperation.AcceptManualWithdrawal,
    {
      exchangeBaseUrl: exchange.baseUrl,
      amount: "TESTKUDOS:10",
    },
  );

  {
    const txns = await walletClient.call(
      WalletApiOperation.GetTransactionsV2,
      {},
    );
    console.log(`transactions at start: ${j2s(txns)}`);
  }

  const wireGatewayApiClient = new TalerWireGatewayHttpClient(
    exchangeBankAccount.wireGatewayApiBaseUrl,
  );

  await exchange.stop();

  await exchange.purgeSecmodDenomKeys();

  t.logStep("before-skip-keyup");
  await exchange.start({
    skipKeyup: true,
  });

  t.logStep("after-skip-keyup");

  await wireGatewayApiClient.addIncoming({
    auth: exchangeBankAccount.wireGatewayAuth,
    body: {
      amount: "TESTKUDOS:10",
      debit_account: myPayto,
      reserve_pub: wres.reservePub,
    },
  });

  t.logStep("after-add-incoming");

  await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
    transactionId: wres.transactionId,
    txState: WithdrawalGroupStatus.PendingRedenominate,
  });

  t.logStep("after-wait-pending-redenominate");

  // This time, start without skipping key update
  await exchange.stop();
  await exchange.start();

  t.logStep("after-exchange-restart");

  await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
    transactionId: wres.transactionId,
    txState: {
      major: TransactionMajorState.Done,
    },
  });

  t.logStep("after-wait-done");

  const txns = await walletClient.call(
    WalletApiOperation.GetTransactionsV2,
    {},
  );

  console.log(`${j2s(txns)}`);

  const bal = await walletClient.call(WalletApiOperation.GetBalanceDetail, {
    currency: "TESTKUDOS",
  });

  console.log(`${j2s(bal)}`);
}

runDenomLostComplexTest.suites = ["wallet"];
