/*
 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,
  PreparePayResult,
  PreparePayResultType,
  TranslatedString,
} from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Amount } from "./Amount.js";
import { Part } from "./Part.js";
import { QR } from "./QR.js";
import { LinkSuccess, WarningBox } from "./styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
import { ButtonHandler } from "../mui/handlers.js";
import { assertUnreachable } from "../utils/index.js";

interface Props {
  payStatus: PreparePayResult;
  payHandler: ButtonHandler | undefined;
  balance: AmountJson | undefined;
  uri: string;
  amount: AmountJson;
  goToWalletManualWithdraw: (currency: string) => Promise<void>;
}

export function PaymentButtons({
  payStatus,
  uri,
  payHandler,
  balance,
  amount,
  goToWalletManualWithdraw,
}: Props): VNode {
  const { i18n } = useTranslationContext();
  if (payStatus.status === PreparePayResultType.PaymentPossible) {
    const privateUri = `${uri}&n=${payStatus.noncePriv}`;

    return (
      <Fragment>
        <section>
          <Button
            variant="contained"
            color="success"
            onClick={payHandler?.onClick}
          >
            <i18n.Translate>
              Pay &nbsp;
              {<Amount value={amount} />}
            </i18n.Translate>
          </Button>
        </section>
        <PayWithMobile uri={privateUri} />
      </Fragment>
    );
  }

  if (payStatus.status === PreparePayResultType.InsufficientBalance) {
    let BalanceMessage = "";
    if (!balance) {
      BalanceMessage = i18n.str`You have no balance for this currency. Withdraw digital cash first.`;
    } else {
      const balanceShouldBeEnough = Amounts.cmp(balance, amount) !== -1;
      if (balanceShouldBeEnough) {
        BalanceMessage = i18n.str`Could not find enough coins to pay. Even if you have enough ${balance.currency} some restriction may apply.`;
      } else {
        BalanceMessage = i18n.str`Your current balance is not enough.`;
      }
    }
    const uriPrivate = `${uri}&n=${payStatus.noncePriv}`;

    return (
      <Fragment>
        <section>
          <WarningBox>{BalanceMessage}</WarningBox>
        </section>
        <section>
          <Button
            variant="contained"
            color="success"
            onClick={() => goToWalletManualWithdraw(Amounts.stringify(amount))}
          >
            <i18n.Translate>Get digital cash</i18n.Translate>
          </Button>
        </section>
        <PayWithMobile uri={uriPrivate} />
      </Fragment>
    );
  }
  if (payStatus.status === PreparePayResultType.AlreadyConfirmed) {
    return (
      <Fragment>
        <section>
          {payStatus.paid && payStatus.contractTerms.fulfillment_message && (
            <Part
              title={i18n.str`Merchant message`}
              text={
                payStatus.contractTerms.fulfillment_message as TranslatedString
              }
              kind="neutral"
            />
          )}
        </section>
        {!payStatus.paid && <PayWithMobile uri={uri} />}
      </Fragment>
    );
  }

  assertUnreachable(payStatus);
}

function PayWithMobile({ uri }: { uri: string }): VNode {
  const { i18n } = useTranslationContext();

  const [showQR, setShowQR] = useState<boolean>(false);

  return (
    <section>
      <LinkSuccess upperCased onClick={() => setShowQR((qr) => !qr)}>
        {!showQR ? i18n.str`Pay with a mobile phone` : i18n.str`Hide QR`}
      </LinkSuccess>
      {showQR && (
        <div>
          <QR text={uri} />
          <i18n.Translate>
            Scan the QR code or &nbsp;
            <a href={uri}>
              <i18n.Translate>click here</i18n.Translate>
            </a>
          </i18n.Translate>
        </div>
      )}
    </section>
  );
}
