/*
 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,
  PaytoUri,
  PaytoUriIBAN,
  PaytoUriTalerBank,
  TranslatedString,
  WithdrawUriResult
} from "@gnu-taler/taler-util";
import {
  RequestError,
  notify,
  notifyError,
  notifyInfo,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useMemo, useState } from "preact/hooks";
import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
import { useAccessAnonAPI } from "../hooks/access.js";
import { buildRequestErrorMessage, undefinedIfEmpty } from "../utils.js";

const logger = new Logger("WithdrawalConfirmationQuestion");

interface Props {
  onAborted: () => void;
  withdrawUri: WithdrawUriResult;
  details: {
    account: PaytoUri,
    reserve: string,
    amount: AmountJson,
  }
}
/**
 * Additional authentication required to complete the operation.
 * Not providing a back button, only abort.
 */
export function WithdrawalConfirmationQuestion({
  onAborted,
  details,
  withdrawUri,
}: Props): VNode {
  const { i18n } = useTranslationContext();

  const captchaNumbers = useMemo(() => {
    return {
      a: Math.floor(Math.random() * 10),
      b: Math.floor(Math.random() * 10),
    };
  }, []);

  const { confirmWithdrawal, abortWithdrawal } = useAccessAnonAPI();
  const [captchaAnswer, setCaptchaAnswer] = useState<string | undefined>();
  const answer = parseInt(captchaAnswer ?? "", 10);
  const [busy, setBusy] = useState<Record<string, undefined>>()
  const errors = undefinedIfEmpty({
    answer: !captchaAnswer
      ? i18n.str`Answer the question before continue`
      : Number.isNaN(answer)
        ? i18n.str`The answer should be a number`
        : answer !== captchaNumbers.a + captchaNumbers.b
          ? i18n.str`The answer "${answer}" to "${captchaNumbers.a} + ${captchaNumbers.b}" is wrong.`
          : undefined,
  }) ?? busy;

  async function doTransfer() {
    try {
      setBusy({})
      await confirmWithdrawal(
        withdrawUri.withdrawalOperationId,
      );
      notifyInfo(i18n.str`Wire transfer completed!`)
    } catch (error) {
      if (error instanceof RequestError) {
        notify(
          buildRequestErrorMessage(i18n, error.cause, {
            onClientError: (status) =>
              status === HttpStatusCode.Conflict
                ? i18n.str`The withdrawal has been aborted previously and can't be confirmed`
                : status === HttpStatusCode.UnprocessableEntity
                  ? i18n.str`The withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before`
                  : undefined,
          }),
        );
      } else {
        notifyError(
          i18n.str`Operation failed, please report`,
          (error instanceof Error
            ? error.message
            : JSON.stringify(error)) as TranslatedString
        )
      }
    }
    setBusy(undefined)
  }

  async function doCancel() {
    try {
      setBusy({})
      await abortWithdrawal(withdrawUri.withdrawalOperationId);
      onAborted();
    } catch (error) {
      if (error instanceof RequestError) {
        notify(
          buildRequestErrorMessage(i18n, error.cause, {
            onClientError: (status) =>
              status === HttpStatusCode.Conflict
                ? i18n.str`The reserve operation has been confirmed previously and can't be aborted`
                : undefined,
          }),
        );
      } else {
        notifyError(
          i18n.str`Operation failed, please report`,
          (error instanceof Error
            ? error.message
            : JSON.stringify(error)) as TranslatedString
        )
      }
    }
    setBusy(undefined)
  }

  return (
    <Fragment>
      <div class="bg-white shadow sm:rounded-lg">
        <div class="px-4 py-5 sm:p-6">
          <h3 class="text-base font-semibold text-gray-900">
            <i18n.Translate>Confirm the withdrawal operation</i18n.Translate>
          </h3>
          <div class="mt-2 max-w-xl text-sm text-gray-500">
            <div class="px-4 mt-4 grid grid-cols-1 gap-y-6 sm:grid-cols-3 sm:gap-x-3">

              <label class={"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-noneborder-indigo-600 ring-2 ring-indigo-600"}>
                <input type="radio" name="project-type" value="Newsletter" class="sr-only" aria-labelledby="project-type-0-label" aria-describedby="project-type-0-description-0 project-type-0-description-1" />
                <span class="flex flex-1">
                  <span class="flex flex-col">
                    <span id="project-type-0-label" class="block text-sm font-medium text-gray-900 ">
                      <i18n.Translate>challenge response test</i18n.Translate>
                    </span>
                  </span>
                </span>
                <svg class="h-5 w-5 text-indigo-600" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
                  <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
                </svg>
              </label>


              <label class="relative flex cursor-pointer rounded-lg border bg-gray-100  p-4 shadow-sm focus:outline-none border-gray-300">
                <input type="radio" name="project-type" value="Existing Customers" class="sr-only" aria-labelledby="project-type-1-label" aria-describedby="project-type-1-description-0 project-type-1-description-1" />
                <span class="flex flex-1">
                  <span class="flex flex-col">
                    <span id="project-type-1-label" class="block text-sm font-medium text-gray-900">
                      <i18n.Translate>using SMS</i18n.Translate>
                    </span>
                    <span id="project-type-1-description-0" class="mt-1 flex items-center text-sm text-gray-500">
                      <i18n.Translate>not available</i18n.Translate>
                    </span>
                  </span>
                </span>
                <svg class="h-5 w-5 text-indigo-600 hidden" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
                  <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
                </svg>
              </label>

              <label class="relative flex cursor-pointer rounded-lg border bg-gray-100 p-4 shadow-sm focus:outline-none border-gray-300">
                <input type="radio" name="project-type" value="Existing Customers" class="sr-only" aria-labelledby="project-type-1-label" aria-describedby="project-type-1-description-0 project-type-1-description-1" />
                <span class="flex flex-1">
                  <span class="flex flex-col">
                    <span id="project-type-1-label" class="block text-sm font-medium text-gray-900">
                      <i18n.Translate>one time password</i18n.Translate>
                    </span>
                    <span id="project-type-1-description-0" class="mt-1 flex items-center text-sm text-gray-500">
                      <i18n.Translate>not available</i18n.Translate>
                    </span>
                  </span>
                </span>
                <svg class="h-5 w-5 text-indigo-600 hidden" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
                  <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
                </svg>
              </label>
            </div>
          </div>
          <div class="mt-3 text-sm leading-6">

            <div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-10 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg">
              <div class="px-4 sm:px-0">
                <h2 class="text-base font-semibold text-gray-900"><i18n.Translate>Answer the next question to authorize the wire transfer</i18n.Translate></h2>
              </div>
              <form
                class="bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2"
                autoCapitalize="none"
                autoCorrect="off"
                onSubmit={e => {
                  e.preventDefault()
                }}
              >
                <div class="px-4 py-6 sm:p-8">
                  <label for="withdraw-amount">{i18n.str`What is`}&nbsp;
                    <em>
                      {captchaNumbers.a}&nbsp;+&nbsp;{captchaNumbers.b}
                    </em>
                    ?
                  </label>
                  <div class="mt-2">
                    <div class="relative rounded-md shadow-sm">
                      <input
                        type="text"
                        // class="block w-full rounded-md border-0 py-1.5 pl-16 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
                        aria-describedby="answer"
                        autoFocus
                        class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
                        value={captchaAnswer ?? ""}
                        required

                        name="answer"
                        id="answer"
                        autocomplete="off"
                        onChange={(e): void => {
                          setCaptchaAnswer(e.currentTarget.value)
                        }}
                      />
                    </div>
                    <ShowInputErrorLabel message={errors?.answer} isDirty={captchaAnswer !== undefined} />
                  </div>
                </div>
                <div class="flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8">
                  <button type="button" class="text-sm font-semibold leading-6 text-gray-900"
                    onClick={doCancel}
                  >
                    <i18n.Translate>Cancel</i18n.Translate></button>
                  <button type="submit"
                    class="disabled:opacity-50 disabled:cursor-default cursor-pointer 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"
                    disabled={!!errors}
                    onClick={(e) => {
                      e.preventDefault()
                      doTransfer()
                    }}
                  >
                    <i18n.Translate>Transfer</i18n.Translate>
                  </button>
                </div>

              </form>
            </div>
          </div>
          <div class="px-4 mt-4 ">
            <div class="w-full">
              <div class="px-4 sm:px-0 text-sm">
                <p><i18n.Translate>Wire transfer details</i18n.Translate></p>
              </div>
              <div class="mt-6 border-t border-gray-100">
                <dl class="divide-y divide-gray-100">
                  {((): VNode => {
                    switch (details.account.targetType) {
                      case "iban": {
                        const p = details.account as PaytoUriIBAN
                        const name = p.params["receiver-name"]
                        return <Fragment>
                          <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
                            <dt class="text-sm font-medium leading-6 text-gray-900">Exchange account</dt>
                            <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">{p.iban}</dd>
                          </div>
                          {name &&
                            <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
                              <dt class="text-sm font-medium leading-6 text-gray-900">Exchange name</dt>
                              <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">{p.params["receiver-name"]}</dd>
                            </div>
                          }
                        </Fragment>
                      }
                      case "x-taler-bank": {
                        const p = details.account as PaytoUriTalerBank
                        const name = p.params["receiver-name"]
                        return <Fragment>
                          <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
                            <dt class="text-sm font-medium leading-6 text-gray-900">Exchange account</dt>
                            <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">{p.account}</dd>
                          </div>
                          {name &&
                            <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
                              <dt class="text-sm font-medium leading-6 text-gray-900">Exchange name</dt>
                              <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">{p.params["receiver-name"]}</dd>
                            </div>
                          }
                        </Fragment>
                      }
                      default:
                        return <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
                          <dt class="text-sm font-medium leading-6 text-gray-900">Exchange account</dt>
                          <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">{details.account.targetPath}</dd>
                        </div>

                    }
                  })()}
                  <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
                    <dt class="text-sm font-medium leading-6 text-gray-900">Withdrawal identification</dt>
                    <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0 break-words">{details.reserve}</dd>
                  </div>
                  <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
                    <dt class="text-sm font-medium leading-6 text-gray-900">Amount</dt>
                    <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">To be added</dd>
                    {/* Amounts.stringifyValue(details.amount) */}
                  </div>
                </dl>
              </div>
            </div>

          </div>
        </div>
      </div>

    </Fragment>
  );
}
