<script setup lang="ts">
import {
  Cell as VanCell,
  CellGroup as VanCellGroup,
  Checkbox as VanCheckbox,
  CheckboxGroup as VanCheckboxGroup,
  Field as VanField,
  Popup as VanPopup,
  Search as VanSearch,
} from 'vant'
import { computed, onBeforeUnmount, ref, watch } from 'vue'

const props = withDefaults(defineProps<{
  columns?: any[]
  selectValue?: any[]
  option?: Record<string, string>
  isSearch?: boolean // 是否支持搜索
  lazyLoad?: string // 是否启用懒加载
  onSearch?: ((searchValue: string) => Promise<any[]>) | null // 懒加载时的搜索函数
}>(), {
  columns: () => [],
  selectValue: () => [],
  option: () => ({ text: 'label', value: 'value' }),
  isSearch: true,
  lazyLoad: 'false',
  onSearch: null,
})
const emits = defineEmits(['input', 'confirm', 'change', 'cancel'])
const show = ref(false)
const searchVal = ref('')
const columnsData = ref([])
const checkboxValue = ref(JSON.parse(JSON.stringify(props.selectValue)))
const checkedAll = ref(false)
const resultValue = defineModel()
const checkboxGroup = ref()
const checkboxes = ref()
const isLoading = ref(false)
function search(val) {
  // 如果是懒加载模式
  if (props.lazyLoad && props.lazyLoad === 'true' && props.onSearch) {
    isLoading.value = true
    // 调用父组件传递的搜索函数
    props.onSearch(val).then((results) => {
      columnsData.value = results || []
      isLoading.value = false
    }).catch((error) => {
      console.error('懒加载搜索失败:', error)
      columnsData.value = []
      isLoading.value = false
    })
    return
  }

  // 普通搜索模式
  if (val) {
    columnsData.value = props.columns.filter((item) => {
      return item[props.option.text].includes(val)
    })
  }
  else {
    columnsData.value = JSON.parse(JSON.stringify(props.columns))
  }
}
function getData(val) {
  const res = props.columns.filter((item) => {
    return val?.includes(item[props.option.value])
  })
  return res
}
function onConfirm() {
  resultValue.value = checkboxValue.value
  show.value = !show.value
  emits('confirm', resultValue.value, getData(resultValue.value))
}
function change(val) {
  emits('change', val, getData(resultValue.value))
}
function cancel() {
  show.value = !show.value
  emits('cancel', resultValue.value)
}
function toggle(item, _index) {
  // 假设 checkboxValue 是一个对象，我们通过 index 来切换对应 checkbox 的值
  const idx = checkboxValue.value.indexOf(item[props.option.value])
  if (idx !== -1)
    checkboxValue.value.splice(idx, 1)
  else
    checkboxValue.value.push(item[props.option.value])
}
function toggleAll() {
  // 遍历 checkboxValue 并设置所有 checkbox 的值为 checkedAll 的值
  if (checkedAll.value)
    checkboxValue.value = columnsData.value.map(item => item[props.option.value])

  else
    checkboxValue.value = []
}
function showPopu(disabled) {
  columnsData.value = JSON.parse(JSON.stringify(props.columns))
  checkboxValue.value = JSON.parse(JSON.stringify(props.selectValue))
  if (disabled !== undefined && disabled !== false)
    return false
  else
    show.value = !show.value
}
watch(() => columnsData.value, (newVal, _oldVal) => {
  checkedAll.value = newVal.length && newVal.length === checkboxValue.value.length
})
const stopWatchCheckboxValue = watch(() => checkboxValue.value.length, (newVal, _oldVal) => {
  checkedAll.value = newVal && newVal === columnsData.value.length
})

onBeforeUnmount(() => {
  stopWatchCheckboxValue()
  show.value = false
})
const resultLabel = computed(() => {
  const res = props.columns.filter((item) => {
    return (resultValue.value as unknown as string[])?.includes(item[props.option.value])
  }).map(item => item[props.option.text])
  return res.join(',')
})
</script>

<template>
  <div class="x-multi-select">
    <VanField
      v-model="resultLabel"
      v-bind="$attrs"
      readonly
      :border="false"
      :is-link="$attrs.disabled === undefined"
      @click="showPopu($attrs.readonly)"
    />
    <VanPopup v-model:show="show" position="bottom" teleport="body" round>
      <div class="x-multi-select-popup">
        <div class="van-picker__toolbar">
          <button type="button" class="van-picker__cancel" @click="cancel">
            取消
          </button>
          <div class="van-ellipsis van-picker__title">
            {{ $attrs.label }}
          </div>
          <button type="button" class="van-picker__confirm" @click="onConfirm">
            确认
          </button>
        </div>
        <div class="x-multi-select-content">
          <VanSearch
            v-if="props.isSearch"
            v-model="searchVal"
            placeholder="搜索"
            @update:model-value="search"
            @cancel="search"
          />
          <div v-if="isLoading" class="loading-container">
            <div class="loading-text">
              搜索中...
            </div>
          </div>
          <div v-else class="x-multi-select-checkbox-group">
            <VanCell title="全选">
              <template #right-icon>
                <VanCheckbox v-model="checkedAll" name="all" @click="toggleAll" />
              </template>
            </VanCell>
            <VanCheckboxGroup ref="checkboxGroup" v-model="checkboxValue" @change="change">
              <VanCellGroup>
                <VanCell
                  v-for="(item, index) in columnsData"
                  :key="item[props.option.value]"
                  :title="item[props.option.text]"
                  clickable
                  @click="toggle(item, index)"
                >
                  <template #right-icon>
                    <VanCheckbox ref="checkboxes" :name="item[props.option.value]" @click.stop />
                  </template>
                </VanCell>
              </VanCellGroup>
            </VanCheckboxGroup>
          </div>
        </div>
      </div>
    </VanPopup>
  </div>
</template>

<style lang="less" scoped>
.x-multi-select {
  width: 100%;
  padding: 0;
  background: #fff;
  .dh-cell.van-cell {
    padding: 10px 16px;
  }
  .dh-cell.van-cell--required::before {
    left: -8px;
  }
  .x-multi-select-content {
    max-height: calc(70vh - 44px);
    overflow-y: auto;
    .x-multi-select-checkbox-group {
      padding: 0 16px;
    }
  }
  .x-multi-select-popup {
    max-height: 70vh;
    padding-bottom: env(safe-area-inset-bottom);
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  .loading-container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 200px;
  }
  .loading-text {
    color: #969799;
    font-size: 14px;
  }
  //.van-popup {
  //  border-radius: 20px 20px 0 0;
  //}
}
</style>
