import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { NiceForm } from "../NiceForm.js";
import { FlexibleForm } from "../forms/index.js";
import { UIFormField } from "../handlers/forms.js";
import { AmlEvent } from "./CaseDetails.js";
import { AmlExchangeBackend } from "../types.js";
import { AbsoluteTime, AmountJson, TranslatedString } from "@gnu-taler/taler-util";
import { format } from "date-fns";

export function ShowConsolidated({
  history,
  until,
}: {
  history: AmlEvent[];
  until: AbsoluteTime;
}): VNode {
  const cons = getConsolidated(history, until);

  const form: FlexibleForm<Consolidated> = {
    versionId: "1",
    behavior: (form) => {
      return {
        aml: {
          threshold: {
            hidden: !form.aml
          },
          since: {
            hidden: !form.aml
          },
          state: {
            hidden: !form.aml
          }
        }
      };
    },
    design: [
      {
        title: "AML" as TranslatedString,
        fields: [
          {
            type: "amount",
            props: {
              label: "Threshold" as TranslatedString,
              name: "aml.threshold",
            },
          },
          {
            type: "choiceHorizontal",
            props: {
              label: "State" as TranslatedString,
              name: "aml.state",
              converter: amlStateConverter,
              choices: [
                {
                  label: "Frozen" as TranslatedString,
                  value: AmlExchangeBackend.AmlState.frozen,
                },
                {
                  label: "Pending" as TranslatedString,
                  value: AmlExchangeBackend.AmlState.pending,
                },
                {
                  label: "Normal" as TranslatedString,
                  value: AmlExchangeBackend.AmlState.normal,
                },
              ],
            },
          },
        ],
      },
      Object.entries(cons.kyc).length > 0
        ? {
          title: "KYC" as TranslatedString,
          fields: Object.entries(cons.kyc).map(([key, field]) => {
            const result: UIFormField = {
              type: "text",
              props: {
                label: key as TranslatedString,
                name: `kyc.${key}.value`,
                help: `${field.provider} since ${field.since.t_ms === "never"
                  ? "never"
                  : format(field.since.t_ms, "dd/MM/yyyy")
                  }` as TranslatedString,
              },
            };
            return result;
          }),
        }
        : undefined,
    ],
  };
  return (
    <Fragment>
      <h1 class="text-base font-semibold leading-7 text-black">
        Consolidated information 
        {until.t_ms === "never"
          ? ""
          : `after ${format(until.t_ms, "dd MMMM yyyy")}` }
      </h1>
      <NiceForm
        key={`${String(Date.now())}`}
        form={form}
        initial={cons}
        onUpdate={() => { }}
      />
    </Fragment>
  );
}

interface Consolidated {
  aml: {
    state: AmlExchangeBackend.AmlState;
    threshold: AmountJson;
    since: AbsoluteTime;
  };
  kyc: {
    [field: string]: {
      value: any;
      provider: string;
      since: AbsoluteTime;
    };
  };
}

function getConsolidated(
  history: AmlEvent[],
  when: AbsoluteTime,
): Consolidated {
  const initial: Consolidated = {
    aml: {
      state: AmlExchangeBackend.AmlState.normal,
      threshold: {
        currency: "ARS",
        value: 1000,
        fraction: 0,
      },
      since: AbsoluteTime.never()
    },
    kyc: {},
  };
  return history.reduce((prev, cur) => {
    if (AbsoluteTime.cmp(when, cur.when) < 0) {
      return prev;
    }
    switch (cur.type) {
      case "kyc-expiration": {
        cur.fields.forEach((field) => {
          delete prev.kyc[field];
        });
        break;
      }
      case "aml-form": {
        prev.aml = {
          since: cur.when,
          state: cur.state,
          threshold: cur.threshold
        }
        break;
      }
      case "kyc-collection": {
        Object.keys(cur.values).forEach((field) => {
          prev.kyc[field] = {
            value: (cur.values as any)[field],
            provider: cur.provider,
            since: cur.when,
          };
        });
        break;
      }
    }
    return prev;
  }, initial);
}

export const amlStateConverter = {
  toStringUI: stringifyAmlState,
  fromStringUI: parseAmlState,
};

function stringifyAmlState(s: AmlExchangeBackend.AmlState | undefined): string {
  if (s === undefined) return "";
  switch (s) {
    case AmlExchangeBackend.AmlState.normal:
      return "normal";
    case AmlExchangeBackend.AmlState.pending:
      return "pending";
    case AmlExchangeBackend.AmlState.frozen:
      return "frozen";
  }
}

function parseAmlState(s: string | undefined): AmlExchangeBackend.AmlState {
  switch (s) {
    case "normal":
      return AmlExchangeBackend.AmlState.normal;
    case "pending":
      return AmlExchangeBackend.AmlState.pending;
    case "frozen":
      return AmlExchangeBackend.AmlState.frozen;
    default:
      throw Error(`unknown AML state: ${s}`);
  }
}
