import { Amounts, HttpStatusCode, TalerError, TalerErrorCode, TranslatedString } from "@gnu-taler/taler-util";
import { Attention, Loading, LocalNotificationBanner, ShowInputErrorLabel, notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { ErrorLoadingWithDebug } from "../../components/ErrorLoadingWithDebug.js";
import { useBankCoreApiContext } from "../../context/config.js";
import { useAccountDetails } from "../../hooks/access.js";
import { useBackendState } from "../../hooks/backend.js";
import { undefinedIfEmpty } from "../../utils.js";
import { LoginForm } from "../LoginForm.js";
import { doAutoFocus } from "../PaytoWireTransferForm.js";
import { assertUnreachable } from "../WithdrawalOperationPage.js";

export function RemoveAccount({
  account,
  onCancel,
  onUpdateSuccess,
  focus,
}: {
  focus?: boolean;
  onCancel: () => void;
  onUpdateSuccess: () => void;
  account: string;
}): VNode {
  const { i18n } = useTranslationContext();
  const result = useAccountDetails(account);
  const [accountName, setAccountName] = useState<string | undefined>()

  const { state } = useBackendState();
  const token = state.status !== "loggedIn" ? undefined : state.token
  const { api } = useBankCoreApiContext()
  const [notification, notify, handleError] = useLocalNotification()

  if (!result) {
    return <Loading />
  }
  if (result instanceof TalerError) {
    return <ErrorLoadingWithDebug error={result} />
  }
  if (result.type === "fail") {
    switch (result.case) {
      case HttpStatusCode.Unauthorized: return <LoginForm currentUser={account} />
      case HttpStatusCode.NotFound: return <LoginForm currentUser={account} />
      default: assertUnreachable(result)
    }
  }

  const balance = Amounts.parse(result.body.balance.amount);
  if (!balance) {
    return <div>there was an error reading the balance</div>;
  }
  const isBalanceEmpty = Amounts.isZero(balance);
  if (!isBalanceEmpty) {
    return <Attention type="warning" title={i18n.str`Can't delete the account`} onClose={onCancel}>
      <i18n.Translate>The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.</i18n.Translate>
    </Attention>
  }

  async function doRemove() {
    if (!token) return;
    await handleError(async () => {
      const resp = await api.deleteAccount({ username: account, token });
      if (resp.type === "ok") {
        notifyInfo(i18n.str`Account removed`);
        onUpdateSuccess();
      } else {
        switch (resp.case) {
          case HttpStatusCode.Unauthorized: return notify({
            type: "error",
            title: i18n.str`No enough permission to delete the account.`,
            description: resp.detail.hint as TranslatedString,
            debug: resp.detail,
          })
          case HttpStatusCode.NotFound: return notify({
            type: "error",
            title: i18n.str`The username was not found.`,
            description: resp.detail.hint as TranslatedString,
            debug: resp.detail,
          })
          case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: return notify({
            type: "error",
            title: i18n.str`Can't delete a reserved username.`,
            description: resp.detail.hint as TranslatedString,
            debug: resp.detail,
          })
          case TalerErrorCode.BANK_ACCOUNT_BALANCE_NOT_ZERO: return notify({
            type: "error",
            title: i18n.str`Can't delete an account with balance different than zero.`,
            description: resp.detail.hint as TranslatedString,
            debug: resp.detail,
          })
          default: {
            assertUnreachable(resp)
          }
        }
      }
    })
  }

  const errors = undefinedIfEmpty({
    accountName: !accountName
      ? i18n.str`required`
      : account !== accountName
        ? i18n.str`name doesn't match`
        : undefined,
  });


  return (
    <div>
      <LocalNotificationBanner notification={notification} />

      <Attention type="warning" title={i18n.str`You are going to remove the account`}>
        <i18n.Translate>This step can't be undone.</i18n.Translate>
      </Attention>

      <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 leading-7 text-gray-900">
            <i18n.Translate>Deleting account "{account}"</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">
            <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">

              <div class="sm:col-span-5">
                <label
                  class="block text-sm font-medium leading-6 text-gray-900"
                  for="password"
                >
                  {i18n.str`Verification`}
                </label>
                <div class="mt-2">
                  <input
                    ref={focus ? doAutoFocus : undefined}
                    type="text"
                    class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
                    name="password"
                    id="password"
                    data-error={!!errors?.accountName && accountName !== undefined}
                    value={accountName ?? ""}
                    onChange={(e) => {
                      setAccountName(e.currentTarget.value)
                    }}
                    placeholder={account}
                    autocomplete="off"
                  />
                  <ShowInputErrorLabel
                    message={errors?.accountName}
                    isDirty={accountName !== undefined}
                  />
                </div>
                <p class="mt-2 text-sm text-gray-500" >
                  <i18n.Translate>enter the account name that is going to be deleted</i18n.Translate>
                </p>
              </div>



            </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">
            {onCancel ?
              <button type="button" class="text-sm font-semibold leading-6 text-gray-900"
                onClick={onCancel}
              >
                <i18n.Translate>Cancel</i18n.Translate>
              </button>
              : <div />
            }
            <button type="submit"
              class="disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600"
              disabled={!!errors}
              onClick={(e) => {
                e.preventDefault()
                doRemove()
              }}
            >
              <i18n.Translate>Delete</i18n.Translate>
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}
