<template>
  <a-row id="XDescriptionGroup" :gutter="24">
    <!-- left 模式：左侧导航 + 右侧内容 -->
    <template v-if="tabMode === 'left'">
      <a-col :span="4" v-if="realData.length">
        <a-tabs tab-position="left" v-model="activeTab" @change="scrollToGroup">
          <template v-for="(item, index) in realData">
            <a-tab-pane :tab="item.title" :key="index" v-if="item.title"></a-tab-pane>
          </template>
        </a-tabs>
      </a-col>
      <a-col :span="realData.length ? 20 : 24" ref="descriptionsGroupContext" class="descriptionsGroupContext">
        <div
          class="descriptions-item"
          :ref="`descriptions-item-${realDataIndex}`"
          :key="realDataIndex"
          v-for="(realDataItem, realDataIndex) in realData"
        >
          <!-- 渲染所有分组内容 -->
          <template v-if="!loadError">
            <!-- 插槽分组：由父组件通过具名插槽传入内容 -->
            <template v-if="realDataItem.slot">
              <slot :name="realDataItem.slotName" :data="data"></slot>
            </template>
            <!-- 带有子的详情 -->
            <template v-else-if="realDataItem.title && groups[realDataIndex]?.type === 'array'">
              <div class="ant-descriptions-title">{{ realDataItem.title }}</div>
              <div class="descriptions-array-item">
                <a-descriptions
                  v-for="(arrayItem, arrayIndex) in realDataItem.column"
                  :column="isMobile ? 1 : column"
                  size="small"
                  :key="arrayIndex"
                  :title="arrayItem.title"
                >
                  <template v-for="(item, index) in arrayItem.column">
                    <!-- 大多数情况 循环下 空值省略不展示，todo 后期可能加配置处理 -->
                    <a-descriptions-item :key="index" v-if="item.value" :label="item.key">
                      {{ formatText(item.value) }}
                    </a-descriptions-item>
                  </template>
                </a-descriptions>
              </div>
            </template>
            <a-descriptions v-else-if="realDataItem.title" :column="isMobile ? 1 : column" :title="realDataItem.title">
              <a-descriptions-item
                v-for="(item, index) in visibleDescriptionFields(realDataItem.column)"
                :key="index"
                :span="item.span || 1"
              >
                <template #label>
                  {{ item.key }}
                  <span v-if="isFieldRequired(item, data)" style="color: red">*</span>
                </template>
                <span :style="getFieldStyle(item, data)">
                  <!-- 超链接样式兼容 -->
                  <template v-if="item.isLink">
                    <span
                      role="link"
                      tabindex="0"
                      class="link-text"
                      @click="handleLinkClick(item, data, $event)"
                      @keyup.enter="handleLinkClick(item, data, $event)">
                      {{ formatFieldValue(item.value, item, data) ?? '--' }}
                    </span>
                  </template>
                  <template v-else>
                    {{ formatFieldValue(item.value, item, data) ?? '--' }}
                  </template>
                  <a-button
                    v-if="item.canEdit"
                    type="link"
                    size="small"
                    @click="handleEditField(item)"
                    style="padding: 0 4px"
                  >
                    <a-icon type="edit"/>
                  </a-button>
                </span>
              </a-descriptions-item>
            </a-descriptions>
          </template>
        </div>
      </a-col>
    </template>

    <!-- top 模式：顶部横向 tab -->
    <template v-else-if="tabMode === 'top'">
      <a-col :span="24" v-if="realData.length">
        <a-tabs v-model="activeTab" size="small" :tabBarStyle="{ margin: 0, padding: '0 8px' }">
          <a-tab-pane v-for="(item, index) in realData" :key="index" :tab="item.title">
            <div class="tab-content-scroll">
              <!-- 只渲染当前激活的分组内容 -->
              <template v-if="!loadError && realData[activeTab]">
                <!-- 插槽分组：由父组件通过具名插槽传入内容 -->
                <template v-if="realData[activeTab].slot">
                  <slot :name="realData[activeTab].slotName" :data="data"></slot>
                </template>
                <!-- 带有子的详情 -->
                <template v-else-if="realData[activeTab].title && groups[activeTab]?.type === 'array'">
                  <div class="ant-descriptions-title" v-if="tabMode !== 'top'">{{ realData[activeTab].title }}</div>
                  <div class="descriptions-array-item">
                    <a-descriptions
                      v-for="(arrayItem, arrayIndex) in realData[activeTab].column"
                      :column="isMobile ? 1 : column"
                      size="small"
                      :key="arrayIndex"
                      :title="arrayItem.title"
                    >
                      <template v-for="(fieldItem, fieldIndex) in arrayItem.column">
                        <a-descriptions-item :key="fieldIndex" v-if="fieldItem.value" :label="fieldItem.key">
                          {{ formatText(fieldItem.value) }}
                        </a-descriptions-item>
                      </template>
                    </a-descriptions>
                  </div>
                </template>
                <a-descriptions
                  v-else-if="realData[activeTab].title"
                  :column="isMobile ? 1 : column"
                  :title="tabMode === 'top' ? undefined : realData[activeTab].title"
                >
                  <a-descriptions-item
                    v-for="(fieldItem, fieldIndex) in visibleDescriptionFields(realData[activeTab].column)"
                    :key="fieldIndex"
                    :span="fieldItem.span || 1"
                  >
                    <template #label>
                      {{ fieldItem.key }}
                      <span v-if="isFieldRequired(fieldItem, data)" style="color: red">*</span>
                    </template>
                    <span :style="getFieldStyle(fieldItem, fieldItem.value, data)">
                      <!-- 超链接样式兼容 - 修复变量引用错误 -->
                      <template v-if="fieldItem.isLink">
                        <span
                          role="link"
                          tabindex="0"
                          class="link-text"
                          @click="handleLinkClick(fieldItem, data, $event)"
                          @keyup.enter="handleLinkClick(fieldItem, data, $event)"
                        >
                          {{ formatFieldValue(fieldItem.value, fieldItem, data) || '--' }}
                        </span>
                      </template>
                      <template v-else>
                        {{ formatFieldValue(fieldItem.value, fieldItem, data) || '--' }}
                      </template>
                      <a-button
                        v-if="fieldItem.canEdit"
                        type="link"
                        size="small"
                        @click="handleEditField(fieldItem)"
                        style="padding: 0 4px"
                      >
                        <a-icon type="edit"/>
                      </a-button>
                    </span>
                  </a-descriptions-item>
                </a-descriptions>
              </template>
            </div>
          </a-tab-pane>
        </a-tabs>
      </a-col>
    </template>

    <!-- none 模式：无 tab，直接展示所有内容 -->
    <template v-else>
      <a-col :span="24" class="descriptionsGroupContext">
        <div class="descriptions-item" :key="realDataIndex" v-for="(realDataItem, realDataIndex) in realData">
          <!-- 渲染所有分组内容 -->
          <template v-if="!loadError">
            <!-- 插槽分组：由父组件通过具名插槽传入内容 -->
            <template v-if="realDataItem.slot">
              <slot :name="realDataItem.slotName" :data="data"></slot>
            </template>
            <!-- 带有子的详情 -->
            <template v-else-if="realDataItem.title && groups[realDataIndex]?.type === 'array'">
              <div class="ant-descriptions-title">{{ realDataItem.title }}</div>
              <div class="descriptions-array-item">
                <a-descriptions
                  v-for="(arrayItem, arrayIndex) in realDataItem.column"
                  :column="isMobile ? 1 : column"
                  size="small"
                  :key="arrayIndex"
                  :title="arrayItem.title"
                >
                  <template v-for="(item, index) in arrayItem.column">
                    <a-descriptions-item :key="index" v-if="item.value" :label="item.key">
                      {{ formatText(item.value) }}
                    </a-descriptions-item>
                  </template>
                </a-descriptions>
              </div>
            </template>
            <a-descriptions v-else-if="realDataItem.title" :column="isMobile ? 1 : column" :title="realDataItem.title">
              <a-descriptions-item
                v-for="(item, index) in visibleDescriptionFields(realDataItem.column)"
                :key="index"
                :span="item.span || 1"
              >
                <template #label>
                  {{ item.key }}
                  <span v-if="isFieldRequired(item, data)" style="color: red">*</span>
                </template>
                <span :style="getFieldStyle(item, item.value, data)">
                  <template v-if="item.isLink">
                    <span
                      role="link"
                      tabindex="0"
                      class="link-text"
                      @click="handleLinkClick(item, data, $event)"
                      @keyup.enter="handleLinkClick(item, data, $event)"
                    >
                      {{ formatFieldValue(item.value, item, data) || '--' }}
                    </span>
                  </template>
                  <template v-else>
                    {{ formatFieldValue(item.value, item, data) || '--' }}
                  </template>
                  <a-button
                    v-if="item.canEdit"
                    type="link"
                    size="small"
                    @click="handleEditField(item)"
                    style="padding: 0 4px"
                  >
                    <a-icon type="edit"/>
                  </a-button>
                </span>
              </a-descriptions-item>
            </a-descriptions>
          </template>
        </div>
      </a-col>
    </template>
  </a-row>
</template>
<script>
import {mapState} from 'vuex'
import {getRealKeyData} from '@vue2-client/utils/formatter'
import {getConfigByName} from '@vue2-client/services/api/common'
import {executeStrFunctionByContext} from '@vue2-client/utils/runEvalFunction'
import XAddNativeForm from '@vue2-client/base-client/components/common/XAddNativeForm/XAddNativeForm.vue'

export default {
  name: 'XDescriptionsGroup',
  components: {
    XAddNativeForm
  },
  props: {
    // 内容
    data: {
      type: Object,
      required: true,
      default: undefined
    },
    configName: {
      type: String,
      required: true,
      default: ''
    },
    // 配置所属命名空间
    serviceName: {
      type: String,
      default: process.env.VUE_APP_SYSTEM_NAME
    }
  },
  mounted() {
  },
  beforeDestroy() {
    const formGroupContext = this.$refs.formGroupContext?.$el
    if (formGroupContext && formGroupContext.removeEventListener) {
      formGroupContext.removeEventListener('scroll', this.onScroll)
    }
  },
  created() {
    this.initConfig()
  },
  data() {
    return {
      // 加载状态
      loading: false,
      loadError: false,
      realData: [],
      // 获取到的配置组
      groups: {},
      activeTab: 0,
      // 从配置中获取的值
      column: 3, // 默认值
      getRealData: false, // 默认值
      tabMode: 'left' // 默认值
    }
  },
  computed: {
    ...mapState('setting', {isMobile: 'isMobile'})
  },
  methods: {
    initConfig() {
      this.loading = true
      if (this.configName) {
        this.getConfig()
        // 只在 left 模式启用滚动监听
        if (this.tabMode === 'left') {
          this.$nextTick(() => {
            const formGroupContext = this.$refs.descriptionsGroupContext?.$el
            if (formGroupContext && formGroupContext.addEventListener) {
              formGroupContext.addEventListener('scroll', this.onScroll)
            }
          })
        }
      } else {
        this.loading = false
        this.loadError = true
      }
    },
    scrollToGroup(index) {
      const groupElement = this.$refs[`descriptions-item-${index}`][0]
      if (groupElement) {
        groupElement.scrollIntoView({behavior: 'smooth'})
      }
    },
    getConfig() {
      getConfigByName(this.configName, this.serviceName, res => {
        if (res.groups) {
          // 从配置中获取 column、getRealData 和 tabMode
          this.column = res.column !== undefined ? res.column : 3
          this.getRealData = res.getRealData !== undefined ? res.getRealData : false
          this.tabMode = res.tabMode !== undefined ? res.tabMode : 'left'

          // 解析分组配置
          const groups = this.parseGroupsConfig(res.groups)
          this.groups = groups
          this.realData = groups
            .map(group => {
              const dataItem = {title: group.name}

              if (group.type === 'slot') {
                // 插槽分组：由父组件通过具名插槽传入内容
                return {
                  title: group.name,
                  slot: true,
                  slotName: group.slotName || group.name
                }
              }

              if (group.type === 'array') {
                // 处理数组类型数据
                const arrayData = this.data[group.key] || []
                dataItem.column = arrayData
                  .map((item, index) => ({
                    title: `${group.name} ${index + 1}`,
                    column: group.fields.map(field => ({
                      key: field.name,
                      value: item[field.key]
                    }))
                  }))
                  .filter(Boolean)
              } else {
                dataItem.column = group.fields.map(field => ({
                  key: field.name,
                  dataKey: field.key,
                  value: this.getRealKeyData(this.data, field.key),
                  span: field.span,
                  // 存储字段函数配置
                  showIf: field.showIf,
                  styleFunc: field.styleFunc,
                  formatFunc: field.formatFunc,
                  requireFunc: field.requireFunc,
                  canEdit: field.canEdit === true,
                  isLink: field.isLink === true
                }))
              }

              return dataItem.column.length > 0 ? dataItem : null
            })
            .filter(Boolean)
        }
      })
    },
    /**
     * 解析分组配置数据，支持新旧两种配置格式
     * @param {Object|Array} groupsConfig - 分组配置对象或数组
     * @returns {Array} 解析后的分组数组
     *
     * 配置格式说明：
     *
     * 旧模式 - 对象格式 (Object):
     * {
     *   "表具信息": {
     *     "f_gasbrand": "气表品牌",           // 简单字段配置
     *     "f_meter_type": "表具类型"
     *   },
     *   "设备信息": {
     *     "type": "array",                    // 数组类型标识
     *     "key": "devices",                   // type为array时必填：数据源key
     *     "value": {                          // type为array时的字段配置
     *       "f_devices_num": "设备数量",
     *       "f_devices_type": "设备类型"
     *     }
     *   },
     *   "客户信息": {
     *     "f_user_code": {                    // 字段可配置为对象
     *       "name": "用户编号",
     *       "span": 2                         // 可选：列跨度
     *     },
     *     "f_user_name": "用户姓名"           // 简单字段配置
     *   }
     * }
     *
     * 新模式 - 数组格式 (Array):
     * [{
     *   "name": "客户信息",
     *   "fields": [
     *     {
     *       "name": "用户编号",
     *       "key": "f_user_code",
     *       "span": 3
     *     }
     *   ]
     * }, {
     *   "name": "设备信息",
     *   "type": "array",                    // 数组类型标识
     *   "key": "devices",                   // type为array时必填：数据源key
     *   "fields": [
     *     {
     *       "name": "设备数量",
     *       "key": "f_devices_num"
     *     },
     *     {
     *       "name": "设备类型",
     *       "key": "f_devices_type"
     *     }
     *   ]
     * }]
     */
    parseGroupsConfig(groupsConfig) {
      // 如果已经是数组格式，直接返回
      if (Array.isArray(groupsConfig)) {
        return groupsConfig
      }

      // 解析对象格式配置
      return Object.entries(groupsConfig).map(([groupName, groupConfig]) => {
        // 处理插槽类型的配置
        if (groupConfig.type === 'slot') {
          return {
            name: groupName,
            type: 'slot',
            slotName: groupConfig.slotName || groupName
          }
        }

        // 处理数组类型的配置
        if (groupConfig.type === 'array') {
          return {
            name: groupName,
            type: 'array',
            key: groupConfig.key,
            fields: Object.entries(groupConfig.value || {}).map(([k, v]) => ({
              key: k,
              name: v
            }))
          }
        }

        // 处理普通配置（支持新旧格式）
        return {
          name: groupName,
          fields: Object.entries(groupConfig).map(([fieldKey, fieldValue]) => ({
            key: fieldKey,
            name: typeof fieldValue === 'string' ? fieldValue : fieldValue.name,
            showIf: typeof fieldValue === 'object' ? fieldValue.showIf : undefined,
            styleFunc: typeof fieldValue === 'object' ? fieldValue.styleFunc : undefined,
            formatFunc: typeof fieldValue === 'object' ? fieldValue.formatFunc : undefined,
            requireFunc: typeof fieldValue === 'object' ? fieldValue.requireFunc : undefined,
            canEdit: typeof fieldValue === 'object' ? fieldValue.canEdit : undefined,
            // 新增超链接配置
            isLink: typeof fieldValue === 'object' ? fieldValue.isLink : undefined,
            ...(typeof fieldValue === 'object' ? fieldValue : {})
          }))
        }
      })
    },
    // 文字格式化
    formatText(value) {
      return value ?? '--'
    },
    // 执行字段展示函数
    shouldShowField(field, data) {
      if (!field.showIf) return true
      try {
        return executeStrFunctionByContext(this, field.showIf, [data, field.key])
      } catch (error) {
        console.warn('showIf 函数执行错误:', error)
        return true
      }
    },
    /** 供模板循环使用，避免在同一元素上混用 v-for 与 v-if */
    visibleDescriptionFields(column) {
      if (!column?.length) return []
      return column.filter(item => this.shouldShowField(item, this.data))
    },
    // 获取字段样式
    getFieldStyle(field, data) {
      if (!field.styleFunc) return {}
      try {
        return executeStrFunctionByContext(this, field.styleFunc, [data, field.key])
      } catch (error) {
        console.warn('styleFunc 函数执行错误:', error)
        return {}
      }
    },
    // 格式化字段值
    formatFieldValue(value, field, data) {
      if (!field.formatFunc) return value
      try {
        return executeStrFunctionByContext(this, field.formatFunc, [data, field.key])
      } catch (error) {
        console.warn('formatFunc 函数执行错误:', error)
        return value
      }
    },
    // 判断字段是否必填（显示红色星号）
    isFieldRequired(field, data) {
      if (!field.requireFunc) return false
      try {
        return executeStrFunctionByContext(this, field.requireFunc, [data, field.key])
      } catch (error) {
        console.warn('requireFunc 函数执行错误:', error)
        return false
      }
    },
    getRealKeyData(data, key) {
      if (this.getRealData) {
        return getRealKeyData(data)[key] || ''
      } else {
        return this.data[key] || ''
      }
    },
    // 触发编辑事件，由外部组件实现具体编辑逻辑
    handleEditField(field) {
      this.$emit('edit-field', {
        field,
        value: field.value,
        data: this.data
      })
    },
    // 处理超链接点击
    handleLinkClick(field, data, event) {
      event.stopPropagation()
      // 向父组件抛出事件
      this.$emit('link-click', {
        field,
        value: field.value,
        data: this.data
      })
    },
    onScroll() {
      // 只在 left 模式启用滚动联动
      if (this.tabMode !== 'left') return

      const formGroupContext = this.$refs.descriptionsGroupContext.$el
      let groupItems = []
      if (formGroupContext && formGroupContext.querySelectorAll) {
        groupItems = formGroupContext.querySelectorAll('.descriptions-item')
      }
      let activeIndex = this.activeTab

      groupItems.forEach((item, index) => {
        const rect = item.getBoundingClientRect()
        if (rect.top <= 205 && rect.bottom > 200) {
          activeIndex = index
        }
      })
      this.activeTab = activeIndex
    }
  },
  watch: {
    content: {
      handler() {
        this.initConfig()
      }
    },
    configName: {
      handler() {
        this.initConfig()
      }
    },
    serviceName: {
      handler() {
        this.initConfig()
      }
    }
  }
}
</script>

<style lang="less" scoped>
#XDescriptionGroup {
  height: 100%;

  :deep(.ant-descriptions-title) {
    color: @primary-color;
  }

  :deep(.ant-descriptions-item-label) {
    color: #6b7280; // 统一标签颜色
    font-weight: 500;
  }

  :deep(.ant-descriptions-item-content) {
    color: #111827; // 统一内容颜色
    font-weight: 400;
  }

  // 移除最后一行的 padding-bottom
  :deep(.ant-descriptions-view) {
    .ant-descriptions-row:last-child {
      > th,
      > td {
        padding-bottom: 0;
      }
    }
  }

  .descriptions-item {
    margin-bottom: 8px;
  }

  .descriptions-array-item {
    padding-left: 1rem;
  }

  .descriptionsGroupContext {
    height: 100%;
    overflow-y: scroll;
  }

  .link-text {
    color: @primary-color;
    text-decoration: none;
    cursor: pointer;
    outline: none;

    &:hover {
      text-decoration: underline;
    }

    &:focus {
      text-decoration: underline;
      box-shadow: 0 0 0 2px fade(@primary-color, 20%);
    }
  }

  // top 模式样式
  .tab-content-scroll {
    overflow-y: auto;
    padding: 8px 10px;

    :deep(.ant-descriptions-item) {
      padding-bottom: 12px;
    }
  }

  // none 模式：移除分组间距
  &:has(.tabMode-none) {
    .descriptions-item {
      margin-bottom: 4px;
    }
  }
}
</style>
