<script setup>
import logoDiapositiefCompact from "../assets/layout/images/logo-diapositief-compact.svg";
import logoDark from "../assets/layout/images/logo-dark.svg";
import logoDiapositief from "../assets/layout/images/logo-diapositief.svg";
import { useLayout } from "../composables/layout/layout.js";
import { nextTick, onBeforeUnmount, ref, watch, computed } from "vue";
import { useRoute } from "vue-router";
import AppMenu from "./AppMenu.vue";
import AppTopbar from "./AppTopbar.vue";

const BREAKPOINT = 992;
const mediaQuery = window.matchMedia(`(min-width: ${BREAKPOINT}px)`);
const {
  layoutConfig,
  layoutState,
  isDesktop,
  isHorizontal,
  isSlim,
  isCompact,
  hasOpenOverlay,
  hasOverlaySubmenu,
  hasOpenOverlaySubmenu,
  shouldCollapseSidebar,
  isDrawerLike,
  isMaestroMode,
} = useLayout();
const route = useRoute();
const menuContainerRef = ref(null);
const sidebarRef = ref(null);

let timeout = null;
let observer = null;
let outsideClickListener = null;

watch(
  () => route.path,
  (newPath) => {
    if (hasOverlaySubmenu.value && isDesktop()) layoutState.activePath = null;
    else if (!isDrawerLike.value) layoutState.activePath = newPath;
    // In drawer/maestro mode, layout.js route watcher owns activePath

    layoutState.overlayMenuActive = false;
    layoutState.mobileMenuActive = false;
    layoutState.menuHoverActive = false;
  },
  { immediate: true },
);

watch(hasOpenOverlay, (newVal) => {
  if (isDesktop()) {
    if (newVal) bindOutsideClickListener();
    else unbindOutsideClickListener();
  }
});

watch(hasOpenOverlaySubmenu, (newValue) => {
  if (isDesktop()) {
    if (newValue) nextTick(setupIntersectionObserver);
    else unbindObserver();
  }
});

const screenChangeListener = () => {
  if (hasOverlaySubmenu.value) {
    layoutState.activePath = isDesktop() ? null : route.path;
    layoutState.menuHoverActive = false;
    unbindOutsideClickListener();
    unbindObserver();
  }
};

const bindOutsideClickListener = () => {
  if (!outsideClickListener) {
    outsideClickListener = (event) => {
      if (isOutsideClicked(event)) {
        layoutState.overlayMenuActive = false;

        if (hasOverlaySubmenu.value) {
          layoutState.activePath = null;
          layoutState.menuHoverActive = false;
        }
      }
    };

    document.addEventListener("click", outsideClickListener);
  }
};

const unbindOutsideClickListener = () => {
  if (outsideClickListener) {
    document.removeEventListener("click", outsideClickListener);
    outsideClickListener = null;
  }
};

const isOutsideClicked = (event) => {
  const topbarButtonEl = document.querySelector(".topbar-left > a");
  const topbarRightEl = document.querySelector(".topbar-right");

  return (
    topbarRightEl?.isSameNode(event.target) ||
    topbarRightEl?.contains(event.target) ||
    !(
      sidebarRef.value.isSameNode(event.target) ||
      sidebarRef.value.contains(event.target) ||
      topbarButtonEl?.isSameNode(event.target) ||
      topbarButtonEl?.contains(event.target)
    )
  );
};

const onAnchorToggle = () => {
  layoutState.anchored = !layoutState.anchored;
};
const isAnchored = computed(() => layoutState.anchored);
const showPinButton = computed(() => !isMaestroMode.value);

const onMenuScroll = () => {
  if (menuContainerRef.value) {
    if (isHorizontal.value) {
      menuContainerRef.value.style.setProperty(
        "--menu-scroll-x",
        `-${menuContainerRef.value.scrollLeft}px`,
      );
    } else if (isSlim.value || isCompact.value) {
      menuContainerRef.value.style.setProperty(
        "--menu-scroll-y",
        `-${menuContainerRef.value.scrollTop}px`,
      );
    }
  }

  if (hasOverlaySubmenu.value && isDesktop()) {
    layoutState.activePath = null;
  }
};

const setupIntersectionObserver = () => {
  if (!menuContainerRef.value) return;

  if (observer) {
    observer.disconnect();
  }

  const activeMenuItem = menuContainerRef.value.querySelector(
    ".layout-root-menuitem.active-menuitem",
  );
  if (!activeMenuItem) return;

  observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        if (
          isDesktop() &&
          !entry.isIntersecting &&
          hasOverlaySubmenu.value &&
          layoutState.activePath
        ) {
          layoutState.activePath = null;
        }
      });
    },
    {
      root: menuContainerRef.value,
      threshold: 0,
    },
  );

  observer.observe(activeMenuItem);
};

const unbindObserver = () => {
  if (observer) {
    observer.disconnect();
    observer = null;
  }
};

mediaQuery.addEventListener("change", screenChangeListener);

onBeforeUnmount(() => {
  unbindOutsideClickListener();
  unbindObserver();
  mediaQuery.removeEventListener("change", screenChangeListener);
});

const sidebarLogoSrc = computed(() => {
  if (shouldCollapseSidebar.value) return logoDiapositiefCompact;
  return layoutConfig.menuTheme === "light" ? logoDark : logoDiapositief;
});
</script>

<template>
  <div
    ref="sidebarRef"
    class="layout-sidebar h-screen flex flex-col overflow-hidden"
  >
    <div class="sidebar-header flex-shrink-0">
      <router-link :to="{ name: 'dashboard' }" class="logo">
        <img class="logo-image" :src="sidebarLogoSrc" alt="Company Logo" />
      </router-link>
      <button
        v-if="showPinButton"
        class="layout-sidebar-pin"
        :class="{ pinned: isAnchored }"
        type="button"
        :aria-label="isAnchored ? 'Unpin sidebar' : 'Pin sidebar'"
        @click="onAnchorToggle"
      >
        <i class="pi pi-thumbtack" />
      </button>
    </div>
    <div
      ref="menuContainerRef"
      class="layout-menu-container flex-1 min-h-0 overflow-y-auto flex flex-col"
      @scroll="onMenuScroll"
    >
      <AppMenu />
    </div>
    <AppTopbar v-if="isHorizontal" />
  </div>
</template>
