/*
 This file is part of GNU Taler
 (C) 2022 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 {
  AmountJson,
  Amounts,
  HttpStatusCode,
  Logger,
} from "@gnu-taler/taler-util";
import {
  RequestError,
  useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useEffect, useRef, useState } from "preact/hooks";
import { PageStateType } from "../context/pageState.js";
import { useAccessAPI } from "../hooks/access.js";
import { buildRequestErrorMessage, undefinedIfEmpty } from "../utils.js";
import { ShowInputErrorLabel } from "./ShowInputErrorLabel.js";

const logger = new Logger("WalletWithdrawForm");

export function WalletWithdrawForm({
  focus,
  limit,
  onError,
  onSuccess,
}: {
  limit: AmountJson;
  focus?: boolean;
  onError: (e: PageStateType["error"]) => void;
  onSuccess: (
    data: SandboxBackend.Access.BankAccountCreateWithdrawalResponse,
  ) => void;
}): VNode {
  // const backend = useBackendContext();
  // const { pageState, pageStateSetter } = usePageContext();
  const { i18n } = useTranslationContext();
  const { createWithdrawal } = useAccessAPI();

  const [amountStr, setAmountStr] = useState<string | undefined>("5.00");
  const ref = useRef<HTMLInputElement>(null);
  useEffect(() => {
    if (focus) ref.current?.focus();
  }, [focus]);

  const trimmedAmountStr = amountStr?.trim();

  const parsedAmount = trimmedAmountStr
    ? Amounts.parse(`${limit.currency}:${trimmedAmountStr}`)
    : undefined;

  const errors = undefinedIfEmpty({
    amount:
      trimmedAmountStr == null
        ? i18n.str`required`
        : !parsedAmount
        ? i18n.str`invalid`
        : Amounts.cmp(limit, parsedAmount) === -1
        ? i18n.str`balance is not enough`
        : undefined,
  });
  return (
    <form
      id="reserve-form"
      class="pure-form"
      name="tform"
      onSubmit={(e) => {
        e.preventDefault();
      }}
      autoCapitalize="none"
      autoCorrect="off"
    >
      <p>
        <label for="withdraw-amount">{i18n.str`Amount to withdraw:`}</label>
        &nbsp;
        <div style={{ width: "max-content" }}>
          <input
            type="text"
            readonly
            class="currency-indicator"
            size={limit.currency.length}
            maxLength={limit.currency.length}
            tabIndex={-1}
            value={limit.currency}
          />
          &nbsp;
          <input
            type="number"
            ref={ref}
            id="withdraw-amount"
            name="withdraw-amount"
            value={amountStr ?? ""}
            onChange={(e): void => {
              setAmountStr(e.currentTarget.value);
            }}
          />
          <ShowInputErrorLabel
            message={errors?.amount}
            isDirty={amountStr !== undefined}
          />
        </div>
      </p>
      <p>
        <div>
          <input
            id="select-exchange"
            class="pure-button pure-button-primary"
            type="submit"
            disabled={!!errors}
            value={i18n.str`Withdraw`}
            onClick={async (e) => {
              e.preventDefault();
              if (!parsedAmount) return;
              try {
                const result = await createWithdrawal({
                  amount: Amounts.stringify(parsedAmount),
                });
                onSuccess(result.data);
              } catch (error) {
                if (error instanceof RequestError) {
                  onError(
                    buildRequestErrorMessage(i18n, error.cause, {
                      onClientError: (status) =>
                        status === HttpStatusCode.Forbidden
                          ? i18n.str`The operation was rejected due to insufficient funds`
                          : undefined,
                    }),
                  );
                } else {
                  onError({
                    title: i18n.str`Operation failed, please report`,
                    description:
                      error instanceof Error
                        ? error.message
                        : JSON.stringify(error),
                  });
                }
              }
            }}
          />
        </div>
      </p>
    </form>
  );
}
