/*
 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 Affero 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 Affero Public License for more details.

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

import { TalerFormAttributes } from "@gnu-taler/taler-util";
import { intervalToDuration, isDate, isFuture, isValid, parse } from "date-fns";
import {
  DoubleColumnFormDesign,
  InternationalizationAPI,
  UIFormElementConfig,
} from "../../index.browser.js";
import { countryNationalityList } from "../../utils/select-ui-lists.js";

const Descr = {
  CUSTOMER_INFO_TYPE: (
    i18n: InternationalizationAPI,
  ) => i18n.str`The customer is the person with whom the member concludes the contract with regard to the financial service provided (civil law). Does the
  member act as director of a domiciliary company, this domiciliary company is the customer.`,
} as const;

export const form_vqf_902_1_customer = (i18n: InternationalizationAPI) => ({
  label: i18n.str`Identification Form (customer)`,
  description: i18n.str`The customer has to be identified on entering into a permanent business relationship or on concluding a cash transaction, which meets the according threshold.`,
  id: "vqf_902_1_customer",
  version: 1,
  config: design_VQF_902_1_customer(i18n),
});

const fieldCorrespondenceLanguage = (
  i18n: InternationalizationAPI,
): UIFormElementConfig => ({
  id: TalerFormAttributes.CORRESPONDENCE_LANGUAGE,
  required: true,
  label: i18n.str`Correspondence language:`,
  type: "choiceStacked",
  choices: [
    {
      value: "en",
      label: i18n.str`English`,
    },
    {
      value: "de",
      label: i18n.str`German`,
    },
    {
      value: "fr",
      label: i18n.str`French`,
    },
    {
      value: "it",
      label: i18n.str`Italian`,
    },
  ],
});

/**
 * Form vqf_902_1_customer.
 */
export function design_VQF_902_1_customer(
  i18n: InternationalizationAPI,
): DoubleColumnFormDesign {
  return {
    type: "double-column",
    title: i18n.str`Identification form (basic customer information)`,
    sections: [
      {
        title: i18n.str`Information on customer`,
        description: Descr.CUSTOMER_INFO_TYPE(i18n),
        fields: [
          {
            id: TalerFormAttributes.CUSTOMER_TYPE,
            label: i18n.str`Customer type`,
            type: "choiceStacked",
            choices: [
              {
                value: "NATURAL_PERSON",
                label: i18n.str`Natural person (incl. sole proprietors)`,
              },
              {
                value: "LEGAL_ENTITY",
                label: i18n.str`Legal entity`,
              },
            ],
            required: true,
          },
        ],
      },
      {
        title: i18n.str`Information on customer`,
        description: i18n.str`Applicable if customer is a natural person`,
        hide(root) {
          return root[TalerFormAttributes.CUSTOMER_TYPE] !== "NATURAL_PERSON";
        },
        fields: [
          {
            id: TalerFormAttributes.FULL_NAME,
            label: i18n.str`Full name`,
            type: "text",
            required: true,
          },
          {
            id: TalerFormAttributes.DOMICILE_ADDRESS,
            label: i18n.str`Residential address in Switzerland`,
            type: "textArea",
            required: true,
          },
          {
            id: TalerFormAttributes.CONTACT_PHONE,
            label: i18n.str`Telephone`,
            type: "text",
            required: false,
          },
          {
            id: TalerFormAttributes.CONTACT_EMAIL,
            label: i18n.str`E-mail`,
            type: "text",
            required: false,
          },
          {
            id: TalerFormAttributes.DATE_OF_BIRTH,
            label: i18n.str`Date of birth`,
            type: "isoDateText",
            placeholder: "dd/MM/yyyy",
            pattern: "dd/MM/yyyy",
            defaultCalendarValue: "1980-01-01",
            required: true,
            validator(text, form) {
              //FIXME: why returning in this format even if pattern is in another?
              const time = parse(text, "yyyy-MM-dd", new Date());
              if (!isValid(time)) {
                return i18n.str`invalid format`;
              }
              if (isFuture(time)) {
                return i18n.str`it can't be in the future`;
              }
              const { years } = intervalToDuration({
                start: time,
                end: new Date(),
              });
              if (years && years > 120) {
                return i18n.str`it can't be greater than 120 years`;
              }
              return undefined;
            },
          },
          {
            id: TalerFormAttributes.NATIONALITY,
            label: i18n.str`Nationality`,
            type: "selectOne",
            choices: countryNationalityList(i18n),
            preferredChoiceVals: ["CH"],
            required: true,
          },
          {
            id: TalerFormAttributes.PERSONAL_IDENTIFICATION_DOCUMENT_COPY,
            label: i18n.str`Copy of identification document`,
            type: "file",
            accept: "application/pdf",
            tooltip: i18n.str`Only official government IDs (incl. passports) are accepted. Please scan both sides if applicable.`,
            required: true,
          },
          {
            id: TalerFormAttributes.CUSTOMER_IS_SOLE_PROPRIETOR,
            label: i18n.str`Sole proprietor`,
            type: "toggle",
            threeState: false,
          },
        ],
      },
      {
        title: i18n.str`Information on customer (sole proprietor)`,
        description: i18n.str`Applicable only if customer is a sole proprietor`,
        hide(root) {
          return (
            root[TalerFormAttributes.CUSTOMER_TYPE] !== "NATURAL_PERSON" ||
            !root[TalerFormAttributes.CUSTOMER_IS_SOLE_PROPRIETOR]
          );
        },
        fields: [
          {
            id: TalerFormAttributes.COMPANY_NAME,
            label: i18n.str`Company name`,
            type: "text",
            required: true,
          },
          {
            id: TalerFormAttributes.REGISTERED_OFFICE_ADDRESS,
            label: i18n.str`Registered office`,
            type: "text",
            required: true,
          },
          {
            id: TalerFormAttributes.LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY,
            label: i18n.str`Company identification document`,
            type: "file",
            required: true,
            accept: "application/pdf",
          },
        ],
      },
      {
        title: i18n.str`Information on customer (legal entity)`,
        description: i18n.str`Applicable if customer is a legal entity`,
        hide(root) {
          return root[TalerFormAttributes.CUSTOMER_TYPE] !== "LEGAL_ENTITY";
        },
        fields: [
          {
            id: TalerFormAttributes.COMPANY_NAME,
            label: i18n.str`Company name`,
            type: "text",
            required: true,
          },
          {
            id: TalerFormAttributes.DOMICILE_ADDRESS,
            label: i18n.str`Domicile`,
            type: "textArea",
            required: true,
          },
          {
            id: TalerFormAttributes.CONTACT_PERSON_NAME,
            label: i18n.str`Contact person`,
            type: "text",
            required: false,
          },
          {
            id: TalerFormAttributes.CONTACT_PHONE,
            label: i18n.str`Telephone`,
            type: "text",
            required: false,
          },
          {
            id: TalerFormAttributes.CONTACT_EMAIL,
            label: i18n.str`E-mail`,
            type: "text",
            required: false,
          },
          {
            id: TalerFormAttributes.LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY,
            label: i18n.str`Copy of identification document (not older than 12 months)`,
            type: "file",
            accept: "application/pdf",
            required: true,
          },
        ],
      },
      {
        title: i18n.str`Correspondence Preferences`,
        hide(root) {
          return !root[TalerFormAttributes.CUSTOMER_TYPE];
        },
        fields: [fieldCorrespondenceLanguage(i18n)],
      },
      {
        title: i18n.str`Information on the natural persons who establish the business relationship for legal entities and partnerships`,
        description: i18n.str`For legal entities and partnerships the identity of the natural persons who establish the business relationship must be verified.`,
        hide(root) {
          return root[TalerFormAttributes.CUSTOMER_TYPE] !== "LEGAL_ENTITY";
        },
        fields: [
          {
            id: TalerFormAttributes.ESTABLISHER_LIST,
            label: i18n.str`Establishers of the legal relationship`,
            type: "array",
            labelFieldId: TalerFormAttributes.FULL_NAME,
            required: true,
            fields: [
              {
                id: TalerFormAttributes.FULL_NAME,
                label: i18n.str`Full name`,
                type: "text",
                required: true,
              },
              {
                id: TalerFormAttributes.DOMICILE_ADDRESS,
                label: i18n.str`Residential address`,
                type: "textArea",
                required: true,
              },
              {
                id: TalerFormAttributes.DATE_OF_BIRTH,
                label: i18n.str`Date of birth`,
                type: "isoDateText",
                placeholder: "dd/MM/yyyy",
                pattern: "dd/MM/yyyy",
                defaultCalendarValue: "1980-01-01",
                required: true,
                validator(text, form) {
                  //FIXME: why returning in this format even if pattern is in another?
                  const time = parse(text, "yyyy-MM-dd", new Date());
                  if (!isValid(time)) {
                    return i18n.str`invalid format`;
                  }
                  if (isFuture(time)) {
                    return i18n.str`it can't be in the future`;
                  }
                  const { years } = intervalToDuration({
                    start: time,
                    end: new Date(),
                  });
                  if (years && years > 120) {
                    return i18n.str`it can't be greater than 120 years`;
                  }
                  return undefined;
                },
              },
              {
                id: TalerFormAttributes.NATIONALITY,
                label: i18n.str`Nationality`,
                type: "selectOne",
                choices: countryNationalityList(i18n),
                preferredChoiceVals: ["CH"],
                required: true,
              },
              {
                id: TalerFormAttributes.PERSONAL_IDENTIFICATION_DOCUMENT_COPY,
                label: i18n.str`Copy of identification document`,
                type: "file",
                accept: "application/pdf",
                tooltip: i18n.str`Only official government IDs (incl. passports) are accepted. Please scan both sides if applicable.`,
                required: true,
              },
              {
                id: TalerFormAttributes.SIGNING_AUTHORITY_TYPE,
                tooltip: i18n.str`Signing authority of the person`,
                label: i18n.str`Power of attorney arrangements`,
                type: "choiceStacked",
                required: true,
                choices: [
                  {
                    label: "Sole signature authority",
                    value: "SINGLE",
                  },
                  {
                    label: "Collective authority with two signatures",
                    value: "COLLECTIVE_TWO",
                  },
                  {
                    label: "Other (please specify)",
                    value: "OTHER",
                  },
                ],
              },
              {
                id: TalerFormAttributes.SIGNING_AUTHORITY_TYPE_OTHER,
                required: true,
                label: i18n.str`Other type of signing authority`,
                type: "text",
                hide(value, root) {
                  return (
                    root[TalerFormAttributes.SIGNING_AUTHORITY_TYPE] !== "OTHER"
                  );
                },
              },
              {
                id: TalerFormAttributes.SIGNING_AUTHORITY_EVIDENCE,
                required: true,
                label: i18n.str`Evidence of signing authority:`,
                type: "choiceStacked",
                choices: [
                  {
                    value: "CR",
                    label: i18n.str`Company register extract`,
                  },
                  {
                    value: "MANDATE",
                    label: i18n.str`Mandate`,
                  },
                  {
                    value: "OTHER",
                    label: i18n.str`Other`,
                  },
                ],
              },
              {
                id: TalerFormAttributes.SIGNING_AUTHORITY_EVIDENCE_OTHER,
                required: true,
                label: i18n.str`Specify other way of establishing signing authority:`,
                type: "text",
                hide(value, root) {
                  return (
                    root[TalerFormAttributes.SIGNING_AUTHORITY_EVIDENCE] !==
                    "OTHER"
                  );
                },
              },
              {
                id: TalerFormAttributes.SIGNING_AUTHORITY_EVIDENCE_DOCUMENT_COPY,
                label: i18n.str`Copy of document that serves as evidence of signing authority:`,
                type: "file",
                accept: "application/pdf",
                required: true,
              },
            ],
          },
        ],
      },
      // Version of the question for natural persons
      {
        title: i18n.str`Customer classification`,
        description: i18n.str`Classification for the establishment of the beneficial owner of the assets and/or controlling person`,
        hide(root) {
          return root[TalerFormAttributes.CUSTOMER_TYPE] !== "NATURAL_PERSON";
        },
        fields: [
          {
            id: TalerFormAttributes.CUSTOMER_TYPE_VQF,
            required: true,
            label: i18n.str`The customer is:`,
            type: "choiceStacked",
            choices: [
              {
                value: "NATURAL_PERSON",
                label: i18n.str`A natural person and there are no doubts that this person is the sole beneficial owner of the assets`,
              },
              {
                value: "OTHER",
                label: i18n.str`Other`,
              },
            ],
          },
        ],
      },
      // Version for Businesses
      {
        title: i18n.str`Customer classification`,
        description: i18n.str`Classification for the establishment of the beneficial owner of the assets and/or controlling person`,
        hide(root) {
          return root[TalerFormAttributes.CUSTOMER_TYPE] !== "LEGAL_ENTITY";
        },
        fields: [
          {
            id: TalerFormAttributes.CUSTOMER_TYPE_VQF,
            required: true,
            label: i18n.str`The customer is:`,
            type: "choiceStacked",
            choices: [
              {
                value: "OPERATIONAL",
                label: i18n.str`An operational legal entity or partnership`,
              },
              {
                value: "FOUNDATION",
                label: i18n.str`A foundation (or a similar construct; incl. underlying companies)`,
              },
              {
                value: "TRUST",
                label: i18n.str`A trust (incl. underlying companies)`,
              },
              {
                value: "LIFE_INSURANCE",
                label: i18n.str`A life insurance policy with separately managed accounts / securities accounts (so-called insurance wrappers)`,
              },
              {
                value: "OTHER",
                label: i18n.str`Other`,
              },
            ],
          },
        ],
      },
    ],
  };
}
