/*
 This file is part of GNU Taler
 (C) 2023 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 {
  j2s,
  ScopeType,
  TalerCorebankApiClient,
  TransactionType,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { defaultCoinConfig } from "../harness/denomStructures.js";
import {
  createSimpleTestkudosEnvironmentV3,
  withdrawViaBankV3,
} from "../harness/environments.js";
import { ExchangeService, GlobalTestState } from "../harness/harness.js";

/**
 * Run test for a base URL migration, where
 * the wallet already has funds for the base URL we're migrating to.
 */
export async function runWalletExchangeMigrationExistingTest(
  t: GlobalTestState,
) {
  // Set up test environment

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

  // Withdraw digital cash into the wallet.
  const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl);

  await withdrawViaBankV3(t, {
    walletClient,
    bankClient,
    exchange,
    amount: "TESTKUDOS:20",
  });

  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});

  await exchange.stop();

  // Exchange running on a different port.
  const exchange2 = ExchangeService.create(t, {
    name: "testexchange-1",
    currency: "TESTKUDOS",
    httpPort: 8181,
    hostname: "myexchange.localhost",
    database: commonDb.connStr,
    allowExistingMasterPriv: true,
  });

  exchange2.addCoinConfigList(defaultCoinConfig.map((x) => x("TESTKUDOS")));

  await exchange2.addBankAccount("1", exchangeBankAccount);

  await exchange2.start();

  const wres2 = await withdrawViaBankV3(t, {
    walletClient,
    bankClient,
    exchange: exchange2,
    amount: "TESTKUDOS:20",
  });

  await wres2.withdrawalFinishedCond;

  await walletClient.call(
    WalletApiOperation.TestingPlanMigrateExchangeBaseUrl,
    {
      oldExchangeBaseUrl: exchange.baseUrl,
      newExchangeBaseUrl: exchange2.baseUrl,
    },
  );

  try {
    await walletClient.call(WalletApiOperation.UpdateExchangeEntry, {
      exchangeBaseUrl: exchange.baseUrl,
      force: true,
    });
  } catch (e) {}

  const balances = await walletClient.call(WalletApiOperation.GetBalances, {});
  console.log(j2s(balances));

  t.assertDeepEqual(balances.balances.length, 1);
  const si = balances.balances[0].scopeInfo;
  t.assertDeepEqual(si.type, ScopeType.Exchange);
  t.assertDeepEqual(si.url, "http://myexchange.localhost:8181/");

  const transactions = await walletClient.call(
    WalletApiOperation.GetTransactionsV2,
    {},
  );
  console.log(j2s(transactions));
  t.assertDeepEqual(transactions.transactions.length, 2);
  const tx0 = transactions.transactions[0];
  t.assertDeepEqual(tx0.type, TransactionType.Withdrawal);
  t.assertDeepEqual(tx0.exchangeBaseUrl, "http://myexchange.localhost:8181/");
}

runWalletExchangeMigrationExistingTest.suites = ["wallet"];
