<template>
  <div :style="{ marginBottom: !visible ? '12px' : '' }">
    <div v-if="visible && realJsonData.length > 0" class="table-page-search-wrapper">
      <a-form-model v-if="loaded" ref="form" :model="form" :rules="rules" :layout="layout">
        <a-row :gutter="24" type="flex">
          <x-form-item
            v-for="item in visibleItems"
            :showLabel="!simpleMode"
            :key="`${queryParamsName}-item-${item._originalIndex}`"
            :attr="item.formItem"
            :form="form"
            :service-name="serviceName"
            :get-data-params="getDataParams"
            :env="env"
            :setForm="setForm"
            @x-form-item-emit-func="emitFunc"
            @mounted="onItemMounted"
          />
          <x-form-item
            v-show="advanced"
            v-for="item in hiddenItems"
            :showLabel="!simpleMode"
            :key="`${queryParamsName}-item-${item._originalIndex}`"
            :attr="item.formItem"
            :form="form"
            :service-name="serviceName"
            :get-data-params="getDataParams"
            :env="env"
            :setForm="setForm"
            @x-form-item-emit-func="emitFunc"
            @mounted="onItemMounted"
          />
          <a-col style="margin-left: auto">
            <span
              :style="advanced ? { float: 'right', overflow: 'hidden' } : {}"
              class="table-page-search-submitButtons"
            >
              <template v-if="hiddenItems.length > 0">
                <a @click="toggleAdvanced">
                  <span v-if="!advanced" style="display: inline-flex; align-items: center">
                    <a-icon type="eye" :style="iconStyle" class="form-expand-icon"></a-icon>
                    &nbsp;更多条件
                  </span>
                  <span v-else style="display: inline-flex; align-items: center">
                    <a-icon type="eye-invisible" :style="iconStyle" class="form-expand-icon rotated"></a-icon>
                    &nbsp;收起更多
                  </span>
                </a>
                <a-divider type="vertical" />
              </template>
              <a-space>
                <a-button v-if="!simpleMode" htmlType="submit" type="primary" @click="onSubmit">
                  <a-icon :style="iconStyle" type="search"></a-icon>
                  查询
                </a-button>
                <a-button v-if="!simpleMode" @click="resetForm">重置</a-button>
                <slot></slot>
              </a-space>
            </span>
          </a-col>
        </a-row>
      </a-form-model>
      <div class="next-divider-dashed" role="separator"></div>
    </div>
  </div>
</template>
<script>
import XFormItem from '@vue2-client/base-client/components/common/XForm/XFormItem'
import { mapState } from 'vuex'
import moment from 'moment'
import { executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
import { getConfigByNameAsync, runLogic } from '@vue2-client/services/api/common'
import * as util from '@vue2-client/utils/util'
import formValidationMixin from '@vue2-client/mixins/formValidationMixin'
import { findLabelByValue } from '@vue2-client/base-client/plugins/selectValueTypeHelper'

export default {
  name: 'XForm',
  components: {
    XFormItem
  },
  mixins: [formValidationMixin],
  data() {
    return {
      // 内容加载是否完成
      loaded: false,
      // 服务名称
      serviceName: undefined,
      // 是否展开条件
      advanced: false,
      // 表单Model
      form: undefined,
      // 校验
      rules: {},
      // 图标样式
      iconStyle: {
        position: 'relative',
        top: '1px'
      },
      // 表单项集合
      formItems: [],
      // 是否显示
      visible: true,
      // 调用logic获取数据源的追加参数
      getDataParams: {},
      // 当前环境
      env: 'prod',
      // 暂存 form 的默认值
      defaultMap: {},
      // 已经渲染得 x-from-item 为了让所有节点init执行完在调用 table 查询
      mountedCount: 0,
      // 是否简易模式
      simpleMode: false,
      queryParamsName: '',
      // 默认显示的表单项数量
      visibleItemCount: 7,
      // 表单模式 horizontal | vertical | inline
      layout: 'inline',
      // 是否为扩展按钮预留空间（减少 1 个可见表单项，由 init 传入）
      reserveSpaceForButtons: false
    }
  },
  computed: {
    ...mapState('account', { currUser: 'user' }),
    // 过滤掉仅用于新增/修改场景的表单项
    realJsonData: function () {
      return this.formItems.filter(
        item =>
          (!item.isOnlyAddOrEdit && item.type !== 'group') ||
          (item.type === 'group' && item.groupItems.some(groupItem => !groupItem.isOnlyAddOrEdit))
      )
    },
    // 过滤出用于新增/修改场景的表单项
    groupJsonData: function () {
      return this.formItems
        .filter(item => {
          return item.type === 'group'
        })
        .map(item => {
          item.groupItems = item.groupItems
            .filter(item => !item.isOnlyAddOrEdit)
            .map(groupItem => {
              // 只保留第一个下划线后面的内容
              // groupItem.model = groupItem.model.substring(groupItem.model.indexOf('_') + 1)
              return groupItem
            })
          return item
        })
    },
    // 合并所有来源的表单项
    allFormItems: function () {
      const normalItems = this.realJsonData.map(item => ({
        type: 'normal',
        formItem: item
      }))

      const groupItems = this.groupJsonData.flatMap(group =>
        group.groupItems.map(item => ({
          type: 'group',
          formItem: item,
          groupName: group.name || '分组'
        }))
      )

      return [...normalItems, ...groupItems]
    },
    // 显示的表单项
    visibleItems: function () {
      return this.allFormItems.slice(0, this.visibleItemCount).map((item, index) => ({
        ...item,
        _originalIndex: index
      }))
    },
    // 隐藏的表单项（需要点击展开才显示）
    hiddenItems: function () {
      return this.allFormItems.slice(this.visibleItemCount).map((item, index) => ({
        ...item,
        _originalIndex: this.visibleItemCount + index
      }))
    }
  },
  provide() {
    return {
      XFormContext: this,
      // 移除必填项
      removeRequired: this.removeRequired,
      // 设置必填项
      setRequired: this.setRequired,
      // 全局 label 宽度，确保所有表单项的 label 宽度一致
      globalLabelWidth: this.globalLabelWidth
    }
  },
  methods: {
    // 根据flex值计算可见表单项数量
    updateVisibleItemCount(flex) {
      // flex值与显示数量的映射关系
      const flexToCountMap = {
        24: 2, // 小屏：1个/行，显示2个（2行）
        12: 3, // 中屏：2个/行，显示3个（2行-1个）
        8: 5, // 大屏：3个/行，显示5个（2行-1个）
        6: 7, // 超大屏：4个/行，显示7个（2行-1个）
        4: 11 // 超超大屏：6个/行，显示11个（2行-1个）
      }

      let newCount = flexToCountMap[flex] || 7
      if (this.reserveSpaceForButtons) {
        newCount = Math.max(1, newCount - 1)
      }
      // 只有当数量真正变化时才更新，避免不必要的重新渲染
      if (this.visibleItemCount !== newCount) {
        this.visibleItemCount = newCount
      }
    },

    // 递归查找第一个XFormCol实例
    findFirstXFormCol(components = this.$children) {
      for (const component of components) {
        if (component.$options.name === 'XFormCol') {
          return component
        }
        // 递归查找子组件
        const found = this.findFirstXFormCol(component.$children)
        if (found) return found
      }
      return null
    },

    // 设置flex监听
    setupFlexWatcher() {
      this.$nextTick(() => {
        const firstXFormCol = this.findFirstXFormCol()
        if (firstXFormCol) {
          // 立即执行一次设置初始值
          this.updateVisibleItemCount(firstXFormCol.computedFlex)

          // 设置监听
          this._flexWatcher = this.$watch(
            () => firstXFormCol.computedFlex,
            newFlex => {
              this.updateVisibleItemCount(newFlex)
            }
          )
        } else {
          // 重试机制，直到找到XFormCol
          setTimeout(() => this.setupFlexWatcher(), 100)
        }
      })
    },

    init(params) {
      const {
        formItems,
        serviceName,
        getDataParams = {},
        env = 'prod',
        simpleMode = false,
        funcData = {},
        queryParamsName = 'localConfig',
        defaultQueryForm = {},
        advanced = false,
        layout = 'inline',
        reserveSpaceForButtons = false
      } = params
      this.mountedCount = 0
      this.queryParamsName = queryParamsName
      this.loaded = false
      this.formItems = JSON.parse(JSON.stringify(formItems))
      this.serviceName = serviceName
      this.env = env
      this.simpleMode = simpleMode
      this.advanced = advanced
      this.layout = layout
      this.reserveSpaceForButtons = reserveSpaceForButtons
      // visibleItemCount 现在由 flex 监听动态控制，不再需要手动设置
      const formData = {}
      for (let i = 0; i < this.realJsonData.length; i++) {
        const item = this.realJsonData[i]
        this.setFormProps(formData, item)
      }
      if (this.realJsonData.length === 0) {
        this.$nextTick(() => {
          this.$emit('itemsMounted')
        })
      }
      // 处理分组数据表单
      for (let i = 0; i < this.groupJsonData.length; i++) {
        const groupItem = this.groupJsonData[i]
        for (let j = 0; j < groupItem.groupItems.length; j++) {
          const item = groupItem.groupItems[j]
          this.setFormProps(formData, item)
        }
      }
      this.form = formData
      // 应用外部传入的默认查询表单值
      if (defaultQueryForm && Object.keys(defaultQueryForm).length > 0) {
        this.form = Object.assign({}, this.form, defaultQueryForm)
      }
      try {
        if (funcData.queryFormInit) {
          if (!funcData.queryFormInit.startsWith('async')) {
            funcData.queryFormInit = `async ${funcData.queryFormInit}`
          }
          executeStrFunctionByContext(this, funcData.queryFormInit, [util, runLogic, getConfigByNameAsync]).then(
            res => {
              this.form = Object.assign({}, this.form, res)
            }
          )
        }
      } catch (e) {
        console.error('queryFormInit error', e)
      }
      this.getDataParams = getDataParams
      this.loaded = true
      // 若已有 XFormCol，立即应用 reserveSpaceForButtons 到 visibleItemCount
      this.$nextTick(() => {
        const firstXFormCol = this.findFirstXFormCol()
        if (firstXFormCol) {
          this.updateVisibleItemCount(firstXFormCol.computedFlex)
        }
      })
    },
    onItemMounted(_h) {
      this.mountedCount += 1
      if (this.mountedCount === this.allFormItems.length) {
        // 所有 x-from-item 挂载完成，触发父组件中的 xTable.init
        this.$emit('itemsMounted')
      }
    },
    // 时间组件赋默认值
    getDateRange({ type, queryFormDefault: defaultValue, queryType, queryValueFormat: defaultFormat, name }) {
      const formatMap = {
        yearPicker: 'YYYY',
        yearRangePicker: 'YYYY',
        monthPicker: 'YYYY-MM',
        monthRangePicker: 'YYYY-MM',
        datePicker: 'YYYY-MM-DD',
        rangePicker: 'YYYY-MM-DD HH:mm:ss',
        timePicker: 'HH:mm:ss',
        timeRangePicker: 'HH:mm:ss'
      }
      let format = formatMap[type]

      if (defaultFormat) {
        format = defaultFormat
      }

      let start, end

      switch (defaultValue) {
        case 'curYear':
          start = moment().startOf('year').format(format)
          end = moment().endOf('year').format(format)
          break
        case 'curMonth':
          start = moment().startOf('month').format(format)
          end = moment().endOf('month').format(format)
          break
        case 'curDay':
          start = moment().startOf('day').format(format)
          end = moment().endOf('day').format(format)
          break
        case 'curTime':
          start = moment().format(format)
          end = moment().format(format)
          break
        default:
          return undefined
      }
      if (['monthPicker', 'yearPicker', 'datePicker', 'timePicker'].includes(type)) {
        if (queryType === 'BETWEEN') {
          return [start, end]
        }
        if (name.indexOf('开始') > -1 || name.indexOf('起始') > -1) {
          return start
        } else {
          return end
        }
      } else if (['rangePicker', 'yearRangePicker', 'monthRangePicker', 'timeRangePicker'].includes(type)) {
        return [start, end]
      }
      return [start, end]
    },
    setFormProps(formData, item) {
      formData[item.model] = undefined
      if (item.queryFormDefault) {
        if (
          [
            'datePicker',
            'rangePicker',
            'yearPicker',
            'monthPicker',
            'yearRangePicker',
            'monthRangePicker',
            'timePicker',
            'timeRangePicker'
          ].includes(item.type)
        ) {
          formData[item.model] = this.getDateRange(item)
        } else if (
          ['treeSelect', 'select', 'checkbox'].includes(item.type) &&
          ['curOrgId', 'curDepId', 'curUserId'].includes(item.queryFormDefault)
        ) {
          if (item.queryFormDefault === 'curOrgId') {
            formData[item.model] = item.type === 'select' ? this.currUser.orgid : [this.currUser.orgid + '']
          }
          if (item.queryFormDefault === 'curDepId') {
            formData[item.model] = item.type === 'select' ? this.currUser.depids : [this.currUser.depids + '']
          }
          if (item.queryFormDefault === 'curUserId') {
            formData[item.model] = item.type === 'select' ? this.currUser.id : [this.currUser.id + '']
          }
        } else {
          formData[item.model] = item.queryFormDefault
        }
        if (item.forceQueryDefault) {
          this.defaultMap[item.model] = formData[item.model]
        }
      } else {
        if (
          ['datePicker', 'rangePicker', 'yearPicker', 'monthPicker', 'yearRangePicker', 'monthRangePicker'].includes(
            item.type
          )
        ) {
          if (item.queryType === 'BETWEEN') {
            formData[item.model] = []
          }
        }
      }
      if (item.rule) {
        this.rules[item.model] = []
        const required = item.rule.queryRequired
          ? item.rule.queryRequired === true || item.rule.queryRequired === 'true'
          : false
        let trigger
        let message
        if (required) {
          switch (item.type) {
            case 'select':
            case 'checkbox':
            case 'radio':
            case 'treeSelect':
            case 'rangePicker':
            case 'monthPicker':
            case 'yearPicker':
            case 'datePicker':
            case 'file':
            case 'image':
            case 'citySelect':
            case 'addressSearch':
            case 'personSetting':
              message = '请选择' + item.name
              trigger = 'change'
              break
            default:
              message = '请输入' + item.name
              trigger = 'blur'
          }
          this.rules[item.model].push({
            required: true,
            message: message,
            trigger: trigger
          })
        }

        switch (item.rule.queryType) {
          case 'customJs': {
            this.rules[item.model].push({
              validator: (rule, value, callback) => {
                this.customJsValidate(rule, value, callback, item)
              },
              trigger: 'blur'
            })
            break
          }
        }
      }
    },
    customJsValidate(rule, value, callback, item) {
      if (item.rule.customQueryValidatorFunc) {
        executeStrFunctionByContext(this, item.rule.customQueryValidatorFunc, [
          rule,
          value,
          callback,
          this.form,
          item,
          util,
          runLogic,
          getConfigByNameAsync
        ])
      } else {
        callback()
      }
    },
    toggleAdvanced() {
      this.advanced = !this.advanced
      this.$emit('toggleAdvanced')
    },
    toggleVisible() {
      this.visible = !this.visible
      return this.visible
    },
    resetForm() {
      this.$refs.form.resetFields()
    },
    emitFunc(func, data, value) {
      this.$emit(func, data, value)
      this.$emit('x-form-item-emit-func', func, data, value)
    },
    /**
     * 递归查找 XFormItem 实例
     * @param {Array} children - 子组件数组
     * @param {String} fieldName - 字段名
     * @returns {Object|null} XFormItem 实例
     */
    findXFormItemByField(children, fieldName) {
      if (!children || children.length === 0) return null

      for (const child of children) {
        if (child && child.$options && child.$options.name === 'XFormItem') {
          if (child.attr && child.attr.model === fieldName) {
            return child
          }
        }
        // 递归查找子组件
        if (child && child.$children && child.$children.length > 0) {
          const found = this.findXFormItemByField(child.$children, fieldName)
          if (found) return found
        }
      }
      return null
    },
    /**
     * 获取表单字段的 labelData（用于导出/打印等场景获取界面展示值）
     * 按需生成，不修改原有 form 对象，返回新的 labelData 对象
     * @returns {Object} labelData 对象，key 为字段名，value 为对应的 label
     */
    getFormLabelData() {
      const labelData = {}
      const labels = []
      const selectTypes = ['select', 'checkbox', 'radio', 'treeSelect']

      this.allFormItems.forEach(item => {
        const attr = item.formItem
        if (!attr) return

        const fieldName = attr.model
        const currentValue = this.form[fieldName]

        // 如果值为 undefined、null、空数组或空字符串，跳过
        if (currentValue === undefined || currentValue === null || (Array.isArray(currentValue) && currentValue.length === 0) || currentValue === '') {
          return
        }

        // 对于 selectTypes 类型，从 options 中查找 label
        if (selectTypes.includes(attr.type)) {
          // 获取 options：优先静态配置 keys，其次从 XFormItem 实例获取
          let options = []
          if (attr.keys && Array.isArray(attr.keys) && attr.keys.length > 0) {
            options = attr.keys
          } else if (attr.keyName) {
            const formItemInstance = this.findXFormItemInstance(fieldName)
            if (formItemInstance) {
              options = formItemInstance.option || formItemInstance.optionForFunc || []
            }
          }

          // 查找 label
          if (options.length > 0) {
            const label = findLabelByValue(currentValue, options)
            if (label !== null && label !== undefined) {
              labelData[fieldName] = label
              // 添加表单项的中文标签（attr.name）
              if (attr.name) {
                labels.push(attr.name)
              }
            }
          }
        } else {
          // 对于非 selectTypes 类型，直接使用 form 中的值作为 label
          // 如果是数组，转换为字符串；如果是对象，转换为 JSON 字符串
          let displayValue = currentValue
          if (Array.isArray(currentValue)) {
            displayValue = currentValue.join(', ')
          } else if (typeof currentValue === 'object') {
            displayValue = JSON.stringify(currentValue)
          } else {
            displayValue = String(currentValue)
          }

          labelData[fieldName] = displayValue
          // 添加表单项的中文标签（attr.name）
          if (attr.name) {
            labels.push(attr.name)
          }
        }
      })

      return {
        labelData,
        labels
      }
    },
    /**
     * 查找指定字段的 XFormItem 实例
     * @param {String} fieldName - 字段名
     * @returns {Object|null} XFormItem 实例
     */
    findXFormItemInstance(fieldName) {
      // 从 $refs.form 开始查找
      if (this.$refs.form?.$children) {
        const found = this.findXFormItemByField(this.$refs.form.$children, fieldName)
        if (found) return found
      }
      // 从根组件开始查找
      if (this.$children) {
        return this.findXFormItemByField(this.$children, fieldName)
      }
      return null
    },
    onSubmit() {
      this.$refs.form.validate(valid => {
        for (const key of Object.keys(this.form)) {
          if (this.form[key] === null || this.form[key] === '') {
            this.form[key] = undefined
          }
          // 树形选择框重置后会重置为[undefined],查询时为[null]
          if (
            Array.isArray(this.form[key]) &&
            (this.form[key].length === 0 || this.form[key][0] === null || this.form[key][0] === undefined)
          ) {
            this.form[key] = undefined
          }
          // 如果 form 中没有值，但是有默认值
          if (this.form[key] === undefined && this.defaultMap[key] !== undefined) {
            this.form = Object.assign({}, this.form, this.defaultMap)
          }
        }
        const requestParameters = Object.assign({}, this.form)
        const data = {
          valid: valid,
          form: requestParameters
        }
        this.$emit('onSubmit', data)
      })
    },
    exports() {
      this.$emit('exports', this.form)
    },
    setForm(obj) {
      this.form = Object.assign(this.form, obj)
    },
    /**
     * 主动触发表单提交
     * 用于 queryTable 等场景，确保走相同的数据处理流程
     * @param {Object} conditionParams - 额外的查询条件参数
     */
    submitForm(conditionParams = {}) {
      // 备份一下 form 这个函数传递的 condition 仅临时用一下
      // 如果要实质修改 form 从其他地方赋值
      const _from = JSON.parse(JSON.stringify(this.form))
      // 将外部参数合并到表单中
      if (Object.keys(conditionParams).length > 0) {
        this.form = Object.assign({}, this.form, conditionParams)
      }
      // 调用现有的 onSubmit 方法，触发 emit
      this.onSubmit()
      this.form = _from
    }
  },
  mounted() {
    console.log('XForm mounted, setting up flex watcher')
    this.setupFlexWatcher()
  },
  beforeDestroy() {
    // 清理watcher
    if (this._flexWatcher) {
      this._flexWatcher()
    }
  }
}
</script>
<style lang="less" scoped>
:deep(.ant-form-inline .ant-form-item) {
  margin-right: 0;
  margin-top: 0;
  margin-bottom: 12px;

  .ant-form-item-control-wrapper {
    min-width: 0;
  }
}

:deep(.table-page-search-wrapper .table-page-search-submitButtons) {
  margin-top: 0;
}
</style>
