/*
 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 {
  Amounts,
  HttpStatusCode,
  TalerError,
  WithdrawUriResult,
  assertUnreachable
} from "@gnu-taler/taler-util";
import {
  Attention,
  ErrorLoading,
  Loading,
  RouteDefinition,
  notifyInfo,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";

import { Paytos, TalerUris } from "@gnu-taler/taler-util";
import { useWithdrawalDetails } from "../hooks/account.js";
import { QrCodeSection } from "./QrCodeSection.js";
import { WithdrawalConfirmationQuestion } from "./WithdrawalConfirmationQuestion.js";

const TALER_SCREEN_ID = 116;

interface Props {
  withdrawUri: WithdrawUriResult;
  origin: "from-bank-ui" | "from-wallet-ui";
  onOperationAborted: () => void;
  routeClose: RouteDefinition;
}
/**
 * Offer the QR code (and a clickable taler://-link) to
 * permit the passing of exchange and reserve details to
 * the bank.  Poll the backend until such operation is done.
 */
export function WithdrawalQRCode({
  withdrawUri,
  onOperationAborted,
  routeClose,
  origin,
}: Props): VNode {
  const { i18n } = useTranslationContext();
  const result = useWithdrawalDetails(withdrawUri.withdrawalOperationId);

  if (!result) {
    return <Loading />;
  }
  if (result instanceof TalerError) {
    return <ErrorLoading error={result} />;
  }
  if (result.type === "fail") {
    switch (result.case) {
      case HttpStatusCode.BadRequest:
      case HttpStatusCode.NotFound:
        return <OperationNotFound routeClose={routeClose} />;
      default:
        assertUnreachable(result);
    }
  }

  const { body: data } = result;

  if (data.status === "aborted") {
    return (
      <div class="relative ml-auto mr-auto transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6">
        <div>
          <div class="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-yellow-100">
            <svg
              class="h-5 w-5 text-yellow-400"
              viewBox="0 0 20 20"
              fill="currentColor"
              aria-hidden="true"
            >
              <path
                fill-rule="evenodd"
                d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z"
                clip-rule="evenodd"
              />
            </svg>
          </div>
          <div class="mt-3 text-center sm:mt-5">
            <h3
              class="text-base font-semibold leading-6 text-gray-900"
              id="modal-title"
            >
              <i18n.Translate>Operation aborted</i18n.Translate>
            </h3>
            <div class="mt-2">
              <p class="text-sm text-gray-500">
                <i18n.Translate>
                  The wire transfer to the Payment Service Provider's account
                  was aborted from somewhere else, your balance was not
                  affected.
                </i18n.Translate>
              </p>
            </div>
          </div>
        </div>
        <div class="mt-5 sm:mt-6">
          <a
            href={routeClose.url({})}
            name="continue"
            class="inline-flex w-full justify-center 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>Continue</i18n.Translate>
          </a>
        </div>
      </div>
    );
  }
  const talerWithdrawUri = TalerUris.toString(withdrawUri);

  if (data.status === "confirmed") {
    return (
      <div class="relative ml-auto mr-auto transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6">
        <div>
          <div class="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
            <svg
              class="h-6 w-6 text-green-600"
              fill="none"
              viewBox="0 0 24 24"
              stroke-width="1.5"
              stroke="currentColor"
              aria-hidden="true"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                d="M4.5 12.75l6 6 9-13.5"
              />
            </svg>
          </div>
          <div class="mt-3 text-center sm:mt-5">
            <h3
              class="text-base font-semibold leading-6 text-gray-900"
              id="modal-title"
            >
              <i18n.Translate>Withdrawal confirmed</i18n.Translate>
            </h3>
            <div class="mt-2">
              <p class="text-sm text-gray-500">
                <i18n.Translate>
                  The wire transfer to the Payment Service Provider has been
                  initiated. You will shortly receive the requested amount in
                  your Taler wallet.{" "}
                </i18n.Translate>
              </p>
            </div>
          </div>
        </div>
        <div class="mt-5 sm:mt-6 items-center justify-between gap-x-2 flex">
          <a
            href={routeClose.url({})}
            name="done"
            class="inline-flex  justify-center rounded-md bg-white-600 px-3 py-2 text-sm font-semibold text-black shadow-sm "
          >
            <i18n.Translate>Close</i18n.Translate>
          </a>
          {origin === "from-wallet-ui" && false ? (
            <a
              href={talerWithdrawUri}
              name="done"
              class="inline-flex  justify-center 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>Go to your wallet now</i18n.Translate>
            </a>
          ) : undefined}
        </div>
      </div>
    );
  }

  if (data.status === "pending") {
    return (
      <QrCodeSection
        withdrawUri={withdrawUri}
        onAborted={() => {
          notifyInfo(i18n.str`Operation aborted`);
          onOperationAborted();
        }}
      />
    );
  }

  const account = !data.selected_exchange_account
    ? undefined
    : Paytos.fromString(data.selected_exchange_account);

  if (!account || account.type === "fail") {
    if (!data.selected_reserve_pub) {
      return (
        <Attention
          type="danger"
          title={i18n.str`The operation is marked as selected, but a process during the withdrawal failed`}
        >
          <i18n.Translate>
            A withdrawal reserve ID was not found and no account has been
            selected.
          </i18n.Translate>
        </Attention>
      );
    }
    return (
      <Attention
        type="danger"
        title={i18n.str`The operation is marked as selected, but a process during the withdrawal failed`}
      >
        <i18n.Translate>
          There is a withdrawal reserve ID but no account has been selected or
          the selected account is invalid.
        </i18n.Translate>
      </Attention>
    );
  }

  if (!data.selected_reserve_pub) {
    return (
      <Attention
        type="danger"
        title={i18n.str`The operation is marked as selected, but a process during the withdrawal failed`}
      >
        <i18n.Translate>
          The account was selected, but no withdrawal reserve ID was found.
        </i18n.Translate>
      </Attention>
    );
  }

  return (
    <WithdrawalConfirmationQuestion
      withdrawUri={withdrawUri}
      details={{
        username: data.username,
        account: account.body,
        reserve: data.selected_reserve_pub,
        amount: !data.amount ? undefined : Amounts.parseOrThrow(data.amount),
      }}
    />
  );
}

export function OperationNotFound({
  routeClose,
}: {
  routeClose: RouteDefinition | undefined;
}): VNode {
  const { i18n } = useTranslationContext();
  return (
    <div class="relative ml-auto mr-auto transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6">
      <div>
        <div class="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100 ">
          <svg
            class="h-6 w-6 text-red-600"
            fill="none"
            viewBox="0 0 24 24"
            stroke-width="1.5"
            stroke="currentColor"
            aria-hidden="true"
          >
            <path
              stroke-linecap="round"
              stroke-linejoin="round"
              d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
            />
          </svg>
        </div>

        <div class="mt-3 text-center sm:mt-5">
          <h3
            class="text-base font-semibold leading-6 text-gray-900"
            id="modal-title"
          >
            <i18n.Translate>Operation not found</i18n.Translate>
          </h3>
          <div class="mt-2">
            <p class="text-sm text-gray-500">
              <i18n.Translate>
                This process is not known to the server. The process ID is
                incorrect or the server has deleted the process information
                before it arrived here.
              </i18n.Translate>
            </p>
          </div>
        </div>
      </div>
      {routeClose && (
        <div class="mt-5 sm:mt-6">
          <a
            href={routeClose.url({})}
            name="continue to dashboard"
            class="inline-flex w-full justify-center 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>Continue to dashboard</i18n.Translate>
          </a>
        </div>
      )}
    </div>
  );
}
