/*
 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/>
 */

import { ComponentChildren, Fragment, h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
import { AdminPaths } from "../../AdminRoutes.js";
import { InstancePaths } from "../../Routing.js";
import { Notification } from "../../utils/types.js";
import { NavigationBar } from "./NavigationBar.js";
import { Sidebar } from "./SideBar.js";
import { useSessionContext } from "../../context/session.js";
import { useNavigationContext } from "@gnu-taler/web-util/browser";
import { LangSelector } from "./LangSelector.js";

function getInstanceTitle(path: string, id: string): string {
  switch (path) {
    case InstancePaths.settings:
      return `${id}: Settings`;
    case InstancePaths.bank_new:
      return `${id}: New bank account`;
    case InstancePaths.bank_list:
      return `${id}: Bank accounts`;
    case InstancePaths.bank_update:
      return `${id}: Update bank Account`;
    case InstancePaths.order_list:
      return `${id}: Orders`;
    case InstancePaths.order_new:
      return `${id}: New order`;
    case InstancePaths.inventory_list:
      return `${id}: Inventory`;
    case InstancePaths.inventory_new:
      return `${id}: New product`;
    case InstancePaths.inventory_update:
      return `${id}: Update product`;
    case InstancePaths.category_list:
      return `${id}: Category`;
    case InstancePaths.category_new:
      return `${id}: New category`;
    case InstancePaths.category_update:
      return `${id}: Update category`;
    case InstancePaths.transfers_list:
      return `${id}: Wire transfers`;
    case InstancePaths.webhooks_list:
      return `${id}: Webhooks`;
    case InstancePaths.webhooks_new:
      return `${id}: New webhook`;
    case InstancePaths.webhooks_update:
      return `${id}: Update webhook`;
    case InstancePaths.otp_devices_list:
      return `${id}: OTP devices`;
    case InstancePaths.otp_devices_new:
      return `${id}: New OTP device`;
    case InstancePaths.otp_devices_update:
      return `${id}: Update OTP device`;
    case InstancePaths.templates_new:
      return `${id}: New template`;
    case InstancePaths.templates_update:
      return `${id}: Update template`;
    case InstancePaths.templates_list:
      return `${id}: Templates`;
    case InstancePaths.templates_use:
      return `${id}: Use template`;
    case InstancePaths.interface:
      return `${id}: Personalization`;
    case InstancePaths.token_family_list:
      return `${id}: Token families`;
    case InstancePaths.token_family_new:
      return `${id}: New token family`;
    case InstancePaths.token_family_update:
      return `${id}: Update token family`;
    case InstancePaths.access_token_list:
      return `${id}: Access tokens`;
    case InstancePaths.access_token_new:
      return `${id}: New access token`;
    default: {
      return "";
    }
  }
}

function getAdminTitle(path: string, instance: string) {
  if (path === AdminPaths.new_instance) return `New instance`;
  if (path === AdminPaths.list_instances) return `Instances`;
  return getInstanceTitle(path, instance);
}

interface MenuProps {}

function WithTitle({
  title,
  children,
}: {
  title: string;
  children: ComponentChildren;
}): VNode {
  useEffect(() => {
    document.title = `Taler Backoffice: ${title}`;
  }, [title]);
  return <Fragment>{children}</Fragment>;
}

export function Menu(_p: MenuProps): VNode {
  const [mobileOpen, setMobileOpen] = useState(false);

  const { state, deImpersonate } = useSessionContext();
  const { path } = useNavigationContext();

  const titleWithSubtitle = !state.isAdmin
    ? getInstanceTitle(path, state.instance)
    : getAdminTitle(path, state.instance);

  const isLoggedIn = state.status === "loggedIn";

  return (
    <WithTitle title={titleWithSubtitle}>
      <div
        class={mobileOpen ? "has-aside-mobile-expanded" : ""}
        onClick={() => setMobileOpen(false)}
      >
        <NavigationBar
          onMobileMenu={() => setMobileOpen(!mobileOpen)}
          title={titleWithSubtitle}
        />

        {isLoggedIn && <Sidebar mobile={mobileOpen} />}

        {state.status !== "loggedOut" && state.impersonated && (
          <nav
            class="level"
            style={{
              zIndex: 100,
              position: "fixed",
              width: "50%",
              marginLeft: "20%",
            }}
          >
            <div class="level-item has-text-centered has-background-warning">
              <p class="is-size-5">
                You are viewing the instance <b>&quot;{state.instance}&quot;</b>
                .{" "}
                <a
                  href="#/instances"
                  onClick={() => {
                    deImpersonate();
                  }}
                >
                  go back
                </a>
              </p>
            </div>
          </nav>
        )}
      </div>
    </WithTitle>
  );
}

interface NotYetReadyAppMenuProps {
  title: string;
  onShowSettings: () => void;
  onLogout?: () => void;
  isPasswordOk: boolean;
}

interface NotifProps {
  notification?: Notification;
}
export function NotificationCard({
  notification: n,
}: NotifProps): VNode | null {
  if (!n) return null;
  return (
    <div class="notification">
      <div class="columns is-vcentered">
        <div class="column is-12">
          <article
            class={
              n.type === "ERROR"
                ? "message is-danger"
                : n.type === "WARN"
                  ? "message is-warning"
                  : "message is-info"
            }
          >
            <div class="message-header">
              <p>{n.message}</p>
            </div>
            {n.description && (
              <div class="message-body">
                <div>{n.description}</div>
                {n.details && <pre>{n.details}</pre>}
              </div>
            )}
          </article>
        </div>
      </div>
    </div>
  );
}

interface NotConnectedAppMenuProps {
  title: string;
}
export function NotConnectedAppMenu({
  title,
}: NotConnectedAppMenuProps): VNode {
  const [mobileOpen, setMobileOpen] = useState(false);

  useEffect(() => {
    document.title = `Taler Backoffice: ${title}`;
  }, [title]);

  return (
    <div
      class={mobileOpen ? "has-aside-mobile-expanded" : ""}
      onClick={() => setMobileOpen(false)}
    >
      <NavigationBar
        onMobileMenu={() => setMobileOpen(!mobileOpen)}
        title={title}
      />
      <div
        style={{
          width: "100%",
          display: "flex",
          justifyContent: "space-between",
          paddingTop:8,
          paddingRight: 8,
          
        }}
      >
        <div />
        <LangSelector />
      </div>
    </div>
  );
}

export function NotYetReadyAppMenu({ title }: NotYetReadyAppMenuProps): VNode {
  const [mobileOpen, setMobileOpen] = useState(false);
  const { state } = useSessionContext();

  useEffect(() => {
    document.title = `Taler Backoffice: ${title}`;
  }, [title]);

  const isLoggedIn = state.status === "loggedIn";

  return (
    <div
      class={mobileOpen ? "has-aside-mobile-expanded" : ""}
      onClick={() => setMobileOpen(false)}
    >
      <NavigationBar
        onMobileMenu={() => setMobileOpen(!mobileOpen)}
        title={title}
      />
      {isLoggedIn && <Sidebar mobile={mobileOpen} />}
    </div>
  );
}
