<template>
  <view class="uni-collapse">
    <slot />
  </view>
</template>

<script setup lang="ts">
import { ref, computed, watch, provide, onMounted, nextTick } from 'vue'

const props = defineProps({
  value: {
    type: [String, Array],
    default: '',
  },
  modelValue: {
    type: [String, Array],
    default: '',
  },
  accordion: {
    // 是否开启手风琴效果
    type: [Boolean, String],
    default: true,
  },
})

const emit = defineEmits(['change', 'activeItem', 'input', 'update:modelValue'])

// 子组件集合
const childrens = ref<any[]>([])
const names = ref<any[]>([])

// 计算当前使用的值（兼容 vue2 和 vue3 的双向绑定）
const dataValue = computed(() => {
  // 优先使用modelValue（Vue3），如果为空则使用value（Vue2）
  if (props.modelValue !== '') {
    return props.modelValue
  }
  return props.value
})
// 发送事件
const emitValue = (val: any) => {
  emit('input', val)
  emit('update:modelValue', val)
}

// 注册子组件
const register = (childInstance: any) => {
  childrens.value.push(childInstance)
}

// 注销子组件
const unregister = (childInstance: any) => {
  const index = childrens.value.findIndex((child) => child.nameSync === childInstance.nameSync)
  if (index !== -1) {
    childrens.value.splice(index, 1)
  }
}
// 设置打开状态 - 进一步优化
const setOpen = (val: any) => {
  // 处理不同类型的值
  const isString = typeof val === 'string' || typeof val === 'number'
  const isArray = Array.isArray(val)

  // 清空所有项的打开状态
  childrens.value.forEach((vm) => {
    if (typeof vm.setOpen === 'function') {
      vm.setOpen(false) // 使用子组件提供的setOpen方法
    } else {
      vm.isOpen = false // 兼容旧的方式
    }
  })

  // 根据不同模式设置打开状态
  childrens.value.forEach((vm) => {
    if (isString) {
      // 手风琴模式 - 单值
      if (val.toString() === vm.nameSync) {
        if (typeof vm.setOpen === 'function') {
          vm.setOpen(true)
        } else {
          vm.isOpen = true
        }
      }
    } else if (isArray) {
      // 多选模式 - 数组
      val.forEach((v) => {
        if (v.toString() === vm.nameSync) {
          if (typeof vm.setOpen === 'function') {
            vm.setOpen(true)
          } else {
            vm.isOpen = true
          }
        }
      })
    }
  })

  emitValue(val)
}

// 监听值变化设置打开状态
watch(
  () => dataValue.value,
  (val) => {
    if (val !== undefined && val !== null) {
      setOpen(val)
    }
  },
  { immediate: true }, // 立即执行以处理默认值
)

// 设置手风琴模式 - 修复版
const setAccordion = (self: any) => {
  if (!props.accordion) return

  childrens.value.forEach((vm) => {
    // 检查各种可能的标识符比较方式
    const isSameComponent =
      // 如果self是组件实例的情况
      (self.uid && vm.instance?.uid && self.uid === vm.instance.uid) ||
      // 如果self只有nameSync属性的情况
      (self.nameSync && self.nameSync === vm.nameSync) ||
      // 如果self就是vm实例本身的情况
      self === vm

    // 如果不是同一个组件，则关闭它
    if (!isSameComponent) {
      vm.isOpen = false
    }
  })
}

// 重新计算高度
const resize = () => {
  childrens.value.forEach((vm) => {
    // #ifndef APP-NVUE
    vm.getCollapseHeight && vm.getCollapseHeight()
    // #endif
    // #ifdef APP-NVUE
    vm.getNvueHwight && vm.getNvueHwight()
    // #endif
  })
}

// 状态变化事件
const onChange = (isOpen: any, self: any) => {
  let activeItem = ''

  if (props.accordion) {
    // 手风琴模式返回单个值
    activeItem = isOpen ? self.nameSync : ''
  } else {
    // 非手风琴模式返回数组
    const activeItems: any = []
    childrens.value.forEach((vm) => {
      if (vm.isOpen) {
        activeItems.push(vm.nameSync)
      }
    })
    activeItem = activeItems
  }

  emit('change', activeItem)
  emitValue(activeItem)
}

// 提供给子组件的内容
provide('uniCollapseContext', {
  childrens,
  names,
  setAccordion,
  onChange,
  register,
  unregister,
  // 新增一个方法，让子组件可以查询当前活动项
  getActiveNames: () => {
    // 如果是手风琴模式，返回单个值组成的数组
    if (props.accordion) {
      return typeof dataValue.value === 'string' || typeof dataValue.value === 'number'
        ? [dataValue.value.toString()]
        : []
    }
    // 如果是多选模式，确保返回数组
    return Array.isArray(dataValue.value) ? dataValue.value.map((v: any) => v.toString()) : []
  },
})

// 组件挂载后初始化
onMounted(() => {
  nextTick(() => {
    if (dataValue.value !== undefined && dataValue.value !== null && dataValue.value !== '') {
      setOpen(dataValue.value)
    }
  })
})
</script>

<style lang="scss">
.uni-collapse {
  /* #ifndef APP-NVUE */
  width: 100%;
  display: flex;
  /* #endif */
  /* #ifdef APP-NVUE */
  flex: 1;
  /* #endif */
  flex-direction: column;
  background-color: #fff;
}
</style>
