<script setup lang="ts">
import type { CheckboxValueType } from 'element-plus'

const props = withDefaults(
  defineProps<{
    modelValue: any[]
    options: any[]
    labelKey?: string
    valueKey?: string
  }>(),
  {
    labelKey: 'label',
    valueKey: 'value',
  },
)

const emit = defineEmits(['update:modelValue'])

defineOptions({ name: 'MjCheckGroup' })

const value = computed({
  get: () => props.modelValue,
  set: val => emit('update:modelValue', val),
})

// 勾选了去哪不
const checkAll = ref(false)
// 勾选了部分
const isIndeterminate = ref(false)
// 勾选的value
const checkedMap = ref({} as any)

function handleCheckAll(val: CheckboxValueType) {
  for (const op of props.options) {
    checkedMap.value[op[props.valueKey]] = val
  }
  _map2values()
}

// 用户操作数据 -> 外部数据
function _map2values() {
  const vals = [] as any
  for (const id in checkedMap.value) {
    if (checkedMap.value[id]) {
      vals.push(id)
    }
  }
  value.value = vals
}

// 更新【全选】的状态
function _updateCheckAllStatus() {
  let checkedCount = 0
  for (const op of props.options) {
    // 勾选了
    if (checkedMap.value[op[props.valueKey]]) {
      checkedCount++
    }
  }

  checkAll.value = checkedCount === props.options.length
  isIndeterminate.value = checkedCount > 0 && checkedCount < props.options.length
}

// 数据流向
// 1.界面操作 -> checkedMap -> value -> checkedMap
// 2.外部数据传递 -> value -> checkedMap -> 界面显示
watch(
  [() => value.value, () => props.options],
  () => {
    if (!props.options.length) return

    // 控制界面显示
    checkedMap.value = {}
    for (const val of value.value) {
      checkedMap.value[val] = true
    }

    _updateCheckAllStatus()
  },
  {
    immediate: true,
  },
)

// watch(
//   () => props.options,
//   () => {
//     if (!props.options.length) return

//     _updateCheckAllStatus()
//   },
// )
</script>

<template>
  <div class="mj-check-group">
    <mj-check
      v-model="checkAll"
      class="check-all"
      label="全选"
      :indeterminate="isIndeterminate"
      @change="handleCheckAll"
    />
    <mj-check
      v-for="op in options"
      :key="op[valueKey]"
      v-model="checkedMap[op[valueKey]]"
      :value="op[valueKey]"
      :label="op[labelKey]"
      @change="_map2values"
    />
  </div>
</template>

<style lang="scss" scoped>
.check-all {
  :deep(.label) {
    color: #3894ff !important;
  }
}

.mj-check-group {
  display: flex;
  flex-wrap: wrap;
  column-gap: 24px;
  row-gap: 1.33vh;
  padding: 0.67vh 0;
}
</style>
