<script lang="ts" setup>
import {
  computed,
  inject,
  nextTick,
  onBeforeMount,
  onMounted,
  reactive,
  ref,
  shallowRef,
  unref,
  watch,
} from "vue";
import { CustomFilterModalVue, FilterModal, NewFilterModal } from "@/views/final/comp";
import Search from "@/views/home/aside/comp/Search.vue";
import AdvanceFilter from "@/views/home/aside/comp/AdvanceFilter.vue";
import { getViewportOffset } from "@/utils/domUtils";
import { useWindowSizeFn } from "@/hooks/event/useWindowSizeFn";
import { useFinal } from "@/store/modules/final";
import type { Filter } from "/#/home";
import type { AsideEntity } from "@/config/aside";
import { asideMap } from "@/config/final";
import type { AsideConfig } from "/#/api";
import emitter from "@/utils/mitt";

const emit = defineEmits(["inputChange"]);
const finalStore = useFinal();
// 所有左侧模块的值
const asideValue: Record<keyof typeof asideMap, any> = reactive({});
// 左侧某个模块是否显示: 个人配置
const asideVisible: Partial<Record<keyof AsideConfig, boolean>> = reactive({});
// 当前显示的模块，按照数组顺序显示
const showItems = shallowRef<{ key: string; config: AsideEntity }[]>([]);

Object.keys(asideMap).forEach((key) => {
  const { defaultValue, inFilterList } = asideMap[key];
  if (inFilterList !== false) asideValue[key] = defaultValue;
});

const filterModalRef = ref(null);
const newFilterModalRef = ref(null);
const customModalRef = ref(null);
const AdvanceFilterRef: any = ref(null);

function showModal(modalRef: any) {
  const modal = unref(modalRef)! as any;
  modal.showModal();
}
const mousetrap = inject("mousetrap") as any;
mousetrap.bind("[", collapseHandler);

onMounted(() => {
  nextTick(() => {
    computeSlideHeight();
  });
});

const collapse = ref(false);

function collapseHandler() {
  collapse.value = !collapse.value;
}

const asideWidth = computed(() => {
  return collapse.value ? 0 : 308;
});

const asideHeight = ref(500);
const asideStyle = computed(() => {
  return {
    width: `${asideWidth.value}px`,
    height: `${asideHeight.value}px`,
  };
});

const collapseIcon = computed(() => {
  return collapse.value ? "expand-cir" : "collapse-cir";
});

function computeSlideHeight() {
  const headEl = document.querySelector(".aside-header")!;
  const { bottomIncludeBody } = getViewportOffset(headEl);
  const height = bottomIncludeBody;
  asideHeight.value = height - 24;
}

useWindowSizeFn(computeSlideHeight, 280);

onBeforeMount(async () => {
  finalStore.fetchCustomConfig();
});

finalStore.$subscribe(() => {
  const customConfig = finalStore.getCustomConfig;

  if (customConfig === null) return;

  const showKeys: string[] = [...customConfig];
  const defaultKeys = Object.keys(asideMap).filter(
    (key) => asideMap[key].isDefaultFilter
  );
  showKeys.unshift(...defaultKeys);

  Object.keys(asideMap).forEach((key) => {
    // 设置显示的或者默认显示的
    if (key.startsWith("iz"))
      asideVisible[key] =
        asideMap[key] && (showKeys.includes(key) || asideMap[key].isDefaultFilter);
  });

  const items = showKeys.reduce((acc, key) => {
    if (asideMap[key]) {
      const config = {
        key,
        config: asideMap[key],
      };
      return [...acc, config];
    } else {
      return acc;
    }
  }, []);

  showItems.value = items;
});

watch(asideVisible, (newVal) => {
  Object.keys(asideValue).forEach((key) => {
    if (newVal[key] === false) asideValue[key] = asideMap[key].defaultValue;
  });
});

const asideEnter = ref(false);

const showCollapse = computed(() => {
  return collapse.value ? true : asideEnter.value;
});

const showSearch = ref(false);

function setShowSearch(value: boolean) {
  showSearch.value = value;
  if(!value){
    inputChange('')
  }
}

// 滚动容器，让key对应模块处于可视区域
function scrollHandler(key: string) {
  const element = document.querySelector(`#${key}`);
  element?.scrollIntoView(true);
}

function filterHandler(searchId: string) {
  emitter.emit("filter-final", searchId);
}

function editFilter(filter: any) {
  const modal = unref(newFilterModalRef)! as any;
  modal.showModal();
  modal.edit(filter);
}

watch(asideValue, (newVal) => {
  finalStore.setAsideValue(newVal);
});

const inputChange = (keyword) => {
  emit("inputChange", keyword);
};
const handleOk = (item: any) => {
  console.log("handleOk", item);
  if (item) {
    AdvanceFilterRef.value.setCurrentlySelectedAdvanced(item.searchname);
    filterHandler(item.id);
  } else {
    AdvanceFilterRef.value.setCurrentlySelectedAdvanced("高级筛选");
    filterHandler("");
  }
};
</script>

<template>
  <div
    class="aside"
    :style="asideStyle"
    @mouseenter="asideEnter = true"
    @mouseleave="asideEnter = false"
  >
    <div v-show="showCollapse" class="aside-collapse">
      <div class="aside-collapse-btn" @click="collapseHandler">
        <SvgIcon :name="collapseIcon" size="40" />
      </div>
    </div>
    <n-scrollbar trigger="none">
      <div class="aside-header">
        <!-- 搜索跳转模块 -->
        <Search
          v-show="showSearch"
          @select="scrollHandler"
          @close="setShowSearch(false)"
          @inputChange="inputChange"
        />
        <!-- 高级筛选 -->
        <AdvanceFilter
          v-show="!showSearch"
          :type="1"
          @select="filterHandler"
          @update:search="setShowSearch(true)"
          @show-custom="showModal(customModalRef)"
          @show-filter="showModal(filterModalRef)"
          ref="AdvanceFilterRef"
        />
      </div>

      <component
        :is="item.config.component"
        v-for="(item, index) in showItems"
        :id="item.key"
        :key="index"
        v-model:value="asideValue[item.key]"
        :label="item.config.label"
      />

      <!-- 筛选 -->
      <CustomFilterModalVue ref="customModalRef" />
      <!-- 过滤列表 -->
      <FilterModal
        ref="filterModalRef"
        @edit-filter="editFilter"
        @show-new-filter="showModal(newFilterModalRef)"
        @handleOk="handleOk"
      />
      <!-- 新增过滤 -->
      <NewFilterModal ref="newFilterModalRef" />
    </n-scrollbar>
  </div>
</template>

<style lang="less" scoped>
.aside {
  display: flex;
  position: relative;
  flex-direction: column;
  background: #fff;
  border: 1px solid #efeff5;
  border-radius: 3px;
  box-sizing: border-box;

  &-header {
    padding: 10px;
    width: 100%;
    border-bottom: 1px solid #e8e8e8;
    margin-bottom: 15px;
    height: 58px
  }

  &-divider {
    width: 100%;
    height: 1px;
    background-color: #e8e8e8;
  }

  &-collapse {
    width: 2px;
    height: 100%;
    background: #507afd;
    position: absolute;
    right: -2px;
    top: 0;
    z-index: 18;
  }

  &-collapse-btn {
    position: absolute;
    cursor: pointer;
    width: 40px;
    height: 40px;
    top: calc(15%);
    right: -20px;
  }

  ::v-deep(.n-collapse
      .n-collapse-item.n-collapse-item--right-arrow-placement
      .n-collapse-item__header
      .n-collapse-item-arrow) {
    margin-left: 8px;
  }

  ::v-deep(.n-collapse
      .n-collapse-item
      .n-collapse-item__header
      .n-collapse-item__header-main) {
    font-weight: bold;
    justify-content: space-between;
  }

  ::v-deep(.n-collapse .n-collapse-item .n-collapse-item__header) {
    padding: 0px;
  }

  ::v-deep(.n-collapse .n-collapse-item:not(:first-child)) {
    border-top: 0px;
  }

  ::v-deep(.n-collapse
      .n-collapse-item
      .n-collapse-item__content-wrapper
      .n-collapse-item__content-inner) {
    padding-top: 10px;
  }

  ::v-deep(.n-scrollbar
      > .n-scrollbar-rail.n-scrollbar-rail--vertical
      > .n-scrollbar-rail__scrollbar, .n-scrollbar
      + .n-scrollbar-rail.n-scrollbar-rail--vertical
      > .n-scrollbar-rail__scrollbar) {
    width: 0px;
  }
}
</style>
