/*
 This file is part of GNU Taler
 (C) 2022-2024 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/>
 */
import {
  AbsoluteTime,
  AccessToken,
  AmountJson,
  Amounts,
  assertUnreachable,
  createNewWalletKycAccount,
  eddsaGetPublic,
  encodeCrock,
  HttpStatusCode,
  signKycAuth,
  signWalletAccountSetup,
  WalletKycRequest,
} from "@gnu-taler/taler-util";
import {
  Button,
  FormMetadata,
  FormUI,
  LocalNotificationBanner,
  UIHandlerId,
  useExchangeApiContext,
  useLocalNotificationHandler,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, h, VNode } from "preact";
import { useEffect, useMemo, useState } from "preact/hooks";
import { useFormMeta } from "../../../web-util/src/hooks/useForm.js";

type FormType = {
  amount: AmountJson;
};

type Props = {
  onKycStarted: (token: AccessToken) => void;
};

export function TriggerKyc({ onKycStarted }: Props): VNode {
  const { i18n } = useTranslationContext();
  const [notification, withErrorHandler, notify] =
    useLocalNotificationHandler();
  const { config, lib } = useExchangeApiContext();
  const [kycAccount, setKycAccount] = useState<string>();

  const theForm: FormMetadata = {
    id: "asd",
    version: 1,
    label: i18n.str`Trigger KYC balance`,
    config: {
      type: "double-column",
      sections: [
        {
          title: i18n.str`Trigger KYC Balance`,
          fields: [
            {
              id: "amount" as UIHandlerId,
              type: "amount",
              currency: config.config.currency,
              label: i18n.str`Amount`,
              required: true,
              converterId: "Taler.Amount",
            },
          ],
        },
      ],
    },
  };

  const {
    model: handler,
    status,
    design,
  } = useFormMeta<FormType>(
    theForm,
    {},
    {
      amount: Amounts.parseOrThrow(`${config.config.currency}:1000000`),
    },
  );

  const accountPromise = useMemo(async () => {
    const resp = await lib.exchange.getSeed();
    const extraEntropy = resp.type === "ok" ? resp.body : new Uint8Array();
    return createNewWalletKycAccount(extraEntropy);
  }, [1]);

  useEffect(() => {
    if (!kycAccount) return;
    const paytoHash = kycAccount;
    async function check() {
      const { signingKey } = await accountPromise;
      const merchantPub = eddsaGetPublic(signingKey);
      const accountOwnerSig = encodeCrock(signKycAuth(signingKey));
      const result = await lib.exchange.checkKycStatus({
        accountPub: encodeCrock(merchantPub),
        accountSig: accountOwnerSig,
        paytoHash,
      });
      switch (result.case) {
        case "ok":
          console.log("empty body");
          break;
        case HttpStatusCode.Ok:
        case HttpStatusCode.Accepted:
          onKycStarted(result.body.access_token);
          break;
        case HttpStatusCode.Forbidden: {
          notify({
            type: "error",
            title: i18n.str`could not create token`,
            description: i18n.str`access denied`,
            when: AbsoluteTime.now(),
          });
          break;
        }
        case HttpStatusCode.NotFound: {
          notify({
            type: "error",
            title: i18n.str`could not create token`,
            description: i18n.str`not found`,
            when: AbsoluteTime.now(),
          });
          break;
        }
        case HttpStatusCode.Conflict: {
          notify({
            type: "error",
            title: i18n.str`could not create token`,
            description: i18n.str`conflict`,
            when: AbsoluteTime.now(),
          });
          break;
        }
      }
    }
    check();
  }, [kycAccount]);

  function triggerAmount(amount: AmountJson) {
    return withErrorHandler(
      async () => {
        const account = await accountPromise;
        const balance = Amounts.stringify(amount);
        const limit: WalletKycRequest = {
          balance,
          reserve_pub: account.id,
          reserve_sig: encodeCrock(
            signWalletAccountSetup(account.signingKey, balance),
          ),
        };
        return lib.exchange.notifyKycBalanceLimit(limit);
      },
      (res) => {
        notify({
          type: "info",
          title: i18n.str`No kyc required`,
          when: AbsoluteTime.now(),
        });
      },
      (fail) => {
        switch (fail.case) {
          case HttpStatusCode.Forbidden:
            return i18n.str`Access denied trying to test balance.`;
          case HttpStatusCode.UnavailableForLegalReasons:
            setKycAccount(fail.body.h_payto);
            return i18n.str`Unavailable For Legal Reasons`;
          default:
            assertUnreachable(fail);
        }
      },
    );
  }

  const sendFormValue =
    theForm === undefined || status.status === "fail"
      ? undefined
      : triggerAmount(status.result.amount);

  if (kycAccount) {
    return <div>loading...</div>;
  }

  return (
    <div class="rounded-lg bg-white px-5 py-6 shadow m-4">
      <LocalNotificationBanner notification={notification} />
      <div class="space-y-10 divide-y -mt-5 divide-gray-900/10">
        <FormUI model={handler} design={design} />
      </div>

      <div class="mt-6 flex items-center justify-end gap-x-6">
        <button
          onClick={() => {}}
          class="text-sm font-semibold leading-6 text-gray-900"
        >
          <i18n.Translate>Cancel</i18n.Translate>
        </button>
        <Button
          type="submit"
          handler={sendFormValue}
          // disabled={!submitHandler}
          class="disabled:opacity-50 disabled:cursor-default 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>Submit</i18n.Translate>
        </Button>
      </div>

      <div class="grid grid-cols-1 gap-x-8 gap-y-4 ">
        <p>
          <i18n.Translate>
            This actions will trigger wallet balance kyc above 1000000
            threshold, the exchange should be properly configured to trigger the
            desired kyc flow.
          </i18n.Translate>
        </p>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000000`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger TOPS Terms of service</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000010`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger GLS onboarding</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000020`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.1</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000030`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.4</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000040`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.5</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000050`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.9</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000060`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.11</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000070`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.12</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000080`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.13</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000090`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.14</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000100`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.15</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000110`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Challenger test</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000120`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.9 customer</i18n.Translate>
          </Button>
        </div>
        <div>
          <Button
            type="submit"
            handler={triggerAmount(
              Amounts.parseOrThrow(`${config.config.currency}:1000130`),
            )}
            // disabled={!submitHandler}
            class="disabled:opacity-50 disabled:cursor-default 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>Trigger VQF 902.9 officer</i18n.Translate>
          </Button>
        </div>
      </div>
    </div>
  );
}
