import { use, FC, useState, useEffect, useCallback, useRef } from "react";

import { reaction } from "mobx";
import { observer } from "mobx-react-lite";

import useDimensions from "react-cool-dimensions";

import { useIdleTimer } from "react-idle-timer";

import { CSSTransition } from "react-transition-group";

import type { AlertStore } from "Stores/AlertStore";
import type { Settings } from "Stores/Settings";
import type { SilenceFormStore } from "Stores/SilenceFormStore";
import { IsMobile } from "Common/Device";
import { OverviewModal } from "Components/OverviewModal";
import { MainModal } from "Components/MainModal";
import SilenceModal from "Components/SilenceModal";
import AppToasts from "Components/Toast/AppToasts";
import { ThemeContext } from "Components/Theme";
import { Fetcher } from "Components/Fetcher";
import { FilterInput } from "./FilterInput";
import { MobileIdleTimeout, DesktopIdleTimeout } from "./timeouts";

const NavBar: FC<{
  alertStore: AlertStore;
  settingsStore: Settings;
  silenceFormStore: SilenceFormStore;
  fixedTop?: boolean;
}> = ({ alertStore, settingsStore, silenceFormStore, fixedTop = true }) => {
  const [containerClass, setContainerClass] = useState<string>("visible");

  const context = use(ThemeContext);

  const ref = useRef<HTMLElement>(null);
  const { observe, height } = useDimensions({});

  const updateBodyPaddingTop = useCallback(
    (idle: boolean) => {
      const paddingTop = idle ? 0 : height + 8;
      // eslint-disable-next-line react-compiler/react-compiler -- intentional DOM side-effect, not React state
      document.body.style.paddingTop = `${paddingTop}px`;
      setContainerClass(idle ? "invisible" : "visible");

      const toggleEvent = new CustomEvent("navbarResize", {
        detail: paddingTop,
      });
      window.dispatchEvent(toggleEvent);
    },
    [height],
  );

  const onActive = useCallback(() => {
    alertStore.ui.setIsIdle(false);
  }, [alertStore.ui]);

  const onIdle = useCallback(() => {
    alertStore.ui.setIsIdle(true);
  }, [alertStore.ui]);

  const { pause, reset } = useIdleTimer({
    timeout: IsMobile() ? MobileIdleTimeout : DesktopIdleTimeout,
    onIdle: onIdle,
    onActive: onActive,
    debounce: 500,
  });

  useEffect(() => {
    let timer: number;
    if (alertStore.ui.isIdle) {
      timer = window.setTimeout(
        () => updateBodyPaddingTop(true),
        context.animations.duration,
      );
    } else {
      updateBodyPaddingTop(false);
    }
    return () => window.clearTimeout(timer);
  }, [
    height,
    updateBodyPaddingTop,
    alertStore.ui.isIdle,
    context.animations.duration,
  ]);

  useEffect(
    () =>
      reaction(
        () =>
          !settingsStore.filterBarConfig.config.autohide ||
          alertStore.status.paused ||
          alertStore.filters.values.filter((f) => f.applied === false).length >
            0,
        (paused) => (paused ? pause() : reset()),
        { fireImmediately: true },
      ),
    [],
  );

  const navRef = useRef<HTMLElement>(null);

  return (
    <div className={`container p-0 m-0 mw-100 ${containerClass}`}>
      <CSSTransition
        classNames="components-animation-navbar"
        in={!alertStore.ui.isIdle}
        timeout={context.animations.duration}
        onEntering={() => {}}
        onExited={() => {}}
        enter
        exit
        nodeRef={navRef}
      >
        <nav
          ref={(el) => {
            observe(el as HTMLElement);
            ref.current = el as HTMLElement;
            navRef.current = el;
          }}
          className={`navbar navbar-expand navbar-dark p-1 bg-primary-transparent d-flex ${
            fixedTop ? "fixed-top" : "w-100"
          } align-items-start`}
        >
          <span className="navbar-nav d-flex flex-row">
            {alertStore.info.timestamp !== "" &&
            alertStore.data.upstreams.instances.length === 0 ? null : (
              <span className="navbar-brand p-0 my-0 mx-2 h1 d-none d-sm-block">
                <OverviewModal alertStore={alertStore} />
              </span>
            )}
            <Fetcher alertStore={alertStore} settingsStore={settingsStore} />
          </span>
          {alertStore.info.timestamp !== "" &&
          alertStore.data.upstreams.instances.length === 0 ? null : (
            <FilterInput
              alertStore={alertStore}
              settingsStore={settingsStore}
            />
          )}
          {alertStore.info.timestamp !== "" &&
          alertStore.data.upstreams.instances.length === 0 ? null : (
            <ul className="navbar-nav flex-wrap flex-shrink-1 ms-1">
              <AppToasts alertStore={alertStore} />
              <SilenceModal
                alertStore={alertStore}
                silenceFormStore={silenceFormStore}
                settingsStore={settingsStore}
              />
              <MainModal
                alertStore={alertStore}
                settingsStore={settingsStore}
              />
            </ul>
          )}
        </nav>
      </CSSTransition>
    </div>
  );
};

export default observer(NavBar);
