<template>
    <div class="editor">
        <div ref="previewContainer" class="preview"></div>
    </div>
</template>
<script setup>
import { ref, onMounted,onUnmounted } from 'vue'
import { loadModule } from 'vue3-sfc-loader'
import * as Vue from 'vue/dist/vue.esm-bundler.js'
import * as ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import less from 'less'
import { i18n } from '@/plugins/vue-i18n'
import * as VueRouter from 'vue-router'
import { useRoute, useRouter } from 'vue-router'
import { moduleUpdate,moduleById } from '@/api/application/module'
import { userLogin } from '@/api/permission/user'
import { useCache } from '@/hooks/web/useCache'
const route = useRoute()
const router = useRouter()
const props = defineProps({
    name:String,
    id:String,
    isExecuteEvent: Boolean,
})
const sfcCode = ref('')
const previewContainer = ref(null)
let prevApp = null

// 增强的Base64转换函数
const convertToBase64 = async (imagePath) => {
    try {
        // 处理路径别名
        const resolvedPath = imagePath.replace('@/', '/src/')
        const response = await fetch(resolvedPath)
        if (!response.ok) throw new Error(`图片加载失败: ${response.status}`)
        const blob = await response.blob()
        return new Promise((resolve) => {
            const reader = new FileReader()
            reader.onloadend = () => resolve(reader.result)
            reader.readAsDataURL(blob)
        })
    } catch (error) {
        console.error('Base64转换失败:', error.message)
        return ''
    }
}
const runCode = async () => {
  try {
    if (prevApp) {
      prevApp.unmount()
      previewContainer.value.innerHTML = ''
    }
    const options = {
      moduleCache: {
        vue: Vue,
        'element-plus': ElementPlus,
        'vue/dist/vue.esm-bundler.js': Vue,
        'vue-router': VueRouter,
        '@/api/permission/user': { userLogin },
        '@/hooks/web/useCache': { useCache }
      },
      getFile: async (fileName) => {
        if (fileName.startsWith('@/')) {
          const resolvedPath = fileName.replace('@/', '/src/')
          try {
            const response = await fetch(resolvedPath)
            return { content: await response.text() }
          } catch (e) {
            console.error(`文件加载失败: ${resolvedPath}`, e)
            return { content: '<!-- 文件加载失败 -->' }
          }
        }
        if (fileName === 'dynamic.vue') {
          let code = sfcCode.value
          // 增强的Less处理（支持scoped）
          const lessRegex = /<style\s+.*?lang="less".*?>(.*?)<\/style>/gis
          let match
          while ((match = lessRegex.exec(code)) !== null) {
            const [full, content] = match
            try {
              const { css } = await less.render(content, {
                paths: ['.'], // 设置解析路径
                filename: 'dynamic.less'
              })
              code = code.replace(full, `<style>${css}</style>`)
            } catch (e) {
              console.error('Less编译错误:', e.message)
              code = code.replace(full, `<style>/* Less Error: ${e.message} */</style>`)
            }
          }

          // 处理图片资源（增强路径处理）
          const imgRegex = /src=['"](.+?\.(png|jpg|jpeg))['"]/gi
          let imgMatch
          while ((imgMatch = imgRegex.exec(code)) !== null) {
            const [full, path] = imgMatch
            const base64 = await convertToBase64(path)
            code = code.replace(full, `src="${base64}"`)
          }
          return code
            .replace(/<\/script>/g, '<\\/script>')
            .replace(/\\\//g, '/')
        }

        // 处理外部Less文件（支持别名）
        if (fileName.endsWith('.less')) {
          const resolvedPath = fileName.replace('@/', '/src/')
          try {
            const response = await fetch(resolvedPath)
            const content = await response.text()
            const { css } = await less.render(content, { filename: fileName })
            return { content: css, mediaType: 'text/css' }
          } catch (e) {
            return { content: `/* Less Error: ${e.message} */`, mediaType: 'text/css' }
          }
        }

        return ''
      },
      addStyle: (css) => {
        const style = document.createElement('style')
        style.textContent = css
        document.head.appendChild(style)

      },
      compiledCache: new Map(),
      compileTemplate: true
    }
    const componentModule = await loadModule('dynamic.vue', options)
    const component = componentModule.default || componentModule
    const dynamicProps = ref({
      id: props.id, 
      name: props.name,
      isExecuteEvent:props.isExecuteEvent
    })
    prevApp = Vue.createApp({
      render: () => Vue.h(component, {
        ...dynamicProps.value,
        router: router,
        route: route
      })
    })
    
    // 显式提供路由实例
    prevApp.use(router)
    prevApp.use(ElementPlus)
    prevApp.use(i18n)
    prevApp.mount(previewContainer.value)

  } catch (error) {
    console.error('运行时错误:', error)
    previewContainer.value.innerHTML = `
      <div class="error">
        <h3>错误</h3>
        <pre>${error.message}</pre>
      </div>
    `
  }
}
onMounted(() => {
    init()
})
function init(){
    moduleById(props.id).then(res => {
    if(res.data.data.canvas_style_data){
      sfcCode.value = res.data.data.canvas_style_data
      runCode()
    }
  })
}
</script>
<style>
/* 保留原有样式并补充 */
.editor {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100vh;
    overflow: hidden;
}

textarea {
    flex: 1;
    margin-bottom: 10px;
    font-family: Monaco, monospace;
    padding: 10px;
}

.preview {
    width: 100%;
    height: 100vh;
    flex: 1;
    overflow: hidden;
}
</style>