/*
 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)
 * @author Nic Eigel
 */

import { HttpStatusCode, LibtoolVersion } from "@gnu-taler/taler-util";
import {
  ErrorType,
  TranslationProvider,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useMemo } from "preact/hooks";
import { ApplicationReadyRoutes } from "./ApplicationReadyRoutes.js";
import { Loading } from "./components/exception/loading.js";
import {
  NotConnectedAppMenu,
  NotificationCard,
} from "./components/menu/index.js";
import { BackendContextProvider } from "./context/backend.js";
import { ConfigContextProvider } from "./context/config.js";
import { useBackendConfig } from "./hooks/backend.js";
import { strings } from "./i18n/strings.js";

export function Application(): VNode {
  return (
    <BackendContextProvider>
      <TranslationProvider source={strings}>
        <ApplicationStatusRoutes />
      </TranslationProvider>
    </BackendContextProvider>
  );
}

/**
 * Check connection testing against /config
 *
 * @returns
 */
function ApplicationStatusRoutes(): VNode {
  const result = useBackendConfig();
  const { i18n } = useTranslationContext();

  const configData = result.ok && result.data ? result.data : undefined;
  const ctx = useMemo(() => configData, [configData]);

  if (!result.ok) {
    if (result.loading) return <Loading />;
    if (
      result.type === ErrorType.CLIENT &&
      result.status === HttpStatusCode.Unauthorized
    ) {
      return (
        <Fragment>
          <NotConnectedAppMenu title="Login" />
          <NotificationCard
            notification={{
              message: i18n.str`Checking the /config endpoint got authorization error`,
              type: "ERROR",
              description: `The /config endpoint of the backend server should be accessible`,
            }}
          />
        </Fragment>
      );
    }
    if (
      result.type === ErrorType.CLIENT &&
      result.status === HttpStatusCode.NotFound
    ) {
      return (
        <Fragment>
          <NotConnectedAppMenu title="Error" />
          <NotificationCard
            notification={{
              message: i18n.str`Could not find /config endpoint on this URL`,
              type: "ERROR",
              description: `Check the URL or contact the system administrator.`,
            }}
          />
        </Fragment>
      );
    }
    if (result.type === ErrorType.SERVER) {
      <Fragment>
        <NotConnectedAppMenu title="Error" />
        <NotificationCard
          notification={{
            message: i18n.str`Server response with an error code`,
            type: "ERROR",
            description: i18n.str`Got message "${result.message}" from ${result.info?.url}`,
          }}
        />
      </Fragment>;
    }
    if (result.type === ErrorType.UNREADABLE) {
      <Fragment>
        <NotConnectedAppMenu title="Error" />
        <NotificationCard
          notification={{
            message: i18n.str`Response from server is unreadable, http status: ${result.status}`,
            type: "ERROR",
            description: i18n.str`Got message "${result.message}" from ${result.info?.url}`,
          }}
        />
      </Fragment>;
    }
    return (
      <Fragment>
        <NotConnectedAppMenu title="Error" />
        <NotificationCard
          notification={{
            message: i18n.str`Unexpected Error`,
            type: "ERROR",
            description: i18n.str`Got message "${result.message}" from ${result.info?.url}`,
          }}
        />
      </Fragment>
    );
  }

  const SUPPORTED_VERSION = "1:0:1";
  if (
    result.data &&
    !LibtoolVersion.compare(SUPPORTED_VERSION, result.data.version)?.compatible
  ) {
    return (
      <Fragment>
        <NotConnectedAppMenu title="Error" />
        <NotificationCard
          notification={{
            message: i18n.str`Incompatible version`,
            type: "ERROR",
            description: i18n.str`Auditor backend server version ${result.data.version} is not compatible with the supported version ${SUPPORTED_VERSION}`,
          }}
        />
      </Fragment>
    );
  }

  return (
    <div class="has-navbar-fixed-top">
      <ConfigContextProvider value={ctx!}>
        <ApplicationReadyRoutes />
      </ConfigContextProvider>
    </div>
  );
}
