/*
 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 {
  HttpStatusCode,
  TalerError,
  TalerExchangeApi,
  assertUnreachable,
} from "@gnu-taler/taler-util";
import {
  ErrorLoading,
  Loading,
  createNewForm,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
import { useState } from "preact/hooks";
import { useCases } from "../hooks/useCases.js";
import { Pages } from "../pages.js";

import { amlStateConverter } from "../utils/converter.js";
import { AmlExchangeBackend } from "../utils/types.js";
import { Officer } from "./Officer.js";

export function CasesUI({
  records,
  filter,
  onChangeFilter,
  onFirstPage,
  onNext,
}: {
  onFirstPage?: () => void;
  onNext?: () => void;
  filter: AmlExchangeBackend.AmlState;
  onChangeFilter: (f: AmlExchangeBackend.AmlState) => void;
  records: TalerExchangeApi.AmlRecord[];
}): VNode {
  const { i18n } = useTranslationContext();

  const form = createNewForm<{ state: AmlExchangeBackend.AmlState }>();

  return (
    <div>
      <div class="sm:flex sm:items-center">
        <div class="px-2 sm:flex-auto">
          <h1 class="text-base font-semibold leading-6 text-gray-900">
            <i18n.Translate>Cases</i18n.Translate>
          </h1>
          <p class="mt-2 text-sm text-gray-700 w-80">
            <i18n.Translate>
              A list of all the account with the status
            </i18n.Translate>
          </p>
        </div>
        <div class="px-2">
          <form.Provider
            initial={{ state: filter }}
            onUpdate={(v) => {
              onChangeFilter(v.state ?? filter);
            }}
            onSubmit={(_v) => {}}
          >
            <form.InputChoiceHorizontal
              name="state"
              label={i18n.str`Filter`}
              converter={amlStateConverter}
              choices={[
                {
                  label: i18n.str`Pending`,
                  value: AmlExchangeBackend.AmlState.pending,
                },
                {
                  label: i18n.str`Frozen`,
                  value: AmlExchangeBackend.AmlState.frozen,
                },
                {
                  label: i18n.str`Normal`,
                  value: AmlExchangeBackend.AmlState.normal,
                },
              ]}
            />
          </form.Provider>
        </div>
      </div>
      <div class="mt-8 flow-root">
        <div class="overflow-x-auto">
          {!records.length ? (
            <div>empty result </div>
          ) : (
            <div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
              <table class="min-w-full divide-y divide-gray-300">
                <thead>
                  <tr>
                    <th
                      scope="col"
                      class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-80"
                    >
                      <i18n.Translate>Account Id</i18n.Translate>
                    </th>
                    <th
                      scope="col"
                      class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-40"
                    >
                      <i18n.Translate>Status</i18n.Translate>
                    </th>
                    <th
                      scope="col"
                      class="sm:hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-40"
                    >
                      <i18n.Translate>Threshold</i18n.Translate>
                    </th>
                  </tr>
                </thead>
                <tbody class="divide-y divide-gray-200 bg-white">
                  {records.map((r) => {
                    return (
                      <tr key={r.h_payto} class="hover:bg-gray-100 ">
                        <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500 ">
                          <div class="text-gray-900">
                            <a
                              href={Pages.account.url({ account: r.h_payto })}
                              class="text-indigo-600 hover:text-indigo-900"
                            >
                              {r.h_payto.substring(0, 16)}...
                            </a>
                          </div>
                        </td>
                        <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500">
                          {((state: AmlExchangeBackend.AmlState): VNode => {
                            switch (state) {
                              case AmlExchangeBackend.AmlState.normal: {
                                return (
                                  <span class="inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20">
                                    Normal
                                  </span>
                                );
                              }
                              case AmlExchangeBackend.AmlState.pending: {
                                return (
                                  <span class="inline-flex items-center rounded-md bg-yellow-50 px-2 py-1 text-xs font-medium text-yellow-700 ring-1 ring-inset ring-green-600/20">
                                    Pending
                                  </span>
                                );
                              }
                              case AmlExchangeBackend.AmlState.frozen: {
                                return (
                                  <span class="inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-green-600/20">
                                    Frozen
                                  </span>
                                );
                              }
                            }
                          })(r.current_state)}
                        </td>
                        <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-900">
                          {r.threshold}
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
              <Pagination onFirstPage={onFirstPage} onNext={onNext} />
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

export function Cases() {
  const [stateFilter, setStateFilter] = useState(
    AmlExchangeBackend.AmlState.pending,
  );

  const list = useCases(stateFilter);

  if (!list) {
    return <Loading />;
  }
  if (list instanceof TalerError) {
    return <ErrorLoading error={list} />;
  }

  if (list.type === "fail") {
    switch (list.case) {
      case HttpStatusCode.Unauthorized:
      case HttpStatusCode.Forbidden:
      case HttpStatusCode.NotFound:
      case HttpStatusCode.Conflict:
        return <Officer />;
      default:
        assertUnreachable(list);
    }
  }

  return (
    <CasesUI
      records={list.body}
      onFirstPage={list.isFirstPage ? undefined : list.loadFirst}
      onNext={list.isLastPage ? undefined : list.loadNext}
      filter={stateFilter}
      onChangeFilter={setStateFilter}
    />
  );
}

export const PeopleIcon = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 24 24"
    stroke-width="1.5"
    stroke="currentColor"
    class="w-6 h-6"
  >
    <path
      stroke-linecap="round"
      stroke-linejoin="round"
      d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z"
    />
  </svg>
);

export const HomeIcon = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 24 24"
    stroke-width="1.5"
    stroke="currentColor"
    class="w-6 h-6"
  >
    <path
      stroke-linecap="round"
      stroke-linejoin="round"
      d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"
    />
  </svg>
);

function Pagination({
  onFirstPage,
  onNext,
}: {
  onFirstPage?: () => void;
  onNext?: () => void;
}) {
  const { i18n } = useTranslationContext();
  return (
    <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
          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={!onFirstPage}
          onClick={onFirstPage}
        >
          <i18n.Translate>First page</i18n.Translate>
        </button>
        <button
          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={!onNext}
          onClick={onNext}
        >
          <i18n.Translate>Next</i18n.Translate>
        </button>
      </div>
    </nav>
  );
}
