<template>
  <el-select class="custom-select" @change="selChange" @clear="selClear">
    <el-option-group
      v-for="(group, index) in renderOptions.groups"
      :key="'group-' + index"
      v-bind="omit(group, ['options'])"
    >
      <el-option
        v-for="(option, OIndex) in group.options"
        :key="'group-' + index + '-option-' + OIndex"
        v-bind="omit(option, 'groupKey')"
      ></el-option>
    </el-option-group>
    <el-option
      v-for="(option, OIndex) in renderOptions.default"
      :key="'group-default' + '-option-' + OIndex"
      v-bind="omit(option, 'groupKey')"
    ></el-option>
  </el-select>
</template>

<script setup lang="ts" name="EpSelect">
import { computed } from 'vue'
import { ElSelect, ElOption, ElOptionGroup } from 'element-plus'
import { omit } from 'lodash-es'
import type { FormItemSelectCustomProp } from 'global-type'

interface SelectProp {
  optionGroup?: Required<FormItemSelectCustomProp>['optionGroup']
  options?: Required<FormItemSelectCustomProp>['options']
}
const emits = defineEmits(['change', 'clear'])
const props = defineProps<SelectProp>()

type OptionGroup = ExtractRecordValue<SelectProp['optionGroup']> & { options: SelectProp['options'] }

type OptionRender = { default: SelectProp['options']; groups: Record<string | number, OptionGroup> }

const renderOptions = computed<OptionRender>(() => {
  const groups = props.options?.reduce(
    (result, option, index) => {
      if (option.groupKey) {
        if (!result.groups[option.groupKey]) {
          result.groups[option.groupKey] = { ...props.optionGroup?.[option.groupKey], options: [] }
        }
        result.groups[option.groupKey]?.options?.push(option)
      } else {
        result.default ??= []
        result.default.push(option)
      }
      return result
    },
    { default: [], groups: {} } as OptionRender
  )
  return groups || { default: [], groups: {} }
})
const selChange = (index: any) => {
  emits('change', index)
}
const selClear = () => {
  emits('clear')
}
</script>

<style scoped lang="scss">
.custom-select {
  // ElSelect Bug: select 中 input高度被硬编码在代码中，它会使用element-plus中定义的常量component-size-map, 而不是sass变量 $common-component-size。
  // 目前的修改方式有两个:
  //  1. 设置props: collapse-tags = true & filterable = false
  //  2. 使用 !important 强制覆盖.
  // 为了不过度限制组件功能, 当前使用 css !important. (在组件用到多选tag功能时可能样式异常)

  :deep(.el-input__inner) {
    height: var(--el-input-inner-height) !important;
    line-height: var(--el-input-inner-height) !important;
  }
}
</style>
