/*
 This file is part of GNU Taler
 (C) 2022-2025 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,
  assertUnreachable,
} from "@gnu-taler/taler-util";
import {
  Attention,
  ErrorLoading,
  InputToggle,
  Loading,
  Pagination,
  RouteDefinition,
  useExchangeApiContext,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useCurrentDecisions } from "../hooks/decisions.js";

import { useEffect, useState } from "preact/hooks";
import { useOfficer } from "../hooks/officer.js";
import { Profile } from "./Profile.js";

export function AccountList({
  routeToAccountById: caseByIdRoute,
}: {
  routeToAccountById: RouteDefinition<{ cid: string }>;
}): VNode {
  const { i18n } = useTranslationContext();
  const [filtered, setFiltered] = useState<boolean>();
  const list = useCurrentDecisions({ investigated: filtered });

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

  if (list.type === "fail") {
    switch (list.case) {
      case HttpStatusCode.Forbidden:
        return (
          <Fragment>
            <Attention type="danger" title={i18n.str`Operation denied`}>
              <i18n.Translate>
                This account signature is invalid, contact administrator or
                create a new one.
              </i18n.Translate>
            </Attention>
            <Profile />
          </Fragment>
        );
      case HttpStatusCode.NotFound:
        return (
          <Fragment>
            <Attention type="danger" title={i18n.str`Operation denied`}>
              <i18n.Translate>
                The designated AML account is not known, contact administrator
                or create a new one.
              </i18n.Translate>
            </Attention>
            <Profile />
          </Fragment>
        );
      case HttpStatusCode.Conflict:
        return (
          <Fragment>
            <Attention type="danger" title={i18n.str`Operation denied`}>
              <i18n.Translate>
                The designated AML account is not enabled, contact administrator
                or create a new one.
              </i18n.Translate>
            </Attention>
            <Profile />
          </Fragment>
        );
      default:
        assertUnreachable(list);
    }
  }

  const records = list.body;

  return (
    <div>
      <div class="sm:flex sm:items-center">
        {filtered === true ? (
          <div class="px-2 sm:flex-auto">
            <h1 class="text-base font-semibold leading-6 text-gray-900">
              <i18n.Translate>Accounts under investigation</i18n.Translate>
            </h1>
            <p class="mt-2 text-sm text-gray-700 w-80">
              <i18n.Translate>
                A list of all the accounts which are waiting for a deicison to
                be made.
              </i18n.Translate>
            </p>
          </div>
        ) : filtered === false ? (
          <div class="px-2 sm:flex-auto">
            <h1 class="text-base font-semibold leading-6 text-gray-900">
              <i18n.Translate>Accounts without investigation</i18n.Translate>
            </h1>
            <p class="mt-2 text-sm text-gray-700 w-80">
              <i18n.Translate>
                A list of all the accounts which are active.
              </i18n.Translate>
            </p>
          </div>
        ) : (
          <div class="px-2 sm:flex-auto">
            <h1 class="text-base font-semibold leading-6 text-gray-900">
              <i18n.Translate>Accounts</i18n.Translate>
            </h1>
            <p class="mt-2 text-sm text-gray-700 w-80">
              <i18n.Translate>
                A list of all the accounts known to the exchange.
              </i18n.Translate>
            </p>
          </div>
        )}

        <JumpByIdForm
          caseByIdRoute={caseByIdRoute}
          filtered={filtered}
          onTog={setFiltered}
        />
      </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 Identification</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>
                  </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={caseByIdRoute.url({
                                cid: r.h_payto,
                              })}
                              class="text-indigo-600 hover:text-indigo-900 font-mono"
                            >
                              {r.h_payto}
                            </a>
                            <p class="text-gray-500 text-xs">{r.full_payto}</p>
                          </div>
                        </td>
                        <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-900">
                          {r.to_investigate ? (
                            <span title="require investigation">
                              <ToInvestigateIcon />
                            </span>
                          ) : undefined}
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
              <Pagination onFirstPage={list.loadFirst} onNext={list.loadNext} />
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

export const ToInvestigateIcon = () => (
  <svg
    title="requires investigation"
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 24 24"
    stroke-width="1.5"
    stroke="currentColor"
    class="size-6 w-6"
  >
    <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>
);

export const TransfersIcon = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 24 24"
    stroke-width="1.5"
    stroke="currentColor"
    class="size-6"
  >
    <path
      stroke-linecap="round"
      stroke-linejoin="round"
      d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5"
    />
  </svg>
);

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>
);
export const FormIcon = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 24 24"
    fill="currentColor"
    class="w-6 h-6"
  >
    <path
      fillRule="evenodd"
      d="M1.5 5.625c0-1.036.84-1.875 1.875-1.875h17.25c1.035 0 1.875.84 1.875 1.875v12.75c0 1.035-.84 1.875-1.875 1.875H3.375A1.875 1.875 0 0 1 1.5 18.375V5.625ZM21 9.375A.375.375 0 0 0 20.625 9h-7.5a.375.375 0 0 0-.375.375v1.5c0 .207.168.375.375.375h7.5a.375.375 0 0 0 .375-.375v-1.5Zm0 3.75a.375.375 0 0 0-.375-.375h-7.5a.375.375 0 0 0-.375.375v1.5c0 .207.168.375.375.375h7.5a.375.375 0 0 0 .375-.375v-1.5Zm0 3.75a.375.375 0 0 0-.375-.375h-7.5a.375.375 0 0 0-.375.375v1.5c0 .207.168.375.375.375h7.5a.375.375 0 0 0 .375-.375v-1.5ZM10.875 18.75a.375.375 0 0 0 .375-.375v-1.5a.375.375 0 0 0-.375-.375h-7.5a.375.375 0 0 0-.375.375v1.5c0 .207.168.375.375.375h7.5ZM3.375 15h7.5a.375.375 0 0 0 .375-.375v-1.5a.375.375 0 0 0-.375-.375h-7.5a.375.375 0 0 0-.375.375v1.5c0 .207.168.375.375.375Zm0-3.75h7.5a.375.375 0 0 0 .375-.375v-1.5A.375.375 0 0 0 10.875 9h-7.5A.375.375 0 0 0 3 9.375v1.5c0 .207.168.375.375.375Z"
      clipRule="evenodd"
    />
  </svg>
);

export const SearchIcon = () => (
  <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="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"
    />
  </svg>
);

let latestTimeout: undefined | ReturnType<typeof setTimeout> = undefined;

function JumpByIdForm({
  caseByIdRoute,
  filtered,
  onTog,
}: {
  caseByIdRoute: RouteDefinition<{ cid: string }>;
  filtered?: boolean;
  onTog: (d: boolean | undefined) => void;
}): VNode {
  const { i18n } = useTranslationContext();
  const [account, setAccount] = useState<string>("");
  const officer = useOfficer();
  const session = officer.state === "ready" ? officer.account : undefined;
  const { lib } = useExchangeApiContext();
  const [valid, setValid] = useState(false);
  const [error, setError] = useState<string>();
  useEffect(() => {
    if (!session || !account) return;
    const activeSession = session;
    if (latestTimeout) {
      clearTimeout(latestTimeout);
    }
    setError(undefined);
    setValid(false);
    latestTimeout = setTimeout(async function checkAccouunt() {
      let found = false;
      try {
        const result = await lib.exchange.getAmlAttributesForAccount(
          activeSession,
          account,
          { limit: 1 },
        );
        found = result.type === "ok";
      } catch (e) {
        console.log(e);
      }
      setValid(found);
      if (!found) {
        setError(i18n.str`Invalid account`);
      }
    }, 500);
  }, [account, session]);
  return (
    <form class="mt-5 grid grid-cols-1">
      <div>
        <div class="flex flex-row">
          <div class="w-full sm:max-w-xs">
            <input
              name="account"
              onChange={(e) => {
                setAccount(e.currentTarget.value);
              }}
              class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6"
              placeholder={i18n.str`Search by ID`}
            />
          </div>
          <a
            href={!valid ? undefined : caseByIdRoute.url({ cid: account })}
            data-disabled={!valid}
            class="data-[disabled=true]:bg-gray-400 mt-3 inline-flex w-full items-center 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 sm:ml-3 sm:mt-0 sm:w-auto"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              fill="none"
              viewBox="0 0 24 24"
              stroke-width="1.5"
              stroke="currentColor"
              class="size-6 w-6 h-6"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"
              />
            </svg>
          </a>
        </div>
        {!error ? undefined : <p class="mt-2 text-sm text-red-600">{error}</p>}
      </div>
      <div class="mt-2 cursor-default">
        <InputToggle
          threeState
          name="inv"
          label={i18n.str`Only investigated`}
          handler={{
            name: "inv",
            onChange: (x) => onTog(x),
            value: filtered,
          }}
        />
      </div>
    </form>
  );
}
