import './index.scss'

import { NMenu, NLayoutSider, NDrawer } from 'naive-ui'
import SiderBarLogo from './components/SiderBarLogo'

import { LAYOUT_SIDER_REF } from '@/app-config'
import { useDevice } from '@/hooks'
import { getVariableToRefs, setVariable } from '@/global-variable'
import { useMenuGetters, useMenuActions, useSettingGetters } from '@/store'

import type { MenuInst } from 'naive-ui'
import type { NaiveMenuOptions } from '@/types'
import type { AppMenuOption } from '@/types'

export default defineComponent({
  name: 'AppMenu',
  setup() {
    const menuRef = ref<MenuInst | null>(null)

    const { changeMenuModelValue, collapsedMenu, updateMenuState } =
      useMenuActions()
    const { getMenuConfig } = useSettingGetters()
    const { getMenuOptions, getCollapsed, getMenuKey } = useMenuGetters()
    const modelMenuKey = computed({
      get: () => {
        // eslint-disable-next-line vue/no-async-in-computed-properties
        setTimeout(() => {
          /**
           *
           * @description
           * 禁用该 eslint 规则，因为在 computed 中使用了异步操作。
           * 该规则只是为了避免异步的 computed get 获取值出现问题；
           * 但是，在这里获取值的操作是同步行为，只是为了在获取值以后将对应菜单项展开；
           * 所以，这里不会出现异步获取值的问题，所以可以禁用该规则。
           */
          showMenuOption()
        }, 300)

        return getMenuKey.value
      },
      set: () => {
        if (isTabletOrSmaller.value) {
          setVariable('globalDrawerValue', false)
        }
      },
    })
    const { isTabletOrSmaller } = useDevice({
      observer: (isSmaller) => {
        if (isSmaller) {
          // 避免菜单折叠时，在小尺寸屏幕导致菜单显示不完整
          updateMenuState('collapsed', false)
        }
      },
    })
    const modelGlobalDrawerValue = computed({
      get: () => getVariableToRefs('globalDrawerValue').value,
      set: (val) => {
        setVariable('globalDrawerValue', val)
      },
    })

    /**
     *
     * @description
     * 手动展开当前激活菜单项。
     */
    const showMenuOption = () => {
      const key = modelMenuKey.value

      if (key !== void 0 && key !== null) {
        nextTick(() => menuRef.value?.showOption?.(key))
      }
    }

    const BasicMenu = () => (
      <NLayoutSider
        class="app-menu__sider"
        showTrigger={!isTabletOrSmaller.value}
        collapseMode={getMenuConfig.value.collapsedMode}
        collapsedWidth={getMenuConfig.value.collapsedWidth}
        onUpdateCollapsed={collapsedMenu.bind(this)}
        width={getMenuConfig.value.menuWidth}
        nativeScrollbar={getMenuConfig.value.nativeScrollbar}
        ref={LAYOUT_SIDER_REF}
        collapsed={getCollapsed.value}
        onExpand={() => {
          updateMenuState('collapsed', false)
        }}
        onCollapse={() => {
          updateMenuState('collapsed', true)
        }}
        inverted={getMenuConfig.value.inverted}
      >
        {getMenuConfig.value.menuSiderBarLogo ? (
          <SiderBarLogo collapsed={getCollapsed.value} />
        ) : null}
        <NMenu
          ref={menuRef}
          class="r-menu--app"
          keyField="fullPath"
          v-model:value={modelMenuKey.value}
          options={getMenuOptions.value as NaiveMenuOptions[]}
          indent={getMenuConfig.value.collapsedIndent}
          collapsed={getCollapsed.value}
          collapsedIconSize={getMenuConfig.value.collapsedIconSize}
          collapsedWidth={getMenuConfig.value.collapsedWidth}
          onUpdateValue={(key, op) => {
            changeMenuModelValue(key, op as unknown as AppMenuOption)
          }}
          accordion={getMenuConfig.value.accordion}
          iconSize={getMenuConfig.value.iconSize}
          inverted={getMenuConfig.value.inverted}
        />
      </NLayoutSider>
    )

    return {
      isTabletOrSmaller,
      BasicMenu,
      modelGlobalDrawerValue,
    }
  },
  render() {
    const { isTabletOrSmaller, BasicMenu } = this

    return !isTabletOrSmaller ? (
      <BasicMenu />
    ) : (
      <NDrawer
        class="app-menu__drawer"
        v-model:show={this.modelGlobalDrawerValue}
        placement="left"
        displayDirective="show"
        autoFocus={false}
      >
        <BasicMenu />
      </NDrawer>
    )
  },
})
