<script setup lang="ts">
import { px2vh } from '@/utils'

// interface selectType {
//   label: string
//   value: string | number
// }
const props = withDefaults(
  defineProps<{
    modelValue: any
    selectList: any
    labelKey?: string
    valueKey?: string
    width?: any
    height?: any
  }>(),
  {
    labelKey: 'label',
    valueKey: 'value',
    width: 264,
    height: '5.33vh',
  },
)

const emits = defineEmits(['update:modelValue', 'selectChange'])
const selectInstanceId = `select_${Math.random().toString(36).slice(2)}`
let widthUnit = 'px'
let widthValue = 0
if (typeof props.width === 'string') {
  const tmpWidth = Number(props.width)
  if (isNaN(tmpWidth)) {
    // 字符串中有单位
    widthUnit = props.width.slice(-2)
    widthValue = Number(props.width.slice(0, -2))
  } else {
    // 字符串中没有单位
    widthValue = tmpWidth
  }
} else {
  widthValue = props.width
}
let contentWidthS = ''
let listWidthS = ''
if (widthUnit === 'px') {
  contentWidthS = px2vh(widthValue)
  listWidthS = px2vh(widthValue - 12)
} else {
  contentWidthS = widthValue + widthUnit
  listWidthS = widthValue - 1 + widthUnit
}

const contentHeightS = props.height

const OSS_URL = `${import.meta.env.VITE_OSS_URL}`
const bg = `url(${OSS_URL}/icon/select.svg) 100% / contain  no-repeat`
const bg2 = `url(${OSS_URL}/icon/check_mark.svg) 100% / contain no-repeat`

const showSelect = ref(false) // 是否显示下拉框
const activeSelect = ref({} as any)
const active = computed({
  get() {
    activeSelect.value =
      props.selectList.find((i: any) => i[props.valueKey] === props.modelValue) || {}
    return props.modelValue
  },
  set(val) {
    emits('update:modelValue', val)
  },
})
watch(
  () => props.selectList,
  _nv => {
    if (props.selectList && props.selectList[0] && !props.modelValue) {
      // 默认激活列表中第一项
      active.value = props.selectList[0][props.valueKey]
    }
  },
  {
    deep: true,
    immediate: true,
  },
)

function closeSelect() {
  showSelect.value = false
}

const handleGlobalSelectOpen = (event: Event) => {
  const customEvent = event as CustomEvent<string>
  if (customEvent.detail !== selectInstanceId) {
    closeSelect()
  }
}

function toggleSelect() {
  const nextState = !showSelect.value
  if (nextState) {
    window.dispatchEvent(new CustomEvent('xuexiaole-select-open', { detail: selectInstanceId }))
  }
  showSelect.value = nextState
}

onMounted(() => {
  window.addEventListener('xuexiaole-select-open', handleGlobalSelectOpen as EventListener)
})

onUnmounted(() => {
  window.removeEventListener('xuexiaole-select-open', handleGlobalSelectOpen as EventListener)
})

const selectChange = (item: any) => {
  if (active.value === item[props.valueKey]) return
  activeSelect.value = item
  closeSelect()
  active.value = item[props.valueKey]
  emits('selectChange', activeSelect.value)
}
</script>

<template>
  <div :class="['select-box', { open: showSelect }]">
    <div class="content" @click="toggleSelect">
      <span>{{ activeSelect[labelKey] }}</span
      ><span
        :class="{ icon: true, iconActive: showSelect }"
        :style="{
          background: bg,
        }"
      >
      </span>
    </div>
    <div v-show="showSelect" class="selectList">
      <div class="selectList-box hidden_scroll">
        <div
          v-for="item in selectList"
          :key="item[valueKey]"
          :class="{ 'select-item': true, active: item[valueKey] === active }"
          @click="selectChange(item)"
        >
          <span>
            {{ item[labelKey] }}
          </span>
          <span
            v-show="item[valueKey] === active"
            class="icon"
            :style="{
              background: bg2,
            }"
          >
          </span>
        </div>
      </div>
    </div>
    <div v-show="showSelect" class="mask" @click="closeSelect"></div>
  </div>
</template>

<style scoped lang="scss">
//
.select-box {
  position: relative;
  z-index: 1;
  font-family: $font-text;
  font-size: 2.33vh;
  color: #ffffffd9;

  &.open {
    z-index: 1100;
  }

  line-height: 4vh;
  .content {
    background: #00000099;
    width: v-bind(contentWidthS);
    height: v-bind(contentHeightS);
    border-radius: 1.67vh;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 20px;
    box-sizing: border-box;
    cursor: pointer;

    span {
      @include single_ellipsis;
    }

    .icon {
      transition: all 0.3s;
      height: 2.33vh;
      width: 2.92vh;
    }
    .iconActive {
      transform: rotate(180deg);
    }
  }
  .selectList {
    width: v-bind(contentWidthS);
    max-height: 24.67vh;
    background: #4f5458;
    margin-top: 0.83vh;
    position: absolute;
    z-index: 1101;
    border-radius: 1.67vh;
    box-sizing: border-box;
    padding: 0.42vh;
    border: 1px solid #5f676d;
  }
  .selectList-box {
    width: v-bind(listWidthS);
    max-height: 23.83vh;
    overflow: scroll;
    padding: 1.25vh;
    box-sizing: border-box;
    .select-item {
      display: flex;
      align-items: center;
      color: #ccd4d4;
      width: 100%;
      padding: 0.42vh 0;
      justify-content: space-between;
      cursor: pointer;
      font-size: 2.33vh;
      .icon {
        width: 32px;
        height: 2.67vh;
        // background-size: contain;
      }
      &.active {
        color: #fff;
      }
    }
  }
  .mask {
    position: absolute;
    height: 200vh;
    width: 200vw;
    z-index: 1100;
    left: -100vw;
    top: -100vh;
  }
}
</style>
