<script setup lang="ts">
import Hummer from "#adata-ui/icons/hummer.vue";
import Work from "#adata-ui/icons/work.vue";
import Company from "#adata-ui/icons/company.vue";
import Car from "#adata-ui/icons/car.vue";
import IconArrowGraph from "#adata-ui/icons/arrow/arrow-graph-up.vue";
import IconSearch from "#adata-ui/icons/search.vue"
import IconUsers from "#adata-ui/icons/users.vue";
import IconDocument from "#adata-ui/icons/hdocument.vue";
import IconArrowCircle from "#adata-ui/icons/arrow/arrow-circle-down.vue";
import IconScales from "#adata-ui/icons/scales/scale.vue";
import IconLink from "#adata-ui/icons/link-chain.vue";
import IconGlobe from "#adata-ui/icons/globe.vue";
import IconBlock from "#adata-ui/icons/block.vue";
import IconWork from "#adata-ui/icons/work-bag.vue";
import IconDollar from "#adata-ui/icons/currency/currency-dollar.vue";
import IconFile from "#adata-ui/icons/file/file.vue";
import IconCheck from "#adata-ui/icons/hcheck.vue";
import IconCheckCircle from "#adata-ui/icons/check/check-circle.vue";
import IconCar from "#adata-ui/icons/car.vue";
import IconTruck from "#adata-ui/icons/truck.vue";
import IconCompany from "#adata-ui/icons/company.vue";
import IconMedal from "#adata-ui/icons/medal.vue";

import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock'
import {PAGES} from "#adata-ui/shared/constans/pages";

type Modules = 'counterparty' | 'work' | 'tender' | 'fines' | 'analytics'

interface Props {
  topMargin?: number
  width?: string
  panelDuration: number
  overlayDuration: number
  zIndex: number | string
}

const props = withDefaults(defineProps<Props>(), {
  topMargin: 0,
  width: 'auto',
  panelDuration: 300,
  overlayDuration: 500,
  zIndex: 'auto'
})
const { myLayer }: any = useAppConfig()

const activeModule = ref<Modules | null>(null)
const bottom = ref<HTMLElement | null>(null)
const bottomHeight = ref(0)
const windowHeight = ref(0)
const open = ref(!!activeModule.value)

const calculateSize = () => {
  if (window?.innerHeight > 0) windowHeight.value = window.innerHeight

  bottomHeight.value = bottom.value ? bottom.value.clientHeight : 0
}

const sidebarHeight = computed(() => {
  if (!windowHeight.value) return

  return  windowHeight.value - props.topMargin - bottomHeight.value
})

const menu = ref<HTMLElement | null>(null)
const isBodyAlreadyLocked = ref<boolean>(false)
const zIndex = ref()
const items = [
  {
    label: "Контрагенты",
    icon: Company,
    value: "counterparty"
  },
  {
    label: "Работа",
    icon: Work,
    value: "work"
  },
  {
    label: "Тендеры",
    icon: Hummer,
    value: "tender"
  },
  {
    label: "Штрафы",
    icon: Car,
    value: "fines"
  },
  {
    label: "Аналитика",
    icon: IconArrowGraph,
    value: "analytics"
  }
]

const sideLinks = {
  counterparty: [
    {
      icon: IconSearch,
      label: "Проверка контрагентов",
      link: myLayer.pkUrl + PAGES.pk.main
    },
    {
      icon: IconScales,
      label: "Сравнение контрагентов",
      link: myLayer.counterParty ?  myLayer.pkUrl + myLayer.counterParty + PAGES.pk.compare : myLayer.pkUrl + PAGES.pk.compare
    },
    {
      icon: IconLink,
      label: "Косвенные связи",
      link: myLayer.counterParty ?  myLayer.pkUrl + myLayer.counterParty + '/search-connections/check' : myLayer.pkUrl + PAGES.pk.connections
    },
    {
      icon: IconUsers,
      label: "Массовая проверка",
      link: myLayer.counterParty ?  myLayer.pkUrl + myLayer.counterParty + PAGES.pk.employees : myLayer.pkUrl + PAGES.pk.employees
    },
    {
      icon: IconGlobe,
      label: "Зарубежные контрагенты",
      link: myLayer.pkUrl + PAGES.pk.foreign
    },
    {
      icon: IconBlock,
      label: "Санкции",
      link: myLayer.counterParty ?  myLayer.pkUrl + myLayer.counterParty + PAGES.pk.sanctions : myLayer.pkUrl + PAGES.pk.sanctions
    },
    {
      icon: IconDollar,
      label: "Офшоры",
      link: myLayer.counterParty ?  myLayer.pkUrl + myLayer.counterParty + PAGES.pk.offshore : myLayer.pkUrl + PAGES.pk.offshore
    },
    {
      icon: IconDocument,
      label: "Экспресс проверка",
      link: "#"
    },
    {
      icon: IconArrowCircle,
      label: "Выгрузка данных",
      link: myLayer.pkUrl + PAGES.pk.unload
    }
  ],
  work: [
    {
      icon: IconWork,
      label: "Вакансии",
      link: myLayer.workUrl + PAGES.work.vacancy
    },
    {
      icon: IconDocument,
      label: "Резюме",
      link: myLayer.workUrl + PAGES.work.summary
    },
  ],
  tender: [
    {
      icon: IconSearch,
      label: "Поиск тендеров",
      link: myLayer.tenderUrl + PAGES.tender.main
    },
    {
      icon: IconFile,
      label: "Поиск договоров",
      link: myLayer.tenderUrl + PAGES.tender.contracts
    },
    {
      icon: IconCheck,
      label: "Планы закупок",
      link: myLayer.tenderUrl + PAGES.tender.plans
    }
  ],
  fines: [
    {
      icon: IconCheckCircle,
      label: "Проверка штрафов",
      link: myLayer.avtoUrl + PAGES.fines.main
    },
    {
      icon: IconCar,
      label: "Проверка авто",
      link: myLayer.avtoUrl + PAGES.fines.avto
    },
    {
      icon: IconTruck,
      label: "Массовая проверка авто",
      link: myLayer.avtoUrl + PAGES.fines.bulk
    }
  ],
  analytics: [
    {
      icon: IconSearch,
      label: "Поиск клиентов",
      link: myLayer.analyticsUrl + PAGES.analytics.clients
    },
    {
      icon: IconCheck,
      label: "Анализ закупок",
      link: myLayer.analyticsUrl + PAGES.analytics.analysis
    },
    {
      icon: IconArrowGraph,
      label: "Индекс деловой активности",
      link: myLayer.analyticsUrl + PAGES.analytics.index
    },
    {
      icon: IconCompany,
      label: "Субьекты бизнеса",
      link: myLayer.analyticsUrl + PAGES.analytics.business
    },
    {
      icon: IconMedal,
      label: "Рейтинг налогоплательщиков",
      link: myLayer.analyticsUrl + PAGES.analytics.rating
    }
  ],
}
const currentLinks = ref(sideLinks.counterparty)

const getMaxZIndex = () =>
  Math.max(
    ...Array.from(document.querySelectorAll('body *'), (el) =>
      parseFloat(window.getComputedStyle(el).zIndex)
    ).filter((zIndex) => !Number.isNaN(zIndex)),
    0
  )

onMounted(() => {
  zIndex.value = props.zIndex === 'auto' ? getMaxZIndex() : props.zIndex
})

const toggleBodyScroll = (el: HTMLBodyElement | HTMLDivElement, lock: boolean) => {
  if (lock) {
    setTimeout(() => {
      disableBodyScroll(el, { reserveScrollBarGap: true })
    }, 0)
    return
  }

  enableBodyScroll(el)
  document.documentElement.style.removeProperty('overflow')
}

watch(() => [
  bottom.value,
  props.topMargin,
  open.value
], () => {
  nextTick(() => calculateSize())
})

watch(
  () => [open.value, menu.value],
  (newVal, oldVal) => {
    const wasShown = oldVal ? oldVal[0] : false
    const [isShown, menuEl] = newVal
    const isOpening = isShown
    const isClosing = wasShown && !isShown

    if (!menuEl) return
    if (isOpening) isBodyAlreadyLocked.value = !!document.body.style.overflow

    if (isShown) {
      toggleBodyScroll(menuEl, true)
      return;
    }

    if (!isClosing || isBodyAlreadyLocked.value) return;

    setTimeout(() => {
      if (menuEl) toggleBodyScroll(menuEl, false)
    }, props.panelDuration)
  })

watch(activeModule, (e) => {
  if (e) {
    currentLinks.value = sideLinks[e]
  }
  open.value = !!e;
})

const overlayStyles = computed(() => ({
  zIndex: zIndex.value,
  animationDuration: `${props.overlayDuration}ms`,
  pointerEvents: !open.value ? 'none' : 'all',
  top: `${props.topMargin}px`,
  bottom: `${bottomHeight.value}px`,
  height: `${sidebarHeight.value}px`,
}))

const panelStyles = computed(() => ({
  zIndex: zIndex.value,
  width: props.width === 'auto' ? '100%': props.width,
  height: `${sidebarHeight.value}px`,
  bottom: `${bottomHeight.value}px`,
  top: `${props.topMargin}px`,
  animationDuration: `${props.panelDuration}ms`
}))
</script>

<template>
  <div class="lg:hidden">
    <Transition name="overlay">
      <div
        v-show="open"
        ref="overlay"
        class="w-full h-full fixed left-0 top-0 backdrop-blur bg-gray-200/20"
        :style="overlayStyles"
        @click="activeModule = null"
      />
    </Transition>
    <Transition name="slide">
      <div
        v-if="open"
        ref="menu"
        class="bg-white dark:bg-gray-900 fixed w-full h-full overflow-y-auto overflow-x-hidden px-4 py-5"
        :style="panelStyles"
      >
        <Transition
          mode="out-in"
          name="module-slide"
        >
          <div :key="activeModule ? activeModule : 0">
            <nuxt-link
              v-for="item in currentLinks"
              :key="item.label"
              :to="item.link"
              class="flex items-center gap-4 px-4 py-3 bg-gray-50 dark:bg-gray-800 mb-2 rounded"
            >
              <component
                :is="item.icon"
                class="w-6 h-6"
              />
              <span>{{ item.label }}</span>
            </nuxt-link>
          </div>
        </Transition>
      </div>
    </Transition>
  </div>
  <div
    ref="bottom"
    class="sticky bottom-0 lg:hidden z-10"
  >
    <a-bottom-navigation
      v-model="activeModule"
      :items="items"
      grow
    />
  </div>
</template>

<style scoped lang="scss">
.slide-enter-active,
.slide-leave-active {
  animation: slide-left;
}

.slide-leave-active {
  animation-direction: reverse;
}

.overlay-enter-active,
.overlay-leave-active {
  animation: overlay-transition;
}

.overlay-leave-active {
  animation-direction: reverse;
}

.module-slide-enter-active,
.module-slide-leave-active {
  transition: .2s ease-in-out;
}

.module-slide-enter-from,
.module-slide-leave-to {
  transform: translateX(50px);
  opacity: 0;
}

@keyframes slide-left {
  0% {
    opacity: 0;
    transform: translateX(-100%);
  }

  100% {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes overlay-transition {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}
</style>
