/*
 This file is part of GNU Taler
 (C) 2024 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 {
  codecForAmlKycAttributes,
  Configuration,
  decodeCrock,
  Duration,
  encodeCrock,
  hashNormalizedPaytoUri,
  j2s,
  LimitOperationType,
  signAmlQuery,
  TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
import { createSyncCryptoApi } from "@gnu-taler/taler-wallet-core";
import {
  configureCommonKyc,
  createKycTestkudosEnvironment,
  postAmlDecision,
} from "../harness/environments.js";
import {
  getTestHarnessPaytoForLabel,
  GlobalTestState,
  harnessHttpLib,
} from "../harness/harness.js";

function adjustExchangeConfig(config: Configuration) {
  configureCommonKyc(config);

  config.setString("KYC-RULE-R1", "operation_type", "withdraw");
  config.setString("KYC-RULE-R1", "enabled", "yes");
  config.setString("KYC-RULE-R1", "exposed", "yes");
  config.setString("KYC-RULE-R1", "is_and_combinator", "no");
  config.setString("KYC-RULE-R1", "threshold", "TESTKUDOS:100");
  config.setString("KYC-RULE-R1", "timeframe", "1d");
  config.setString("KYC-RULE-R1", "next_measures", "verboten");
}

/**
 * Tests for making AML decisions.
 * - Test making decisions on unknown accounts.
 * - Test making decisions with default rules.
 */
export async function runKycDecisionAttrTest(t: GlobalTestState) {
  // Set up test environment

  // FIXME: Reduced test environment without merchant suffices
  const {
    walletClient,
    bankClient,
    exchange,
    amlKeypair,
    exchangeBankAccount,
  } = await createKycTestkudosEnvironment(t, { adjustExchangeConfig });

  const merchantPayto = getTestHarnessPaytoForLabel("merchant-default");

  const cryptoApi = createSyncCryptoApi();

  const kycPaytoHash = encodeCrock(hashNormalizedPaytoUri(merchantPayto));

  await postAmlDecision(t, {
    amlPriv: amlKeypair.priv,
    amlPub: amlKeypair.pub,
    exchangeBaseUrl: exchange.baseUrl,
    paytoHash: kycPaytoHash,
    paytoUri: merchantPayto,
    attributes: { foo: 42 },
    attributes_expiration: TalerProtocolTimestamp.never(),
    newRules: {
      expiration_time: TalerProtocolTimestamp.now(),
      custom_measures: {},
      rules: [
        {
          operation_type: LimitOperationType.deposit,
          display_priority: 1,
          exposed: true,
          measures: ["verboten"],
          threshold: "TESTKUDOS:10",
          timeframe: Duration.toTalerProtocolDuration(
            Duration.fromSpec({
              days: 1,
            }),
          ),
        },
        {
          operation_type: LimitOperationType.withdraw,
          display_priority: 1,
          exposed: true,
          measures: ["verboten"],
          threshold: "TESTKUDOS:0",
          timeframe: Duration.toTalerProtocolDuration(
            Duration.fromSpec({
              days: 1,
            }),
          ),
        },
      ],
    },
  });

  const sig = signAmlQuery(decodeCrock(amlKeypair.priv));

  const attributesResp = await harnessHttpLib.fetch(
    new URL(
      `aml/${amlKeypair.pub}/attributes/${kycPaytoHash}`,
      exchange.baseUrl,
    ).href,
    {
      headers: {
        "Taler-AML-Officer-Signature": encodeCrock(sig),
      },
    },
  );

  const attrs = await readSuccessResponseJsonOrThrow(
    attributesResp,
    codecForAmlKycAttributes(),
  );

  console.log(j2s(attrs));

  t.assertDeepEqual(attrs.details[0].attributes?.foo, 42);
}

runKycDecisionAttrTest.suites = ["wallet"];
