import { TalerCorebankApi, TalerError, TranslatedString } from "@gnu-taler/taler-util";
import { notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { ErrorLoading } from "@gnu-taler/web-util/browser";
import { Loading } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../context/config.js";
import { useAccountDetails } from "../hooks/access.js";
import { useBackendState } from "../hooks/backend.js";
import { undefinedIfEmpty, withRuntimeErrorHandling } from "../utils.js";
import { LoginForm } from "./LoginForm.js";
import { ProfileNavigation } from "./ProfileNavigation.js";
import { assertUnreachable } from "./WithdrawalOperationPage.js";
import { AccountForm } from "./admin/AccountForm.js";
import { ShowLocalNotification } from "@gnu-taler/web-util/browser";

export function ShowAccountDetails({
  account,
  onClear,
  onUpdateSuccess,
}: {
  onClear?: () => void;
  onUpdateSuccess: () => void;
  account: string;
}): VNode {
  const { i18n } = useTranslationContext();
  const { state: credentials } = useBackendState();
  const creds = credentials.status !== "loggedIn" ? undefined : credentials
  const { api } = useBankCoreApiContext()
  const accountIsTheCurrentUser = credentials.status === "loggedIn" ?
    credentials.username === account : false

  const [update, setUpdate] = useState(false);
  const [submitAccount, setSubmitAccount] = useState<TalerCorebankApi.AccountData | undefined>();
  const [notification, notify, handleError] = useLocalNotification()

  const result = useAccountDetails(account);
  if (!result) {
    return <Loading />
  }
  if (result instanceof TalerError) {
    return <ErrorLoading error={result} />
  }
  if (result.type === "fail") {
    switch (result.case) {
      case "not-found": return <LoginForm reason="not-found" />
      case "unauthorized": return <LoginForm reason="forbidden" />
      default: assertUnreachable(result)
    }
  }

  async function doUpdate() {
    if (!update || !submitAccount || !creds) return;
    await handleError(async () => {
      const resp = await api.updateAccount(creds, {
        cashout_address: submitAccount.cashout_payto_uri,
        challenge_contact_data: undefinedIfEmpty({
          email: submitAccount.contact_data?.email,
          phone: submitAccount.contact_data?.phone,
        }),
        is_exchange: false,
        name: submitAccount.name,
      });

      if (resp.type === "ok") {
        notifyInfo(i18n.str`Account updated`);
        onUpdateSuccess();
      } else {
        switch (resp.case) {
          case "unauthorized": return notify({
            type: "error",
            title: i18n.str`The rights to change the account are not sufficient`,
            description: resp.detail.hint as TranslatedString,
            debug: resp.detail,
          })
          case "not-found": return notify({
            type: "error",
            title: i18n.str`The username was not found`,
            description: resp.detail.hint as TranslatedString,
            debug: resp.detail,
          })
          case "cant-change-legal-name-or-admin": return notify({
            type: "error",
            title: i18n.str`Can't change legal name`,
            description: resp.detail.hint as TranslatedString,
            debug: resp.detail,
          })
          default: assertUnreachable(resp)
        }
      }
    })

  }

  return (
    <Fragment>
      <ShowLocalNotification notification={notification} />
      {accountIsTheCurrentUser ?
        <ProfileNavigation current="details" />
        :
        <h1 class="text-base font-semibold leading-6 text-gray-900">
          <i18n.Translate>Account "{account}"</i18n.Translate>
        </h1>

      }

      <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">
            <div class="flex items-center justify-between">
              <span class="flex flex-grow flex-col">
                <span class="text-sm text-black font-semibold leading-6 " id="availability-label">
                  <i18n.Translate>Change details</i18n.Translate>
                </span>
              </span>
              <button type="button" data-enabled={!update} class="bg-indigo-600 data-[enabled=true]:bg-gray-200 relative inline-flex h-5 w-10 flex-shrink-0 cursor-pointer rounded-full ring-2 border-gray-600 transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description"
                onClick={() => {
                  setUpdate(!update)
                }}>
                <span aria-hidden="true" data-enabled={!update} class="translate-x-5 data-[enabled=true]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
              </button>
            </div>
          </h2>
        </div>

        <AccountForm
          focus={update}
          username={account}
          template={result.body}
          purpose={update ? "update" : "show"}
          onChange={(a) => setSubmitAccount(a)}
        >
          <div class="flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8">
            {onClear ?
              <button type="button" class="text-sm font-semibold leading-6 text-gray-900"
                onClick={onClear}
              >
                <i18n.Translate>Cancel</i18n.Translate>
              </button>
              : <div />
            }
            <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={!update || !submitAccount}
              onClick={doUpdate}
            >
              <i18n.Translate>Update</i18n.Translate>
            </button>
          </div>
        </AccountForm>
      </div>
    </Fragment>
  );
}

