/*
 This file is part of GNU Taler
 (C) 2025 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, Logger } from "@gnu-taler/taler-util";
import { GlobalTestState } from "../harness/harness.js";
import { isFrozen, setupMeasuresTestEnvironment } from "../harness/tops.js";

export const logger = new Logger("test-tops-aml-measures.ts");

/**
 * Test that invokes all measures defined for the TOPS deployment.
 */
export async function runTopsAmlMeasuresTest(t: GlobalTestState) {
  // Setup is done, now the real testing can start!

  const {
    decideMeasure,
    decideReset,
    submitForm,
    expectInfo,
    expectInvestigate,
    expectNoInvestigate,
    expectFrozen,
    fakeChallenger,
    challengerPostal,
    challengerSms,
  } = await setupMeasuresTestEnvironment(t);

  // VQF customer type should lead to
  // investigation.
  {
    await decideMeasure("kyx");
    await expectNoInvestigate();
    await submitForm("vqf_902_1_customer", {
      FORM_ID: "vqf_902_1_customer",
      FORM_VERSION: 1,
      CUSTOMER_TYPE: "LEGAL_ENTITY",
      CUSTOMER_TYPE_VQF: "TRUST",
      COMPANY_NAME: "Alice Inc.",
      REGISTERED_OFFICE_ADDRESS: "Castle St. 1\nWondertown",
      ESTABLISHER_LIST: [],
      LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY: "...",
    });
    await expectInvestigate();
  }

  await decideReset();

  // VQF customer type OTHER should lead to
  // investigation.
  {
    await decideMeasure("kyx");
    await expectNoInvestigate();
    await submitForm("vqf_902_1_customer", {
      FORM_ID: "vqf_902_1_customer",
      FORM_VERSION: 1,
      CUSTOMER_TYPE: "LEGAL_ENTITY",
      CUSTOMER_TYPE_VQF: "OTHER",
      FULL_NAME: "Alice A",
      DOMICILE_ADDRESS: "Castle St. 1\nWondertown",
    });
    await expectInvestigate();
  }

  await decideReset();

  // Complex legal entity
  {
    await decideMeasure("kyx");
    await expectNoInvestigate();
    await submitForm("vqf_902_1_customer", {
      FORM_ID: "vqf_902_1_customer",
      FORM_VERSION: 1,
      CUSTOMER_TYPE: "LEGAL_ENTITY",
      CUSTOMER_TYPE_VQF: "OPERATIONAL",
      COMPANY_NAME: "Alice Inc",
      REGISTERED_OFFICE_ADDRESS: "Castle St. 1\nWondertown",
      ESTABLISHER_LIST: [],
      LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY: "...",
    });
    await expectNoInvestigate();

    // Submit with missing attributes
    await t.assertThrowsTalerErrorAsync(async () => {
      await submitForm("vqf_902_11_customer", {
        FORM_ID: "vqf_902_11_customer",
        THIRD_PARTY_OWNERSHIP: true,
        FORM_VERSION: 1,
      });
    });

    // Form currently only undergoes very basic
    // validation directly upon submission.
    await submitForm("vqf_902_11_customer", {
      FORM_ID: "vqf_902_11_customer",
      FORM_VERSION: 1,
      THIRD_PARTY_OWNERSHIP: true,
      IDENTITY_CONTRACTING_PARTNER: "foo",
      CONTROL_REASON: "bla",
      IDENTITY_LIST: [],
      SIGN_DATE: "2020-01-01",
      SIGNATURE: "Alice",
    });
    await expectNoInvestigate();
    await submitForm("vqf_902_9_customer", {
      FORM_ID: "vqf_902_9_customer",
      FORM_VERSION: 1,
      IDENTITY_CONTRACTING_PARTNER: "foo",
      IDENTITY_LIST: [],
    });
    await expectInvestigate();
  }

  await decideReset();

  {
    await decideMeasure("kyx");
    await expectNoInvestigate();
    await submitForm("vqf_902_1_customer", {
      FORM_ID: "vqf_902_1_customer",
      FORM_VERSION: 1,
      CUSTOMER_TYPE: "NATURAL_PERSON",
      CUSTOMER_TYPE_VQF: "NATURAL_PERSON",
      FULL_NAME: "Alice A",
      DOMICILE_ADDRESS: "Castle St. 1\nWondertown",
      DATE_OF_BIRTH: "2000-01-01",
      PERSONAL_IDENTIFICATION_DOCUMENT_COPY: "...",
      CUSTOMER_IS_SOLE_PROPRIETOR: false,
      NATIONALITY: "DE",
    });
    await expectNoInvestigate();
    await fakeChallenger(challengerPostal, {
      CONTACT_NAME: "Richard Stallman",
      ADDRESS_LINES: "Bundesgasse 1\n1234 Bern",
    });
    await expectInvestigate();
  }

  await decideReset();

  await decideReset();

  // Test with weird customer type
  {
    await decideMeasure("kyx");
    await expectNoInvestigate();
    await submitForm("vqf_902_1_customer", {
      FORM_ID: "vqf_902_1_customer",
      FORM_VERSION: 1,
      CUSTOMER_TYPE: "FOO",
      CUSTOMER_TYPE_VQF: "FOO",
    });
    await expectInvestigate();
  }

  await t.assertThrowsTalerErrorAsync(async () => {
    await decideMeasure("foobar");
  });

  {
    const res = await decideMeasure("freeze-investigate");
    console.log("after freeze-investigate:", j2s(res));
    t.assertTrue(isFrozen(res.currentDecision));
  }

  await decideReset();

  {
    const res = await decideMeasure("inform-investigate");
    console.log("after inform-investigate:", j2s(res));
    t.assertTrue(!isFrozen(res.currentDecision));
  }

  await decideReset();

  {
    await decideMeasure("sms-registration");
    await fakeChallenger(challengerSms, {
      CONTACT_PHONE: "+4123456789",
    });
  }

  {
    await decideMeasure("postal-registration");
    await fakeChallenger(challengerPostal, {
      CONTACT_NAME: "Richard Stallman",
      ADDRESS_LINES: "Bundesgasse 1\n1234 Bern",
    });
  }

  {
    await decideMeasure("accept-tos");
    await submitForm("accept-tos", {
      FORM_ID: "accept-tos",
      FORM_VERSION: 1,
      ACCEPTED_TERMS_OF_SERVICE: "v1",
      DOWNLOADED_TERMS_OF_SERVICE: true,
    });
  }

  {
    await decideMeasure("form-vqf-902.9");
    await submitForm("vqf_902_9_customer", {
      FORM_ID: "vqf_902_9_customer",
      FORM_VERSION: 1,
      IDENTITY_CONTRACTING_PARTNER: "foo",
      IDENTITY_LIST: [],
    });
  }

  {
    await decideMeasure("form-vqf-902.11");
    await submitForm("vqf_902_11_customer", {
      FORM_ID: "vqf_902_11_customer",
      FORM_VERSION: 1,
      THIRD_PARTY_OWNERSHIP: true,
      IDENTITY_CONTRACTING_PARTNER: "foo",
      CONTROL_REASON: "bla",
      IDENTITY_LIST: [],
      SIGN_DATE: "2020-01-01",
      SIGNATURE: "Alice",
    });
    await submitForm("vqf_902_9_customer", {
      FORM_ID: "vqf_902_9_customer",
      FORM_VERSION: 1,
      IDENTITY_CONTRACTING_PARTNER: "foo",
      IDENTITY_LIST: [],
    });
  }

  await decideReset();

  {
    await decideMeasure("form-vqf-902.11");
    await submitForm("vqf_902_11_customer", {
      FORM_ID: "vqf_902_11_customer",
      FORM_VERSION: 1,
      THIRD_PARTY_OWNERSHIP: false,
      IDENTITY_CONTRACTING_PARTNER: "foo",
      CONTROL_REASON: "bla",
      IDENTITY_LIST: [],
      SIGN_DATE: "2020-01-01",
      SIGNATURE: "Alice",
    });
    // No third party ownership => Waiting for AML officer
    await expectInfo();
  }
}

runTopsAmlMeasuresTest.suites = ["wallet"];
