<script setup>
import { getConfigByName } from '@vue2-client/services/api/common'
import { reactive, ref, provide } from 'vue'
import RenderRow from './RenderRow'
import XErrorView from '@vue2-client/base-client/components/layout/XPageView/XErrorView.vue'

// 页面布局配置
const layout = ref(null)

// 加载状态：0-加载中，1-已加载，2-出现错误
const loadingStatus = {
  LOADING: 0,
  LOADED: 1,
  ERROR: 2
}
const loaded = ref(loadingStatus.LOADING)

// 组件计数
const componentTotal = ref(0)
const registerComponentTotal = ref(0)

// 组件注册集合
const componentRefMap = reactive({})

// 数据上下文
const dataContext = reactive({
  comps: componentRefMap,
  func: {
    getConfigByName
  },
  data: {}
})

/**
 * 初始化构建页面组件
 */
const init = (params) => {
  const { configName, configValue, serviceName } = params

  // 重置状态
  loaded.value = loadingStatus.LOADING
  componentTotal.value = 0
  registerComponentTotal.value = 0
  Object.keys(componentRefMap).forEach(key => delete componentRefMap[key])

  const processConfig = (config) => {
    if (!config) {
      loaded.value = loadingStatus.ERROR
      return
    }

    layout.value = config
    setComponentTotal(layout.value.children)
    loaded.value = loadingStatus.LOADED
  }

  if (configName) {
    getConfigByName(configName, serviceName, processConfig)
  } else if (configValue) {
    try {
      const config = typeof configValue === 'string' ? JSON.parse(configValue) : configValue
      processConfig(config)
    } catch (error) {
      console.error('配置解析错误:', error)
      loaded.value = loadingStatus.ERROR
    }
  } else {
    loaded.value = loadingStatus.ERROR
  }
}

/**
 * 注册组件
 */
const registerComponent = (name, vm) => {
  if (!vm) return

  componentRefMap[name] = vm
  registerComponentTotal.value++
  console.debug(`总组件数量：${componentTotal.value}，已注册数量：${registerComponentTotal.value}`)

  // 所有组件都已注册完成
  if (registerComponentTotal.value >= componentTotal.value) {
    registerEvents(layout.value.children)
    // 初始化页面
    initPage()
  }
}
provide('registerComponent', registerComponent)
// 提供数据上下文给子组件
provide('dataContext', dataContext)

/**
 * 初始化页面
 */
const initPage = () => {
  if (!layout.value?.onMounted) return

  console.info('开始初始化页面')
  try {
    // 使用 Function 构造函数替代 eval
    // eslint-disable-next-line no-new-func
    const onMountedFun = new Function('data', `return (${layout.value.onMounted})(data)`)
    onMountedFun(dataContext)
  } catch (error) {
    console.error('页面初始化错误:', error)
  }
}

/**
 * 设置需要注册的组件总数
 */
const setComponentTotal = (children) => {
  if (!children?.length) return

  children.forEach((child) => {
    // 如果不是row和text类型，追加组件数量
    if (child.type !== 'row' && child.type !== 'text') {
      componentTotal.value++
    }

    // 递归追加子组件数量
    if (child.children?.length) {
      setComponentTotal(child.children)
    }
  })
}

/**
 * 注册组件事件
 */
const registerEvents = (children) => {
  if (!children?.length) return

  children.forEach((child) => {
    // 如果有事件，注册它们
    if (child.event) {
      Object.entries(child.event).forEach(([eventName, handler]) => {
        try {
          // 使用 Function 构造函数替代 eval
          // eslint-disable-next-line no-new-func
          const eventHandler = new Function('...args', `return (${handler})(...args)`)
          const componentInstance = componentRefMap[child.id]

          if (componentInstance) {
            componentInstance.$on(eventName, (...args) => {
              eventHandler.call(componentInstance, ...args, dataContext)
            })
          }
        } catch (error) {
          console.error(`注册事件 ${eventName} 错误:`, error)
        }
      })
    }

    // 递归注册子组件的事件
    if (child.children?.length) {
      registerEvents(child.children)
    }
  })
}

// 导出组件接口
defineExpose({ init })
</script>

<template>
  <a-row
    type="flex"
    :gutter="layout?.gutter || 0"
    :align="layout?.align || 'top'"
    :justify="layout?.justify || 'start'"
    class="liuli-page">
    <template v-if="loaded === loadingStatus.LOADED">
      <template v-if="layout.children?.length">
        <a-col v-for="row in layout.children" :key="`page-col-${row.id}`" :span="24">
          <render-row :row="row"/>
        </a-col>
      </template>
      <template v-else>
        <div class="liuli-page__empty">
          <a-empty description="无页面内容" />
        </div>
      </template>
    </template>

    <template v-else-if="loaded === loadingStatus.LOADING">
      <div class="liuli-page__loading">
        <a-spin tip="页面加载中..." />
      </div>
    </template>

    <template v-else>
      <div class="liuli-page__error">
        <XErrorView />
      </div>
    </template>
  </a-row>
</template>

<style scoped lang="less">
.liuli-page {
  position: relative;
  width: 100%;
  height: 100%;

  &__content {
    min-height: 100px;
  }

  &__loading, &__error, &__empty {
    display: flex;
    width: 100%;
    justify-content: center;
    align-items: center;
    min-height: 200px;
  }

  &__error {
    width: 100%;
  }
}
</style>
