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

import { CurrencySpecification } from "@gnu-taler/taler-util";
import {
  useConversionInfo,
  useConversionRateClasses,
} from "../../hooks/regional.js";
import { RenderAmount } from "../PaytoWireTransferForm.js";

const TALER_SCREEN_ID = 130;

interface Props {
  routeCreate: RouteDefinition;
  routeShowDetails: RouteDefinition<{ classId: string }>;
}

export function ConversionClassList({
  routeCreate,
  routeShowDetails,
}: Props): VNode {
  const result = useConversionRateClasses();
  const { i18n } = useTranslationContext();
  const resultInfo = useConversionInfo();

  const convInfo =
    !resultInfo || resultInfo instanceof Error || resultInfo.type === "fail"
      ? undefined
      : resultInfo.body;

  if (!convInfo) {
    return <Fragment>-</Fragment>;
  }
  if (!result) {
    return <Loading />;
  }
  if (result instanceof TalerError) {
    return <ErrorLoading error={result} />;
  }

  if (result.type !== "ok") {
    switch (result.case) {
      case HttpStatusCode.Forbidden:
        return (
          <Attention
            type="warning"
            title={i18n.str`No enough permission to access the conversion rate list.`}
          ></Attention>
        );
      case HttpStatusCode.NotFound:
        return (
          <Attention
            type="warning"
            title={i18n.str`Conversion list not found. Maybe conversion rate is not supported.`}
          ></Attention>
        );
      case HttpStatusCode.NotImplemented:
        return (
          <Attention
            type="warning"
            title={i18n.str`Conversion list not implemented.`}
          ></Attention>
        );
      case HttpStatusCode.Unauthorized:
        return (
          <Attention
            type="warning"
            title={i18n.str`No enough permission to access the conversion rate list.`}
          ></Attention>
        );
      default:
        assertUnreachable(result);
    }
  }

  const classes = result.body;

  return (
    <Fragment>
      <div class="px-4 sm:px-6 lg:px-8 mt-8">
        <div class="sm:flex sm:items-center">
          <div class="sm:flex-auto">
            <h1 class="text-base font-semibold leading-6 text-gray-900">
              <i18n.Translate>Conversion rate classes</i18n.Translate>
            </h1>
          </div>
          <div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
            <a
              href={routeCreate.url({})}
              name="create account"
              type="button"
              class="block rounded-md bg-indigo-600 px-3 py-2 text-center 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>Create conversion rate class</i18n.Translate>
            </a>
          </div>
        </div>
        <div class="mt-4 flow-root">
          <div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
            <div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
              {!classes.length ? (
                <div>
                  <i18n.Translate>No conversion rate class</i18n.Translate>
                </div>
              ) : (
                <table class="min-w-full divide-y divide-gray-300">
                  <thead>
                    <tr>
                      <th
                        scope="col"
                        class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0"
                      >{i18n.str`Name`}</th>
                      <th
                        scope="col"
                        class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0"
                      >{i18n.str`Description`}</th>
                      <th
                        scope="col"
                        class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0"
                      >{i18n.str`Cashin`}</th>
                      <th
                        scope="col"
                        class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900"
                      >{i18n.str`Cashout`}</th>
                    </tr>
                  </thead>
                  <tbody class="divide-y divide-gray-200">
                    {classes.map((row, idx) => {
                      return (
                        <tr key={idx} class="">
                          <td class="whitespace-nowrap py-3 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-0">
                            <a
                              href={routeShowDetails.url({
                                classId: String(row.conversion_rate_class_id),
                              })}
                            >
                              {row.name}
                            </a>
                          </td>
                          <td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
                            <a
                              href={routeShowDetails.url({
                                classId: String(row.conversion_rate_class_id),
                              })}
                            >
                              {row.description}
                            </a>
                          </td>
                          <td class="whitespace-nowrap px-3 py-2 text-sm text-gray-500">
                            <a
                              href={routeShowDetails.url({
                                classId: String(row.conversion_rate_class_id),
                              })}
                            >
                              <DescribeConversion
                                ratio={
                                  row.cashin_ratio ??
                                  convInfo.conversion_rate.cashin_ratio
                                }
                                fee={
                                  row.cashin_fee ??
                                  convInfo.conversion_rate.cashin_fee
                                }
                                min={
                                  row.cashin_min_amount ??
                                  convInfo.conversion_rate.cashin_min_amount
                                }
                                rounding={
                                  row.cashin_rounding_mode ??
                                  convInfo.conversion_rate.cashin_rounding_mode
                                }
                                minSpec={convInfo.fiat_currency_specification}
                                feeSpec={
                                  convInfo.regional_currency_specification
                                }
                              />
                            </a>
                          </td>
                          <td class="whitespace-nowrap px-3 py-2 text-sm text-gray-500">
                            <a
                              href={routeShowDetails.url({
                                classId: String(row.conversion_rate_class_id),
                              })}
                            >
                              <DescribeConversion
                                ratio={
                                  row.cashout_ratio ??
                                  convInfo.conversion_rate.cashout_ratio
                                }
                                fee={
                                  row.cashout_fee ??
                                  convInfo.conversion_rate.cashout_fee
                                }
                                min={
                                  row.cashout_min_amount ??
                                  convInfo.conversion_rate.cashout_min_amount
                                }
                                rounding={
                                  row.cashout_rounding_mode ??
                                  convInfo.conversion_rate.cashout_rounding_mode
                                }
                                minSpec={
                                  convInfo.regional_currency_specification
                                }
                                feeSpec={convInfo.fiat_currency_specification}
                              />
                            </a>
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              )}
            </div>
            <nav
              class="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6 rounded-lg"
              aria-label="Pagination"
            >
              <div class="flex flex-1 justify-between sm:justify-end">
                <button
                  name="first page"
                  class="relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0"
                  disabled={!result.loadFirst}
                  onClick={result.loadFirst}
                >
                  <i18n.Translate>First page</i18n.Translate>
                </button>
                <button
                  name="next page"
                  class="relative disabled:bg-gray-100 disabled:text-gray-500 ml-3 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0"
                  disabled={!result.loadNext}
                  onClick={result.loadNext}
                >
                  <i18n.Translate>Next</i18n.Translate>
                </button>
              </div>
            </nav>
          </div>
        </div>
      </div>
    </Fragment>
  );
}

export function DescribeConversion({
  fee,
  min,
  ratio,
  rounding,
  feeSpec,
  minSpec,
}: {
  min: AmountString;
  ratio: DecimalNumber;
  fee: AmountString;
  rounding: RoundingMode;
  minSpec: CurrencySpecification;
  feeSpec: CurrencySpecification;
}): VNode {
  const { i18n } = useTranslationContext();

  return (
    <Fragment>
      1:{ratio}
      {Amounts.isZero(min) ? undefined : (
        <Fragment>
          <br />
          <i18n.Translate>min:</i18n.Translate>&nbsp;
          <RenderAmount spec={minSpec} value={Amounts.parseOrThrow(min)} />
        </Fragment>
      )}
      {Amounts.isZero(fee) ? undefined : (
        <Fragment>
          <br />
          <i18n.Translate>fee:</i18n.Translate>&nbsp;
          <RenderAmount spec={feeSpec} value={Amounts.parseOrThrow(fee)} />
        </Fragment>
      )}
    </Fragment>
  );
}
