import { AbsoluteTime, AmountJson, Amounts, Codec, OperationResult, buildCodecForObject, codecForNumber, codecForString, codecOptional } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { h } from "preact";
import { NiceForm } from "../NiceForm.js";
import { v1 as form_902_11e_v1 } from "../forms/902_11e.js";
import { v1 as form_902_12e_v1 } from "../forms/902_12e.js";
import { v1 as form_902_13e_v1 } from "../forms/902_13e.js";
import { v1 as form_902_15e_v1 } from "../forms/902_15e.js";
import { v1 as form_902_1e_v1 } from "../forms/902_1e.js";
import { v1 as form_902_4e_v1 } from "../forms/902_4e.js";
import { v1 as form_902_5e_v1 } from "../forms/902_5e.js";
import { v1 as form_902_9e_v1 } from "../forms/902_9e.js";
import { v1 as simplest } from "../forms/simplest.js";
import { Pages } from "../pages.js";
import { AmlExchangeBackend } from "../types.js";
import { useExchangeApiContext } from "../context/config.js";
import { FlexibleForm } from "../forms/index.js";

export function AntiMoneyLaunderingForm({ account, formId, onSubmit }: { account: string, formId: string, onSubmit: (justification: Justification, state: AmlExchangeBackend.AmlState, threshold: AmountJson) => Promise<void>; }) {
  const { i18n } = useTranslationContext()
  const theForm = allForms.find((v) => v.id === formId)
  if (!theForm) {
    return <div>form with id {formId} not found</div>
  }

  const { config } = useExchangeApiContext()

  const initial = {
    when: AbsoluteTime.now(),
    state: AmlExchangeBackend.AmlState.pending,
    threshold: Amounts.zeroOfCurrency(config.currency),
  };
  return (
    <NiceForm
      initial={initial}
      form={theForm.impl(initial)}
      onUpdate={() => { }}
      onSubmit={(formValue) => {
        if (formValue.state === undefined || formValue.threshold === undefined) return;
        const st = formValue.state;
        const amount = formValue.threshold;

        const justification: Justification = {
          id: theForm.id,
          label: theForm.label,
          version: theForm.version,
          value: formValue
        }

        onSubmit(justification, st, amount);
      }}
    >
      <div class="mt-6 flex items-center justify-end gap-x-6">
        <a
          href={Pages.account.url({ account })}
          class="text-sm font-semibold leading-6 text-gray-900"
        >
          <i18n.Translate>Cancel</i18n.Translate>
        </a>
        <button
          type="submit"
          class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
        >
          <i18n.Translate>Confirm</i18n.Translate>
        </button>
      </div>
    </NiceForm>
  );
}

export interface BaseForm {
  state: AmlExchangeBackend.AmlState;
  threshold: AmountJson;
}

const DocumentDuplicateIcon = <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
  <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 01-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 011.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 00-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 01-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5a3.375 3.375 0 00-3.375-3.375H9.75" />
</svg>


export type FormMetadata<T extends BaseForm> = {
  label: string,
  id: string,
  version: number,
  icon: h.JSX.Element,
  impl: (current: BaseForm) => FlexibleForm<T>
}

export type Justification<T = any> = {
  // form values
  value: T;
} & Omit<Omit<FormMetadata<any>, "icon">, "impl">

export function stringifyJustification(j: Justification): string {
  return JSON.stringify(j)
}


type SimpleFormMetadata = {
  version?: number,
  id?: string,
}

export const codecForSimpleFormMetadata = (): Codec<SimpleFormMetadata> =>
  buildCodecForObject<SimpleFormMetadata>()
    .property("id", codecOptional(codecForString()))
    .property("version", codecOptional(codecForNumber()))
    .build("SimpleFormMetadata");

type ParseJustificationFail =
  "not-json" |
  "id-not-found" |
  "form-not-found" |
  "version-not-found";

export function parseJustification(s: string, listOfAllKnownForms: FormMetadata<any>[]): OperationResult<{ justification: Justification, metadata: FormMetadata<any> }, ParseJustificationFail> {
  try {
    const justification = JSON.parse(s)
    const info = codecForSimpleFormMetadata().decode(justification)
    if (!info.id) {
      return {
        type: "fail",
        case: "id-not-found",
        detail: {} as any
      }
    }
    if (!info.version) {
      return {
        type: "fail",
        case: "version-not-found",
        detail: {} as any
      }
    }
    const found = listOfAllKnownForms.find((f) => {
      return f.id === info.id && f.version === info.version
    })
    if (!found) {
      return {
        type: "fail",
        case: "form-not-found",
        detail: {} as any
      }
    }
    return {
      type: "ok",
      body: {
        justification, metadata: found
      }
    }
  } catch (e) {
    return {
      type: "fail",
      case: "not-json",
      detail: {} as any
    }
  }

}

export const allForms: Array<FormMetadata<BaseForm>> = [
  {
    label: "Simple comment",
    id: "simple_comment",
    version: 1,
    icon: DocumentDuplicateIcon,
    impl: simplest,
  },
  {
    label: "Identification form",
    id: "902.1e",
    version: 1,
    icon: DocumentDuplicateIcon,
    impl: form_902_1e_v1,
  },
  {
    label: "Operational legal entity or partnership",
    id: "902.11e",
    version: 1,
    icon: DocumentDuplicateIcon,
    impl: form_902_11e_v1,
  },
  {
    label: "Foundations",
    id: "902.12e",
    version: 1,
    icon: DocumentDuplicateIcon,
    impl: form_902_12e_v1,
  },
  {
    label: "Declaration for trusts",
    id: "902.13e",
    version: 1,
    icon: DocumentDuplicateIcon,
    impl: form_902_13e_v1,
  },
  {
    label: "Information on life insurance policies",
    id: "902.15e",
    version: 1,
    icon: DocumentDuplicateIcon,
    impl: form_902_15e_v1,
  },
  {
    label: "Declaration of beneficial owner",
    id: "902.9e",
    version: 1,
    icon: DocumentDuplicateIcon,
    impl: form_902_9e_v1,
  },
  {
    label: "Customer profile",
    id: "902.5e",
    version: 1,
    icon: DocumentDuplicateIcon,
    impl: form_902_5e_v1,
  },
  {
    label: "Risk profile",
    id: "902.4e",
    version: 1,
    icon: DocumentDuplicateIcon,
    impl: form_902_4e_v1,
  },
];
