<template>
  <div class="reportGridMain" ref="reportGridMain">
    <template v-if="isWidget">
      <!--  插槽展示  -->
      <x-report-tr-group
        v-for="(row, rowIndex) in activatedConfig.columns"
        @updateImg="updateImg"
        @selectRow="selectRow"
        @slotsConfigEnded="onTrGroupSlotsConfigEnded"
        :show-img-in-cell="showImgInCell"
        :server-name="serverName"
        :env="env"
        :key="rowIndex"
        :columns="row"
        :no-top-border="noTopBorder"
        :config-data="activatedConfig.data"
        :config="activatedConfig"
        :display="true">
      </x-report-tr-group>
    </template>
    <template v-else>
      <div
        :class=" noPadding ? 'reportMainNoPadding' : 'reportMain'"
        :style="activatedConfig.width > 0 ? ('width:' + activatedConfig.width + 'px') : undefined">
        <!--      主体表格      -->
        <table class="reportTable" v-if="render" :style="activatedConfig.style ? activatedConfig.style : undefined">
          <tbody class="reportTable">
            <!--  插槽展示  -->
            <x-report-tr-group
              :key="rowIndex"
              v-for="(row, rowIndex) in activatedConfig.columns"
              @selectRow="selectRow"
              @slotRendered="slotRendered"
              @slotsConfigEnded="onTrGroupSlotsConfigEnded"
              :server-name="serverName"
              :env="env"
              :columns="row"
              :config-data="activatedConfig.data"
              :config="activatedConfig"
              @listClick="listClick"
              :display="true">
            </x-report-tr-group>
          </tbody>
        </table>
      </div>
    </template>
  </div>
</template>

<script>
import XReportTrGroup from './XReportTrGroup.vue'
import { getConfigByName } from '@vue2-client/services/api/common'
import XFormTable from '@vue2-client/base-client/components/common/XFormTable/XFormTable'

export default {
  name: 'XReportDesign',
  props: {
    // 配置
    config: {
      type: Object,
      require: true,
      default: () => {
      }
    },
    showImgInCell: {
      type: Boolean,
      default: false
    },
    // 是否是展示用
    forDisplay: {
      type: Boolean,
      default: false
    },
    // 命名空间
    serverName: {
      type: String,
      default: process.env.VUE_APP_SYSTEM_NAME
    },
    // 环境
    env: {
      type: String,
      default: 'prod'
    },
    // 是否只能展示不可编辑
    displayOnly: {
      type: Boolean,
      default: false
    },
    // 插槽名
    slotConfigName: {
      type: String,
      default: undefined
    },
    // 表格没有边距
    noPadding: {
      type: Boolean,
      default: true
    },
    // 表格没有上边框，与noPadding搭配可以实现连续表格
    noTopBorder: {
      type: Boolean,
      default: false
    },
  },
  components: {
    XFormTable,
    XReportTrGroup
  },
  inject: ['isWidget'],
  provide () {
    return {
      setColSpanByName: this.setColSpanByName
    }
  },
  data () {
    return {
      // 表单的数据
      data: this.config.data,
      // 插槽配置
      slotConfig: undefined,
      // 控制是否渲染
      render: false,
      // 用于展示的配置
      activatedConfig: {},
      // 已收到 slotsConfigEnded 的 TrGroup 数量，用于聚合为 allSlotsConfigEnded
      trGroupConfigEndedCount: 0
    }
  },
  watch: {
    activatedConfig: {
      deep: true,
      handler (val) {
        this.trGroupConfigEndedCount = 0
        if (val && (!val.columns || val.columns.length === 0)) {
          this.$nextTick(() => this.$emit('allSlotsConfigEnded'))
        }
      }
    }
  },
  methods: {
    onTrGroupSlotsConfigEnded () {
      this.trGroupConfigEndedCount += 1
      if (this.trGroupConfigEndedCount >= (this.activatedConfig.columns || []).length) {
        this.$emit('allSlotsConfigEnded')
      }
    },
    listClick (data) {
      this.$emit('listClick', data)
    },
    slotRendered () {
      this.$emit('slotRendered')
    },
    updateImg (data) {
      this.$emit('updateImg', data)
    },
    selectRow (selectedRowKeys, selectedRows) {
      this.table_selectedRowKeys = selectedRowKeys
      this.table_selectedRows = selectedRows
      this.$emit('selectRow', selectedRowKeys, selectedRows)
    },
    setColSpanByName (componentName, colSpan) {
      // 处理columns配置（二维数组结构）
      const processColumns = (columns) => {
        columns.forEach((row) => {
          row.forEach((cell, index) => {
            if (Array.isArray(cell)) {
              processColumns(cell) // 递归处理嵌套数组
            } else if (cell.slotRef === componentName) {
              // 使用Vue.set确保响应式更新
              this.$set(row[index], 'colSpan', colSpan)
              this.$set(row[index], '_isManualColSpan', true)
            }
          })
        })
      }

      // 处理table配置（二维数组结构）
      const processTable = (table) => {
        table.forEach((row) => {
          row.forEach((cell, index) => {
            // 同时检查顶层和def中的slotRef
            const isTargetCell =
              cell.slotRef === componentName ||
              cell.def?.slotRef === componentName

            if (isTargetCell) {
              // 同时更新顶层和def中的colSpan
              this.$set(row[index], 'colSpan', colSpan)
              this.$set(row[index], '_isManualColSpan', true)
              if (cell.def) {
                this.$set(row[index].def, 'colSpan', colSpan)
                this.$set(row[index].def, '_isManualColSpan', true)
              }
            }
          })
        })
      }

      // 强制刷新视图
      const forceUpdate = () => {
        this.$nextTick(() => {
          // 创建新对象引用以触发watch
          this.activatedConfig = {
            ...this.activatedConfig,
            _version: Date.now()
          }
          this.$forceUpdate()
        })
      }

      // 处理当前激活的配置
      if (this.activatedConfig?.columns) {
        processColumns(this.activatedConfig.columns)
      }
      if (this.activatedConfig?.table) {
        processTable(this.activatedConfig.table)
      }

      forceUpdate()
    },
    applyAllStyles () {
      // 应用组件样式
      const component = this.$refs.reportGridMain
      // 确保组件已经完全挂载
      this.$nextTick(() => {
        this.applyComponentStyles(component)
      })
    },
    // 获取组件样式配置
    async getComponentStyleConfig (componentType) {
      try {
        // 从配置中获取样式定义
        const styleConfig = this.$appdata.getStylesByKey(componentType)
        return styleConfig || {}
      } catch (error) {
        console.error('获取组件样式配置失败:', error)
        return {}
      }
    },

    // 解析组件样式配置
    async parseComponentStyles (cell) {
      if (!cell.class) return { rootStyles: {}, childStyles: {} }

      const styleConfig = await this.getComponentStyleConfig('reportGridMain')
      if (!styleConfig) return { rootStyles: {}, childStyles: {} }

      const rootStyles = {}
      const childStyles = new Map()

      // 处理每个class配置
      cell.class.split(' ').forEach(className => {
        const classConfig = styleConfig[className]
        if (!classConfig) return

        // 处理根节点样式
        Object.entries(classConfig).forEach(([key, value]) => {
          if (!key.startsWith('*') && typeof key !== 'object') {
            rootStyles[key] = value
          }
        })

        // 处理子节点样式
        this.parseNestedStyles(classConfig, childStyles)
      })
      return {
        rootStyles,
        childStyles
      }
    },

    // 递归解析嵌套的样式配置
    parseNestedStyles (config, styleMap, parentKey = '') {
      Object.entries(config).forEach(([key, value]) => {
        if (!key.startsWith('*')) return

        const className = key.replace('*', '.')

        // 如果值是对象，检查是否包含样式和子节点
        if (typeof value === 'object') {
          const { style = {}, children = {} } = this.separateStyleAndChildren(value)

          // 创建或获取当前节点的样式配置
          if (!styleMap.has(className)) {
            styleMap.set(className, {
              styles: {},
              children: new Map()
            })
          }

          const nodeData = styleMap.get(className)

          // 合并样式
          Object.assign(nodeData.styles, style)

          // 递归处理子节点
          this.parseNestedStyles(children, nodeData.children, className)
        }
      })
    },

    // 分离样式属性和子节点配置
    separateStyleAndChildren (obj) {
      const style = {}
      const children = {}

      Object.entries(obj).forEach(([key, value]) => {
        if (key.startsWith('*')) {
          // 子节点配置
          children[key] = value
        } else {
          // 样式属性
          style[key] = value
        }
      })

      return { style, children }
    },

    // 应用组件样式
    async applyComponentStyles (component) {
      if (!component) return

      const { rootStyles, childStyles } = await this.parseComponentStyles(this.activatedConfig)

      // 应用根节点样式
      if (Object.keys(rootStyles).length > 0) {
        Object.entries(rootStyles).forEach(([property, value]) => {
          component.style.setProperty(property, value, 'important')
        })
      }

      // 如果没有子节点样式,直接返回
      if (childStyles.size === 0) return

      let retryCount = 0
      const maxRetries = 5
      const retryInterval = 100 // 100ms

      const applyStyles = () => {
        this.applyChildStylesOptimized(component, childStyles)
      }

      // 首次应用样式
      applyStyles()

      // 创建重试机制
      const retryApplyStyles = () => {
        if (retryCount >= maxRetries) return

        setTimeout(() => {
          applyStyles()
          retryCount++
          retryApplyStyles()
        }, retryInterval)
      }

      // 开始重试
      retryApplyStyles()

      // 创建 MutationObserver 用于动态内容
      const observer = new MutationObserver((mutations) => {
        // 检查是否有新增节点
        const hasNewNodes = mutations.some(mutation =>
          mutation.type === 'childList' && mutation.addedNodes.length > 0
        )

        if (hasNewNodes) {
          applyStyles()
        }
      })

      // 配置 observer
      observer.observe(component, {
        childList: true,
        subtree: true,
        attributes: false
      })

      // 3秒后停止观察
      // setTimeout(() => {
      //   observer.disconnect()
      // }, 3000)

      // 组件销毁时清理
      this.$once('hook:beforeDestroy', () => {
        observer.disconnect()
      })
    },

    // 优化后的子节点样式应用方法
    applyChildStylesOptimized (rootElement, styleMap, parentSelector = '') {
      if (!rootElement) return

      // 处理样式映射
      try {
        for (const [selector, data] of styleMap.entries()) {
          const currentSelector = parentSelector ? `${parentSelector} ${selector}` : selector

          try {
            // 查找匹配的元素
            const elements = Array.from(rootElement.querySelectorAll(currentSelector))

            if (!elements.length) continue

            // 应用当前层级样式
            if (data.styles) {
              elements.forEach(element => {
                if (!element) return

                // 应用每个样式属性
                Object.entries(data.styles).forEach(([property, value]) => {
                  try {
                    element.style.setProperty(property, value, 'important')
                  } catch (err) {
                    console.warn(`设置样式失败: ${property}=${value}`, err)
                  }
                })
              })
            }

            // 处理子层级
            if (data.children && data.children.size > 0) {
              elements.forEach(element => {
                if (element) {
                  this.applyChildStylesOptimized(element, data.children, currentSelector)
                }
              })
            }
          } catch (err) {
            console.warn(`处理选择器失败: ${currentSelector}`, err)
            continue
          }
        }
      } catch (err) {}
    },
  },
  created () {
    if (this.slotConfigName) {
      getConfigByName(this.slotConfigName, undefined, res => {
        this.slotConfig = res
        res.data = { ...res.data, ...this.data }
        this.config.data = res.data
        this.activatedConfig = res
        this.render = true
      }, this.env === 'dev')
    } else {
      this.activatedConfig = this.config
      this.render = true
    }

    this.activatedConfig.columns.forEach(row => {
      if (row[0] && row[0].type && row[0].type === 'list' && row[0].listLength === 1) {
        row.forEach(cell => {
          cell.listLength = this.activatedConfig.data[cell.dataIndex].length
        })
      }
    })
  },
  mounted () {
    this.applyAllStyles()
  }
}
</script>

<style lang="less" scoped>
.img {
  width: 95%;
  height: 180px;
  object-fit: cover;
}

.reportMain {
  text-align: center;
  margin: 0 auto;
  font-size: 16px;
  color: #000;
  background-color: #fff;
  border-radius: 8px;

  .reportTitle {
    font-weight: bold;
  }

  .subTitle {
    display: flex;
    justify-content: space-between;
    margin-bottom: 1%;

    .subTitleItems {
      max-width: 30%;
    }
  }

  .inputsDiv {
    display: flex;
    justify-content: space-between;

    .inputsDivItem {
      display: flex;
      align-items: center;
      padding: 0 4px;
      white-space: nowrap;

      .inputsDivItemLabel {
        padding: 0 4px;
      }
    }
  }

  .reportTable {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    word-break: break-all;
  }
}

.reportMainForDisplay {
  text-align: center;
  margin: 10% auto;
  font-size: 16px;
  color: #000;
  background-color: #fff;
  border-radius: 8px;

  .reportTitle {
    font-weight: bold;
  }

  .subTitle {
    display: flex;
    justify-content: space-between;

    .subTitleItems {
      max-width: 30%;
    }
  }

  .inputsDiv {
    display: flex;
    justify-content: space-around;

    .inputsDivItem {
      display: flex;
      align-items: center;
      padding: 0 4px;
      white-space: nowrap;

      .inputsDivItemLabel {
        padding: 0 4px;
      }
    }
  }

  .reportTable {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    word-break: break-all;
  }
}

.reportMainNoPadding {
  // text-align: center;
  margin: 0 auto;
  font-size: 16px;
  color: #000;
  // background-color: #fff;
  border-radius: 8px;
  height: auto;
  min-height: 20vh;
  overflow-y: auto;
  overflow-x: hidden;

  .reportTitle {
    font-weight: bold;
  }

  .subTitle {
    display: flex;
    justify-content: space-between;

    .subTitleItems {
      max-width: 30%;
    }
  }

  .inputsDiv {
    display: flex;
    justify-content: space-between;

    .inputsDivItem {
      display: flex;
      align-items: center;
      padding: 0 4px;
      white-space: nowrap;

      .inputsDivItemLabel {
        padding: 0 4px;
      }
    }
  }

  .reportTable {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    word-break: break-all;
  }
}

.tools {
  position: fixed;
  right: 2%;
  text-align: right;
  width: 60%;
  cursor: pointer;

  .toolsItem {
    width: 15%;
    margin-right: 3%;
    display: inline-block;
  }
}
</style>
