/*
 This file is part of GNU Taler
 (C) 2021-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/>
 */

/**
 *
 * @author Sebastian Javier Marchano (sebasjm)
 */

import {
  AbsoluteTime,
  AmountJson,
  Amounts,
  HostPortPath,
  MerchantContractVersion,
  TalerMerchantApi,
  assertUnreachable,
  stringifyRefundUri,
} from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { format, formatDistance } from "date-fns";
import { Fragment, VNode, h } from "preact";
import { useEffect, useState } from "preact/hooks";
import { FormProvider } from "../../../../components/form/FormProvider.js";
import { Input } from "../../../../components/form/Input.js";
import { InputCurrency } from "../../../../components/form/InputCurrency.js";
import { InputDate } from "../../../../components/form/InputDate.js";
import { InputDuration } from "../../../../components/form/InputDuration.js";
import { InputGroup } from "../../../../components/form/InputGroup.js";
import { InputLocation } from "../../../../components/form/InputLocation.js";
import { TextField } from "../../../../components/form/TextField.js";
import { ProductList } from "../../../../components/product/ProductList.js";
import { useSessionContext } from "../../../../context/session.js";
import { useWaitForOrderPayment } from "../../../../hooks/order.js";
import {
  datetimeFormatForSettings,
  usePreference,
} from "../../../../hooks/preference.js";
import { mergeRefunds } from "../../../../utils/amount.js";
import { RefundModal } from "../list/Table.js";
import { Event, Timeline } from "./Timeline.js";
import { NotificationCard } from "../../../../components/menu/index.js";

const TALER_SCREEN_ID = 44;

type Entity = TalerMerchantApi.MerchantOrderStatusResponse;
type CT = TalerMerchantApi.MerchantContractTerms;
type CT0 = TalerMerchantApi.MerchantContractTermsV0;
type CT1 = TalerMerchantApi.MerchantContractTermsV1;

export interface Props {
  onBack: () => void;
  selected: Entity;
  id: string;
  onRefunded: () => void;
}

type Paid = TalerMerchantApi.CheckPaymentPaidResponse & {
  refund_taken: string;
};
type Unpaid = TalerMerchantApi.CheckPaymentUnpaidResponse;
type Claimed = TalerMerchantApi.CheckPaymentClaimedResponse;

function ContractTerms({ value }: { value: CT }) {
  if (value.version === undefined) {
    return <ContractTerms_V0 value={value} />;
  }
  switch (value.version) {
    case MerchantContractVersion.V0:
      return <ContractTerms_V0 value={value} />;
    case MerchantContractVersion.V1:
      return <ContractTerms_V1 value={value} />;
    default:
      assertUnreachable(value.version);
  }
}

function ContractTerms_V0({ value }: { value: CT0 }) {
  const { i18n } = useTranslationContext();

  return (
    <InputGroup name="contract_terms" label={i18n.str`Contract terms`}>
      <FormProvider<CT0> object={value} valueHandler={null}>
        <Input<CT0>
          readonly
          name="summary"
          label={i18n.str`Summary`}
          tooltip={i18n.str`Human-readable description of the whole purchase`}
        />
        <InputCurrency<CT0>
          readonly
          name="amount"
          label={i18n.str`Amount`}
          tooltip={i18n.str`Total price for the transaction`}
        />
        {value.fulfillment_url && (
          <Input<CT0>
            readonly
            name="fulfillment_url"
            label={i18n.str`Fulfillment URL`}
            tooltip={i18n.str`URL for this purchase`}
          />
        )}
        <Input<CT0>
          readonly
          name="max_fee"
          label={i18n.str`Max fee`}
          tooltip={i18n.str`Maximum total deposit fee accepted by the merchant for this contract`}
        />
        <InputDate<CT0>
          readonly
          name="timestamp"
          label={i18n.str`Created at`}
          tooltip={i18n.str`Time when this contract was generated`}
        />
        <InputDate<CT0>
          readonly
          name="refund_deadline"
          label={i18n.str`Refund deadline`}
          tooltip={i18n.str`After this deadline has passed, no refunds will be accepted.`}
        />
        <InputDate<CT0>
          readonly
          name="pay_deadline"
          label={i18n.str`Payment deadline`}
          tooltip={i18n.str`After this deadline, the merchant won't accept payments for the contract`}
        />
        <InputDate<CT0>
          readonly
          name="wire_transfer_deadline"
          label={i18n.str`Wire transfer deadline`}
          tooltip={i18n.str`Transfer deadline for the exchange`}
        />
        <InputDate<CT0>
          readonly
          name="delivery_date"
          label={i18n.str`Delivery date`}
          tooltip={i18n.str`Time indicating when the order should be delivered`}
        />
        <InputGroup
          name="delivery_location"
          label={i18n.str`Delivery location`}
          tooltip={i18n.str`Where the order will be delivered`}
        >
          <InputLocation name="delivery_location" />
        </InputGroup>
        <InputDuration<CT0>
          readonly
          name="auto_refund"
          label={i18n.str`Auto-refund delay`}
          tooltip={i18n.str`How long the wallet should try to get an automatic refund for the purchase`}
        />
        <Input<CT0>
          readonly
          name="extra"
          label={i18n.str`Extra info`}
          tooltip={i18n.str`Extra data that is only interpreted by the merchant frontend`}
        />
      </FormProvider>
    </InputGroup>
  );
}

function ContractTerms_V1({ value }: { value: CT1 }) {
  const { i18n } = useTranslationContext();

  return (
    <InputGroup name="contract_terms" label={i18n.str`Contract terms`}>
      <FormProvider<CT1> object={value} valueHandler={null}>
        <Input<CT1>
          readonly
          name="summary"
          label={i18n.str`Summary`}
          tooltip={i18n.str`Human-readable description of the whole purchase`}
        />
        {/* <InputCurrency<CT1>
          readonly
          name="amount"
          label={i18n.str`Amount`}
          tooltip={i18n.str`Total price for the transaction`}
        />
        <Input<CT1>
          readonly
          name="max_fee"
          label={i18n.str`Max fee`}
          tooltip={i18n.str`Maximum total deposit fee accepted by the merchant for this contract`}
        /> */}
        {value.fulfillment_url && (
          <Input<CT1>
            readonly
            name="fulfillment_url"
            label={i18n.str`Fulfillment URL`}
            tooltip={i18n.str`URL for this purchase`}
          />
        )}
        <InputDate<CT1>
          readonly
          name="timestamp"
          label={i18n.str`Created at`}
          tooltip={i18n.str`Time when this contract was generated`}
        />
        <InputDate<CT1>
          readonly
          name="refund_deadline"
          label={i18n.str`Refund deadline`}
          tooltip={i18n.str`After this deadline has passed, no refunds will be accepted.`}
        />
        <InputDate<CT1>
          readonly
          name="pay_deadline"
          label={i18n.str`Payment deadline`}
          tooltip={i18n.str`After this deadline, the merchant won't accept payments for the contract`}
        />
        <InputDate<CT1>
          readonly
          name="wire_transfer_deadline"
          label={i18n.str`Wire transfer deadline`}
          tooltip={i18n.str`Transfer deadline for the exchange`}
        />
        <InputDate<CT1>
          readonly
          name="delivery_date"
          label={i18n.str`Delivery date`}
          tooltip={i18n.str`Time indicating when the order should be delivered`}
        />
        <InputGroup
          name="delivery_location"
          label={i18n.str`Delivery location`}
          tooltip={i18n.str`Where the order will be delivered`}
        >
          <InputLocation name="delivery_location" />
        </InputGroup>
        <InputDuration<CT1>
          readonly
          name="auto_refund"
          label={i18n.str`Auto-refund delay`}
          tooltip={i18n.str`How long the wallet should try to get an automatic refund for the purchase`}
        />
        <Input<CT1>
          readonly
          name="extra"
          label={i18n.str`Extra info`}
          tooltip={i18n.str`Extra data that is only interpreted by the merchant frontend`}
        />
      </FormProvider>
    </InputGroup>
  );
}

function ClaimedPage({
  id,
  order,
}: {
  id: string;
  order: TalerMerchantApi.CheckPaymentClaimedResponse;
}) {
  const { i18n } = useTranslationContext();
  const [value, valueHandler] = useState<Partial<Claimed>>(order);
  const [settings] = usePreference();
  useWaitForOrderPayment(id, order);
  const now = new Date();
  const refundable =
    order.contract_terms.refund_deadline.t_s !== "never" &&
    now.getTime() < order.contract_terms.refund_deadline.t_s * 1000;
  const events: Event[] = [];
  if (order.contract_terms.timestamp.t_s !== "never") {
    events.push({
      when: new Date(order.contract_terms.timestamp.t_s * 1000),
      description: i18n.str`order created`,
      type: "start",
    });
  }
  if (order.contract_terms.pay_deadline.t_s !== "never") {
    events.push({
      when: new Date(order.contract_terms.pay_deadline.t_s * 1000),
      description: i18n.str`pay deadline`,
      type: "pay-deadline",
    });
  }
  if (order.contract_terms.refund_deadline.t_s !== "never" && refundable) {
    events.push({
      when: new Date(order.contract_terms.refund_deadline.t_s * 1000),
      description: i18n.str`refund deadline`,
      type: "refund-deadline",
    });
  }
  if (
    order.contract_terms.delivery_date &&
    order.contract_terms.delivery_date.t_s !== "never"
  ) {
    events.push({
      when: new Date(order.contract_terms.delivery_date?.t_s * 1000),
      description: i18n.str`delivery`,
      type: "delivery",
    });
  }

  return (
    <div>
      <section class="section">
        <div class="columns">
          <div class="column" />
          <div class="column is-10">
            <section class="hero is-hero-bar">
              <div class="hero-body">
                <div class="level">
                  <div class="level-left">
                    <div class="level-item">
                      <i18n.Translate>Order</i18n.Translate> #{id}
                      <div class="tag is-info ml-4">
                        <i18n.Translate>Claimed</i18n.Translate>
                      </div>
                    </div>
                  </div>
                </div>

                {/* {order.contract_terms.version} */}
                {/* <div class="level">
                  <div class="level-left">
                    <div class="level-item">
                      <h1 class="title">{order.contract_terms.amount}</h1>
                    </div>
                  </div>
                </div> */}

                <div class="level">
                  <div class="level-left" style={{ maxWidth: "100%" }}>
                    <div class="level-item" style={{ maxWidth: "100%" }}>
                      <div
                        class="content"
                        style={{
                          whiteSpace: "nowrap",
                          overflow: "hidden",
                          textOverflow: "ellipsis",
                        }}
                      >
                        <p>
                          <b>
                            <i18n.Translate>Claimed at</i18n.Translate>:
                          </b>{" "}
                          {order.contract_terms.timestamp.t_s === "never"
                            ? i18n.str`Never`
                            : format(
                                new Date(
                                  order.contract_terms.timestamp.t_s * 1000,
                                ),
                                datetimeFormatForSettings(settings),
                              )}
                        </p>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </section>

            <section class="section">
              <div class="columns">
                <div class="column is-4">
                  <div class="title">
                    <i18n.Translate>Timeline</i18n.Translate>
                  </div>
                  <Timeline events={events} />
                </div>
                <div class="column is-8">
                  <div class="title">
                    <i18n.Translate>Payment details</i18n.Translate>
                  </div>
                  <FormProvider<Claimed>
                    object={value}
                    valueHandler={valueHandler}
                  >
                    <Input
                      name="contract_terms.summary"
                      readonly
                      inputType="multiline"
                      label={i18n.str`Summary`}
                    />
                    <InputCurrency
                      name="contract_terms.amount"
                      readonly
                      label={i18n.str`Amount`}
                    />
                    <Input<Paid>
                      name="order_status"
                      readonly
                      label={i18n.str`Order status`}
                      toStr={(d) => {
                        switch (d) {
                          case "paid":
                            return i18n.str`Paid`;
                          case "claimed":
                            return i18n.str`Claimed`;
                          case "unpiad":
                            return i18n.str`Unpaid`;
                        }
                        return d;
                      }}
                    />
                  </FormProvider>
                </div>
              </div>
            </section>

            {order.contract_terms.products?.length ? (
              <Fragment>
                <div class="title">
                  <i18n.Translate>Product list</i18n.Translate>
                </div>
                <ProductList list={order.contract_terms.products} />
              </Fragment>
            ) : undefined}

            {!value.contract_terms ? undefined : (
              <ContractTerms value={value.contract_terms} />
            )}
          </div>
          <div class="column" />
        </div>
      </section>
    </div>
  );
}
function PaidPage({
  id,
  order,
  onRefund,
}: {
  id: string;
  order: TalerMerchantApi.CheckPaymentPaidResponse;
  onRefund: (id: string) => void;
}) {
  const [value, valueHandler] = useState<Partial<Paid>>(order);
  const { state } = useSessionContext();
  const { i18n } = useTranslationContext();

  const now = new Date();
  const merchantCanRefund =
    order.contract_terms.refund_deadline.t_s !== "never" &&
    now.getTime() < order.contract_terms.refund_deadline.t_s * 1000;

  const wireDeadlineInThePast =
    order.contract_terms.wire_transfer_deadline.t_s !== "never" &&
    order.contract_terms.wire_transfer_deadline.t_s * 1000 < now.getTime();
  const [_, reload] = useState(false);
  useEffect(() => {
    if (wireDeadlineInThePast) return;
    const deadline = order.contract_terms.wire_transfer_deadline;
    if (deadline.t_s === "never") return;
    const diff = deadline.t_s * 1000 - new Date().getTime();
    setTimeout(() => {
      reload(true);
    }, diff + 100);
  }, []);

  const events: Event[] = [];
  if (
    order.contract_terms.refund_deadline.t_s !== "never" &&
    merchantCanRefund
  ) {
    events.push({
      when: new Date(order.contract_terms.refund_deadline.t_s * 1000),
      description: i18n.str`refund deadline`,
      type: "refund-deadline",
    });
  }
  if (
    order.contract_terms.delivery_date &&
    order.contract_terms.delivery_date.t_s !== "never"
  ) {
    if (order.contract_terms.delivery_date)
      events.push({
        when: new Date(order.contract_terms.delivery_date?.t_s * 1000),
        description: i18n.str`delivery`,
        type: "delivery",
      });
  }

  const sortedOrders = [...order.refund_details].sort((a, b) =>
    AbsoluteTime.cmp(
      AbsoluteTime.fromProtocolTimestamp(a.timestamp),
      AbsoluteTime.fromProtocolTimestamp(b.timestamp),
    ),
  );
  sortedOrders.reduce(mergeRefunds, []).forEach((e) => {
    if (e.timestamp.t_s === "never") return;
    if (e.pending) {
      if (wireDeadlineInThePast) {
        events.push({
          when: new Date(e.timestamp.t_s * 1000),
          description: !e.reason
            ? i18n.str`refund missed: ${e.amount}`
            : i18n.str`refund missed: ${e.amount}: ${e.reason}`,
          type: "refund-missed",
        });
      } else {
        events.push({
          when: new Date(e.timestamp.t_s * 1000),
          description: !e.reason
            ? i18n.str`refund created: ${e.amount}`
            : i18n.str`refund created: ${e.amount}: ${e.reason}`,
          type: "refund-created",
        });
      }
    } else {
      events.push({
        when: new Date(e.timestamp.t_s * 1000),
        description: !e.reason
          ? i18n.str`refund taken: ${e.amount}`
          : i18n.str`refund taken: ${e.amount}: ${e.reason}`,
        type: "refund-taken",
      });
    }
  });

  const orderAmounts = getOrderAmountAndWirefee(order);
  if (orderAmounts === "v1-without-index") {
    return (
      <i18n.Translate>
        The contract terms has a v1 order without choices_index.
      </i18n.Translate>
    );
  }
  if (orderAmounts === "v1-wrong-index") {
    return (
      <i18n.Translate>
        The contract terms has a v1 order with a bad choices_index.
      </i18n.Translate>
    );
  }
  const { amount } = orderAmounts;

  const wireMap: Record<
    string,
    {
      time: number;
      amount: AmountJson;
      confirmed: boolean;
    }
  > = {};

  let hasUnconfirmedWireTransfer = false;
  if (order.wire_details.length) {
    order.wire_details.forEach((w) => {
      if (!wireMap[w.wtid]) {
        const info = {
          time:
            w.execution_time.t_s === "never" ? 0 : w.execution_time.t_s * 1000,
          amount: Amounts.parseOrThrow(w.amount),
          confirmed: w.confirmed,
        };
        wireMap[w.wtid] = info;
      } else {
        const info = {
          time: wireMap[w.wtid].time, // keep the first time
          confirmed: wireMap[w.wtid].confirmed && w.confirmed, // both should be confirmed
          amount: Amounts.add(
            Amounts.parseOrThrow(w.amount),
            wireMap[w.wtid].amount,
          ).amount,
        };
        wireMap[w.wtid] = info;
      }
      hasUnconfirmedWireTransfer = hasUnconfirmedWireTransfer || !w.confirmed;
    });
    Object.values(wireMap).forEach((info) => {
      events.push({
        when: new Date(info.time),
        description: i18n.str`wired ${Amounts.stringify(info.amount)}`,
        type: info.confirmed ? "wired-confirmed" : "wired-pending",
      });
    });
  } else {
    if (order.contract_terms.wire_transfer_deadline.t_s !== "never") {
      events.push({
        when: new Date(order.contract_terms.wire_transfer_deadline.t_s * 1000),
        description: i18n.str`wire deadline`,
        type: "wire-deadline",
      });
    }
  }

  events.sort((a, b) => {
    return b.when.getTime() - a.when.getTime();
  });

  const nextEvent = events.find((e) => {
    return e.when.getTime() > now.getTime();
  });

  const refundURI =
    !order.refunded || wireDeadlineInThePast
      ? undefined
      : stringifyRefundUri({
          merchantBaseUrl: state.backendUrl.href as HostPortPath,
          orderId: order.contract_terms.order_id,
        });

  const refund_taken = order.refund_details.reduce((prev, cur) => {
    if (cur.pending) return prev;
    return Amounts.add(prev, Amounts.parseOrThrow(cur.amount)).amount;
  }, Amounts.zeroOfCurrency(amount.currency));
  value.refund_taken = Amounts.stringify(refund_taken);

  return (
    <div>
      <section class="section">
        <div class="columns">
          <div class="column" />
          <div class="column is-10">
            <section class="hero is-hero-bar">
              <div class="hero-body">
                <div class="level">
                  <div class="level-left">
                    <div class="level-item">
                      <i18n.Translate>Order</i18n.Translate> #{id}
                      <div class="tag is-success ml-4">
                        <i18n.Translate>Paid</i18n.Translate>
                      </div>
                      {order.wired ? (
                        <div class="tag is-success ml-4">
                          <i18n.Translate>Wired</i18n.Translate>
                        </div>
                      ) : null}
                      {order.refunded ? (
                        <div class="tag is-danger ml-4">
                          <i18n.Translate>Refunded</i18n.Translate>
                        </div>
                      ) : null}
                    </div>
                  </div>
                </div>
                <div class="level">
                  <div class="level-left">
                    <div class="level-item">
                      <h1 class="title">{Amounts.stringify(amount)}</h1>
                    </div>
                  </div>
                  <div class="level-right">
                    <div class="level-item">
                      <h1 class="title">
                        <div class="buttons">
                          <span
                            class="has-tooltip-left"
                            data-tooltip={
                              merchantCanRefund
                                ? i18n.str`Refund order`
                                : i18n.str`Not refundable`
                            }
                          >
                            <button
                              type="button"
                              class="button is-danger"
                              disabled={!merchantCanRefund}
                              onClick={() => onRefund(id)}
                            >
                              <i18n.Translate>Refund</i18n.Translate>
                            </button>
                          </span>
                        </div>
                      </h1>
                    </div>
                  </div>
                </div>

                <div class="level">
                  <div class="level-left" style={{ maxWidth: "100%" }}>
                    <div class="level-item" style={{ maxWidth: "100%" }}>
                      <div
                        class="content"
                        style={{
                          whiteSpace: "nowrap",
                          overflow: "hidden",
                          textOverflow: "ellipsis",
                        }}
                      >
                        {nextEvent && (
                          <p>
                            <i18n.Translate>Next event in </i18n.Translate>{" "}
                            {formatDistance(
                              nextEvent.when,
                              new Date(),
                              // "yyyy/MM/dd HH:mm:ss",
                            )}
                          </p>
                        )}
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </section>

            {!hasUnconfirmedWireTransfer ? undefined : (
              <NotificationCard
                notification={{
                  type: "INFO",
                  message: i18n.str`The order was wired.`,
                  description: i18n.str`Bank processing can take a few business days, depending on your bank.`,
                }}
              />
            )}

            <section class="section">
              <div class="columns">
                <div class="column is-4">
                  <div class="title">
                    <i18n.Translate>Timeline</i18n.Translate>
                  </div>
                  <Timeline events={events} />
                </div>
                <div class="column is-8">
                  <div class="title">
                    <i18n.Translate>Payment details</i18n.Translate>
                  </div>
                  <FormProvider<Paid>
                    object={value}
                    valueHandler={valueHandler}
                  >
                    {/* <InputCurrency<Paid> name="deposit_total" readonly label={i18n.str`Deposit total`} /> */}
                    {order.refunded && (
                      <InputCurrency<Paid>
                        name="refund_amount"
                        readonly
                        label={i18n.str`Refunded amount`}
                      />
                    )}
                    {order.refunded && (
                      <InputCurrency<Paid>
                        name="refund_taken"
                        readonly
                        label={i18n.str`Refund taken`}
                      />
                    )}
                    <Input<Paid>
                      name="order_status"
                      readonly
                      label={i18n.str`Order status`}
                      toStr={(d) => {
                        switch (d) {
                          case "paid":
                            return i18n.str`Paid`;
                          case "claimed":
                            return i18n.str`Claimed`;
                          case "unpiad":
                            return i18n.str`Unpaid`;
                        }
                        return d;
                      }}
                    />
                    <TextField<Paid>
                      name="order_status_url"
                      label={i18n.str`Status URL`}
                    >
                      <a
                        target="_blank"
                        rel="noreferrer"
                        href={order.order_status_url}
                      >
                        {order.order_status_url}
                      </a>
                    </TextField>
                    {refundURI && (
                      <TextField<Paid>
                        name="order_status_url"
                        label={i18n.str`Refund URI`}
                      >
                        <a target="_blank" rel="noreferrer" href={refundURI}>
                          {refundURI}
                        </a>
                      </TextField>
                    )}
                  </FormProvider>
                </div>
              </div>
            </section>

            {order.contract_terms.products?.length ? (
              <Fragment>
                <div class="title">
                  <i18n.Translate>Product list</i18n.Translate>
                </div>
                <ProductList list={order.contract_terms.products} />
              </Fragment>
            ) : undefined}

            {!value.contract_terms ? undefined : (
              <ContractTerms value={value.contract_terms} />
            )}
          </div>
          <div class="column" />
        </div>
      </section>
    </div>
  );
}

function UnpaidPage({
  id,
  order,
}: {
  id: string;
  order: TalerMerchantApi.CheckPaymentUnpaidResponse;
}) {
  const [value, valueHandler] = useState<Partial<Unpaid>>(order);
  const { i18n } = useTranslationContext();
  const [settings] = usePreference();
  useWaitForOrderPayment(id, order);

  return (
    <div>
      <section class="hero is-hero-bar">
        <div class="hero-body">
          <div class="level">
            <div class="level-left">
              <div class="level-item">
                <h1 class="title">
                  <i18n.Translate>Order</i18n.Translate> #{id}
                </h1>
              </div>
              <div class="tag is-dark">
                <i18n.Translate>Unpaid</i18n.Translate>
              </div>
            </div>
          </div>

          <div class="level">
            <div class="level-left" style={{ maxWidth: "100%" }}>
              <div class="level-item" style={{ maxWidth: "100%" }}>
                <div
                  class="content"
                  style={{
                    whiteSpace: "nowrap",
                    overflow: "hidden",
                    textOverflow: "ellipsis",
                  }}
                >
                  <p>
                    <b>
                      <i18n.Translate>Pay at</i18n.Translate>:
                    </b>{" "}
                    <a
                      href={order.order_status_url}
                      rel="nofollow"
                      target="new"
                    >
                      {order.order_status_url}
                    </a>
                  </p>
                  <p>
                    <b>
                      <i18n.Translate>Created at</i18n.Translate>:
                    </b>{" "}
                    {order.creation_time.t_s === "never"
                      ? i18n.str`Never`
                      : format(
                          new Date(order.creation_time.t_s * 1000),
                          datetimeFormatForSettings(settings),
                        )}
                  </p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>

      <section class="section is-main-section">
        <div class="columns">
          <div class="column" />
          <div class="column is-four-fifths">
            <FormProvider<Unpaid> object={value} valueHandler={valueHandler}>
              <Input<Unpaid>
                readonly
                name="summary"
                label={i18n.str`Summary`}
                tooltip={i18n.str`Human-readable description of the whole purchase`}
              />
              <InputCurrency<Unpaid>
                readonly
                name="total_amount"
                label={i18n.str`Amount`}
                tooltip={i18n.str`Total price for the transaction`}
              />
              <Input<Paid>
                name="order_status"
                readonly
                label={i18n.str`Order status`}
                toStr={(d) => {
                  switch (d) {
                    case "paid":
                      return i18n.str`Paid`;
                    case "claimed":
                      return i18n.str`Claimed`;
                    case "unpiad":
                      return i18n.str`Unpaid`;
                  }
                  return d;
                }}
              />
              <Input<Unpaid>
                name="order_status_url"
                readonly
                label={i18n.str`Order status URL`}
              />
              <TextField<Unpaid>
                name="taler_pay_uri"
                label={i18n.str`Payment URI`}
              >
                <a target="_blank" rel="noreferrer" href={value.taler_pay_uri}>
                  {value.taler_pay_uri}
                </a>
              </TextField>
            </FormProvider>
          </div>
          <div class="column" />
        </div>
      </section>
    </div>
  );
}

export function DetailPage({ id, selected, onRefunded, onBack }: Props): VNode {
  const [showRefund, setShowRefund] = useState<string | undefined>(undefined);
  const { i18n } = useTranslationContext();
  const DetailByStatus = function () {
    switch (selected.order_status) {
      case "claimed":
        return <ClaimedPage id={id} order={selected} />;
      case "paid":
        return <PaidPage id={id} order={selected} onRefund={setShowRefund} />;
      case "unpaid":
        return <UnpaidPage id={id} order={selected} />;
      default:
        return (
          <div>
            <i18n.Translate>
              Unknown order status. This is an error, please contact the
              administrator.
            </i18n.Translate>
          </div>
        );
    }
  };

  return (
    <Fragment>
      {DetailByStatus()}
      {showRefund && (
        <RefundModal
          order={selected}
          id={id}
          onCancel={() => setShowRefund(undefined)}
          onConfirmed={() => {
            onRefunded();
            setShowRefund(undefined);
          }}
        />
      )}
      <div class="columns">
        <div class="column" />
        <div class="column is-four-fifths">
          <div class="buttons is-right mt-5">
            <button class="button" onClick={onBack}>
              <i18n.Translate>Back</i18n.Translate>
            </button>
          </div>
        </div>
        <div class="column" />
      </div>
    </Fragment>
  );
}
export function getOrderAmountAndWirefee(
  order:
    | TalerMerchantApi.CheckPaymentPaidResponse
    | TalerMerchantApi.CheckPaymentPaidResponse,
) {
  if (
    order.contract_terms.version === undefined ||
    order.contract_terms.version === MerchantContractVersion.V0
  ) {
    const amount = Amounts.parseOrThrow(order.contract_terms.amount);
    const wireFee = Amounts.parseOrThrow(order.contract_terms.max_fee);
    return { amount, wireFee };
  }
  if (order.contract_terms.version === MerchantContractVersion.V1) {
    if (order.choice_index === undefined) return "v1-without-index" as const;
    if (order.choice_index > order.contract_terms.choices.length)
      return "v1-wrong-index" as const;
    const choice = order.contract_terms.choices[order.choice_index];
    const amount = Amounts.parseOrThrow(choice.amount);
    const wireFee = Amounts.parseOrThrow(choice.max_fee);
    return { amount, wireFee };
  }
  assertUnreachable(order.contract_terms.version);
}
