<template>
  <view class="uni-collapse-item">
    <!-- onClick(!isOpen) -->
    <view
      @click="onClick(!isOpen)"
      class="uni-collapse-item__title"
      :class="{
        'is-open': isOpen && titleBorder === 'auto',
        'uni-collapse-item-border': titleBorder !== 'none',
      }"
    >
      <view class="uni-collapse-item__title-wrap">
        <slot name="title" :expanded="isOpen">
          <view class="uni-collapse-item__title-box" :class="{ 'is-disabled': disabled }">
            <image v-if="thumb" :src="thumb" class="uni-collapse-item__title-img" />
            <text class="uni-collapse-item__title-text">{{ title }}</text>
          </view>
        </slot>
      </view>
      <view
        v-if="showArrow && !$slots.title"
        :class="{
          'uni-collapse-item__title-arrow-active': isOpen,
          'uni-collapse-item--animation': showAnimation === true,
        }"
        class="uni-collapse-item__title-arrow"
      >
        <view :color="disabled ? '#ddd' : '#bbb'" class="i-carbon-chevron-down" />
      </view>
    </view>
    <view
      class="uni-collapse-item__wrap"
      :class="{ 'is--transition': showAnimation }"
      :style="{ height: (isOpen ? height : 0) + 'px' }"
    >
      <view
        :id="elId"
        ref="collapseHook"
        class="uni-collapse-item__wrap-content"
        :class="{ open: isheight, 'uni-collapse-item--border': border && isOpen }"
      >
        <slot></slot>
      </view>
    </view>
  </view>
</template>

<script setup>
import {
  ref,
  inject,
  watch,
  onMounted,
  onUnmounted,
  onUpdated,
  getCurrentInstance,
  nextTick,
} from 'vue'

// #ifdef APP-NVUE
const dom = weex.requireModule('dom')
// #endif

/**
 * CollapseItem 折叠面板子组件
 * @description 折叠面板子组件
 * @property {String} title 标题文字
 * @property {String} thumb 标题左侧缩略图
 * @property {String} name 唯一标志符
 * @property {Boolean} open = [true|false] 是否展开组件
 * @property {Boolean} titleBorder = [true|false] 是否显示标题分隔线
 * @property {String} border = ['auto'|'show'|'none'] 是否显示分隔线
 * @property {Boolean} disabled = [true|false] 是否展开面板
 * @property {Boolean} showAnimation = [true|false] 开启动画
 * @property {Boolean} showArrow = [true|false] 是否显示右侧箭头
 */

const props = defineProps({
  // 列表标题
  title: {
    type: String,
    default: '',
  },
  name: {
    type: [Number, String],
    default: '',
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false,
  },
  // #ifdef APP-PLUS
  // 是否显示动画,app 端默认不开启动画，卡顿严重
  showAnimation: {
    type: Boolean,
    default: false,
  },
  // #endif
  // #ifndef APP-PLUS
  // 是否显示动画
  showAnimation: {
    type: Boolean,
    default: true,
  },
  // #endif
  // 是否展开
  open: {
    type: Boolean,
    default: false,
  },
  // 缩略图
  thumb: {
    type: String,
    default: '',
  },
  // 标题分隔线显示类型
  titleBorder: {
    type: String,
    default: 'auto',
  },
  border: {
    type: Boolean,
    default: true,
  },
  showArrow: {
    type: Boolean,
    default: true,
  },
})

// 生成随机元素ID，用于解决百度小程序获取同一个元素位置信息的bug
const elId = ref(`Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`)
const isOpen = ref(false)
const isheight = ref < any > null
const height = ref(0)
const nameSync = ref('0')
const collapseHook = ref < any > null
const proxy = getCurrentInstance()

// 获取折叠面板父组件上下文
const collapseContext = inject('uniCollapseContext', null)

// 监听open属性变化
watch(
  () => props.open,
  (val) => {
    isOpen.value = val
    onClick(val, 'init')
  },
)

// 初始化方法
const init = (type) => {
  // #ifndef APP-NVUE
  getCollapseHeight(type)
  // #endif
  // #ifdef APP-NVUE
  getNvueHwight(type)
  // #endif
}

// 卸载组件时从父组件中移除
const uninstall = () => {
  if (collapseContext) {
    collapseContext.unregister({
      nameSync: nameSync.value,
    })
  }
}

// 点击事件处理 - 修复版
const onClick = (isOpenVal, type) => {
  if (props.disabled) return

  // 保存旧状态用于比较
  const oldIsOpen = isOpen.value

  // 设置新状态
  isOpen.value = isOpenVal

  // 如果是打开操作且在手风琴模式下，关闭其他面板
  if (isOpen.value && !oldIsOpen && collapseContext) {
    // 传递一个包含必要信息的对象，确保能被识别
    collapseContext.setAccordion({
      nameSync: nameSync.value,
      uid: proxy.uid,
      instance: proxy,
    })
  }

  // 非初始化操作时，触发onChange回调
  if (type !== 'init' && collapseContext) {
    collapseContext.onChange(isOpen.value, {
      nameSync: nameSync.value,
      isOpen: isOpen.value,
    })
  }
}

// 获取折叠面板高度（非APP-NVUE）
const getCollapseHeight = (type, index = 0) => {
  const views = uni.createSelectorQuery().in(proxy)
  views
    .select(`#${elId.value}`)
    .fields(
      {
        size: true,
      },
      (data) => {
        // TODO 百度中可能获取不到节点信息，需要循环获取
        if (index >= 10) return
        if (!data) {
          index++
          getCollapseHeight(false, index)
          return
        }

        // #ifdef APP-NVUE
        height.value = data.height + 1
        // #endif
        // #ifndef APP-NVUE
        height.value = data.height
        // #endif

        isheight.value = true
        if (type) return
        onClick(isOpen.value, 'init')
      },
    )
    .exec()
}

// 获取NVUE环境下的高度
const getNvueHwight = (type) => {
  // #ifdef APP-NVUE
  dom.getComponentRect(collapseHook.value, (option) => {
    if (option && option.result && option.size) {
      height.value = option.size.height + 1
      isheight.value = true
      if (type) return
      onClick(props.open, 'init')
    }
  })
  // #endif
}

// 组件挂载后初始化 - 注册部分的修改
onMounted(() => {
  if (!collapseContext) {
    // console.error('找不到折叠面板父组件上下文!')
    return
  }

  // 设置nameSync
  nameSync.value = props.name !== '' ? props.name.toString() : `${collapseContext.childrens.length}`

  // console.log('折叠项挂载:', nameSync.value)

  // 注册到父组件 - 确保传递所有必要的参数
  collapseContext.register({
    nameSync: nameSync.value,
    isOpen: isOpen.value,
    instance: proxy,
    uid: proxy.uid,
    // 添加方法引用，使父组件可以直接操作
    setOpen: (val) => {
      isOpen.value = val
      nextTick(() => init())
    },
  })

  // 初始化动画高度
  init()

  // 检查是否应该默认展开
  nextTick(() => {
    if (collapseContext.getActiveNames) {
      const activeNames = collapseContext.getActiveNames()
      // console.log('当前活动项:', activeNames, '本项:', nameSync.value)
      if (activeNames.includes(nameSync.value.toString())) {
        // console.log('默认展开:', nameSync.value)
        isOpen.value = true
        // 更新高度
        init()
      }
    }
  })
})

// 组件更新后重新初始化
onUpdated(() => {
  nextTick(() => {
    init(true)
  })
})

// 组件卸载时从父组件移除
onUnmounted(() => {
  uninstall()
})
</script>

<style lang="scss">
.uni-collapse-item {
  /* #ifndef APP-NVUE */
  box-sizing: border-box;

  /* #endif */
  &__title {
    /* #ifndef APP-NVUE */
    display: flex;
    width: 100%;
    box-sizing: border-box;
    /* #endif */
    flex-direction: row;
    align-items: center;
    transition: border-bottom-color 0.3s;

    // transition-property: border-bottom-color;
    // transition-duration: 5s;
    &-wrap {
      width: 100%;
      flex: 1;
    }

    &-box {
      padding: 0 15px;
      /* #ifndef APP-NVUE */
      display: flex;
      width: 100%;
      box-sizing: border-box;
      /* #endif */
      flex-direction: row;
      justify-content: space-between;
      align-items: center;
      height: 48px;
      line-height: 48px;
      background-color: #fff;
      color: #303133;
      font-size: 13px;
      font-weight: 500;
      /* #ifdef H5 */
      cursor: pointer;
      outline: none;

      /* #endif */
      &.is-disabled {
        .uni-collapse-item__title-text {
          color: #999;
        }
      }
    }

    &.uni-collapse-item-border {
      border-bottom: 1px solid #ebeef5;
    }

    &.is-open {
      border-bottom-color: transparent;
    }

    &-img {
      height: 22px;
      width: 22px;
      margin-right: 10px;
    }

    &-text {
      flex: 1;
      font-size: 14px;
      /* #ifndef APP-NVUE */
      white-space: nowrap;
      color: inherit;
      /* #endif */
      /* #ifdef APP-NVUE */
      lines: 1;
      /* #endif */
      overflow: hidden;
      text-overflow: ellipsis;
    }

    &-arrow {
      /* #ifndef APP-NVUE */
      display: flex;
      box-sizing: border-box;
      /* #endif */
      align-items: center;
      justify-content: center;
      width: 20px;
      height: 20px;
      margin-right: 10px;
      transform: rotate(0deg);

      &-active {
        transform: rotate(-180deg);
      }
    }
  }

  &__wrap {
    /* #ifndef APP-NVUE */
    will-change: height;
    box-sizing: border-box;
    /* #endif */
    background-color: #fff;
    overflow: hidden;
    position: relative;
    height: 0;

    &.is--transition {
      // transition: all 0.3s;
      transition-property: height, border-bottom-width;
      transition-duration: 0.3s;
      /* #ifndef APP-NVUE */
      will-change: height;
      /* #endif */
    }

    &-content {
      position: absolute;
      font-size: 13px;
      color: #303133;
      // transition: height 0.3s;
      border-bottom-color: transparent;
      border-bottom-style: solid;
      border-bottom-width: 0;

      &.uni-collapse-item--border {
        border-bottom-width: 1px;
        border-bottom-color: red;
        border-bottom-color: #ebeef5;
      }

      &.open {
        position: relative;
      }
    }
  }

  &--animation {
    transition-property: transform;
    transition-duration: 0.3s;
    transition-timing-function: ease;
  }
}
</style>
