import { TalerAmlProperties } from "../taler-account-properties.js";
import { TalerFormAttributes } from "../taler-form-attributes.js";
import { AccountProperties, LegitimizationRuleSet } from "../types-taler-exchange.js";

/**
 * List of account properties required by TOPS
 */
export const TOPS_AccountProperties = [
  TalerAmlProperties.FILE_NOTE,
  TalerAmlProperties.CUSTOMER_LABEL,
  TalerAmlProperties.ACCOUNT_OPEN,
  TalerAmlProperties.PEP_DOMESTIC,
  TalerAmlProperties.PEP_FOREIGN,
  TalerAmlProperties.PEP_INTERNATIONAL_ORGANIZATION,
  TalerAmlProperties.HIGH_RISK_CUSTOMER,
  TalerAmlProperties.HIGH_RISK_COUNTRY,
  TalerAmlProperties.ACCOUNT_IDLE,
  TalerAmlProperties.INVESTIGATION_TRIGGER,
  TalerAmlProperties.INVESTIGATION_STATE,
  TalerAmlProperties.SANCTION_LIST_BEST_MATCH,
  TalerAmlProperties.SANCTION_LIST_RATING,
  TalerAmlProperties.SANCTION_LIST_CONFIDENCE,
  TalerAmlProperties.SANCTION_LIST_SUPPRESS,
] as const;

/**
 * List of account properties required by GLS
 */
export const GLS_AccountProperties = [TalerAmlProperties.FILE_NOTE] as const;

export type PropertiesDerivationFunctionByPropertyName<T extends string> = {
  [name in T]: {
    /**
     * Based on all the current properties, the current account limits and
     * new attributes of the account calculate if the property should
     * change. The value "undefined" means no change.
     *
     * @param formId the current form being filled by the officer
     * @param newAttributes the values of the current form
     * @param limits
     * @param state the current state of the account
     * @returns
     */
    deriveProperty: (
      formId: string,
      newAttributes: Record<keyof typeof TalerFormAttributes, unknown>,
      limits: LegitimizationRuleSet,
      state: AccountProperties,
    ) => string | boolean | undefined;
  };
};

export enum KnownForms {
  vqf_902_1_customer,
  vqf_902_1_officer,
  vqf_902_4,
  vqf_902_5,
  vqf_902_9_customer,
  vqf_902_9_officer,
  vqf_902_11_customer,
  vqf_902_11_officer,
  vqf_902_12,
  vqf_902_13,
  vqf_902_14,
  vqf_902_15,
}

export function isOneOf(formId: string, ...allowedForms: KnownForms[]) {
  return (
    -1 !==
    allowedForms.findIndex((af) => {
      return formId === KnownForms[af];
    })
  );
}

/**
 * Calculate the value of the propertiy for TOPS account properties
 */
export const PropertiesDerivation_TOPS: PropertiesDerivationFunctionByPropertyName<
  (typeof TOPS_AccountProperties)[number]
> = {
  ACCOUNT_OPEN: {
    deriveProperty(formId, attributes, limits, state) {
      if (
        isOneOf(
          formId,
          KnownForms.vqf_902_1_customer,
          KnownForms.vqf_902_1_officer,
        )
      ) {
        // if one of the vqf 902.1 then the account is being open
        return true;
      }
      return false;
    },
  },
  PEP_DOMESTIC: {
    deriveProperty(formId, attributes, limits, state) {
      if (isOneOf(formId, KnownForms.vqf_902_4)) {
        return !!attributes[TalerFormAttributes.PEP_DOMESTIC];
      }
      return undefined;
    },
  },
  PEP_FOREIGN: {
    deriveProperty(formId, attributes, limits, state) {
      if (isOneOf(formId, KnownForms.vqf_902_4)) {
        return !!attributes[TalerFormAttributes.PEP_FOREIGN];
      }
      return undefined;
    },
  },
  PEP_INTERNATIONAL_ORGANIZATION: {
    deriveProperty(formId, attributes, limits, state) {
      if (isOneOf(formId, KnownForms.vqf_902_4)) {
        return !!attributes[TalerFormAttributes.PEP_INTERNATIONAL_ORGANIZATION];
      }
      return undefined;
    },
  },
  HIGH_RISK_CUSTOMER: {
    deriveProperty(formId, attributes, limits, state) {
      if (isOneOf(formId, KnownForms.vqf_902_4)) {
        return (
          attributes[TalerFormAttributes.RISK_CLASSIFICATION_LEVEL] ===
          "HIGH_RISK"
        );
      }
      return undefined;
    },
  },
  HIGH_RISK_COUNTRY: {
    deriveProperty(formId, attributes, limits, state) {
      if (isOneOf(formId, KnownForms.vqf_902_4)) {
        return (
          attributes[TalerFormAttributes.COUNTRY_RISK_NATIONALITY_LEVEL] ===
          "HIGH"
        );
      }
      return undefined;
    },
  },
  ACCOUNT_IDLE: {
    deriveProperty(formId, attributes, limits, state) {
      return undefined;
    },
  },
  CUSTOMER_LABEL: {
    deriveProperty(formId, attributes, limits, state) {
      return undefined;
    },
  },
  FILE_NOTE: {
    deriveProperty(formId, attributes, limits, state) {
      return undefined;
    },
  },
  INVESTIGATION_STATE: {
    deriveProperty(formId, attributes, limits, state) {
      if (isOneOf(formId, KnownForms.vqf_902_14)) {
        if (
          attributes[TalerFormAttributes.INCRISK_RESULT] === "SIMPLE_SUSPICION"
        ) {
          return "REPORTED_SUSPICION_SIMPLE";
        }
        if (
          attributes[TalerFormAttributes.INCRISK_RESULT] === "SUBSTANTIATED_SUSPICION"
        ) {
          return "REPORTED_SUSPICION_SUBSTANTIATED";
        }
        if (
          attributes[TalerFormAttributes.INCRISK_RESULT] === "NO_SUSPICION"
        ) {
          return "INVESTIGATION_COMPLETED_WITHOUT_SUSPICION";
        }
        if (
          attributes[TalerFormAttributes.INCRISK_RESULT] === "OTHER"
        ) {
          return null as any;
        }
      }

      return undefined;
    },
  },
  INVESTIGATION_TRIGGER: {
    deriveProperty(formId, attributes, limits, state) {
      return undefined;
    },
  },
  SANCTION_LIST_BEST_MATCH: {
    deriveProperty(formId, attributes, limits, state) {
      return undefined;
    },
  },
  SANCTION_LIST_CONFIDENCE: {
    deriveProperty(formId, attributes, limits, state) {
      return undefined;
    },
  },
  SANCTION_LIST_RATING: {
    deriveProperty(formId, attributes, limits, state) {
      return undefined;
    },
  },
  SANCTION_LIST_SUPPRESS: {
    deriveProperty(formId, attributes, limits, state) {
      return undefined;
    },
  },
};

export const GLS_AML_PROPERTIES: PropertiesDerivationFunctionByPropertyName<
  (typeof GLS_AccountProperties)[number]
> = {
  FILE_NOTE: {
    deriveProperty(formId, attributes, limits, state) {
      return undefined;
    },
  },
};
