<script setup lang="ts">
import { getCurrentInstance, onMounted, ref, watch } from 'vue';

import { useQuery } from '@tanstack/vue-query';
import { jsonp, request } from '@vtj/utils';
import { createProvider } from '@vtj/web';
import { ElLoading } from 'element-plus';
import Postmate from 'postmate';

import { LowCodeService } from './service';

// 文件加载时，清空一次 sessionStorage
sessionStorage.clear();

// 响应式状态
const renderer = ref();
const lowCodeService = new LowCodeService();
const isLoading = ref(false);
const handshakeCompleted = ref(false);
const accessToken = ref('');
const urlParams = ref(parseUrlParams());
const provider = ref(null);

// 从 URL 解析参数
function parseUrlParams() {
  const urlParams = new URLSearchParams(window.location.search);
  const params = {
    fileId: urlParams.get('fileId') || '',
    projectId: Number(urlParams.get('projectId')) || -1,
    applicationId: Number(urlParams.get('applicationId')) || -1,
    name: urlParams.get('name') || '',
  };
  console.log('解析URL参数:', params);
  return params;
}

// 初始化 Postmate 握手
const initPostmateHandshake = async () => {
  const model = new Postmate.Model({
    sayHi: (data: any) => {
      console.log('sayHi', data);
    },
  });

  return model.then((parent) => {
    console.log('parent', parent);
    // 只获取 accessToken
    accessToken.value = parent.model.accessToken || '';
    sessionStorage.setItem('y-code-access-token', accessToken.value);
    parent.emit('renderer-ready', 'y-code-renderer is ready');

    // 更新请求配置
    if (accessToken.value) {
      initRequestConfig(accessToken.value);
    }

    handshakeCompleted.value = true;
    return accessToken.value;
  });
};

// 初始化请求配置
const initRequestConfig = (token: string) => {
  request.useRequest((req) => {
    req.headers.set('Authorization', `Bearer ${token}`);
    return req;
  });
};

// 初始化低代码引擎 - 只初始化一次
const initLowCodeEngine = async () => {
  // 如果已经初始化过，直接返回
  if (provider.value) return provider.value;

  const token =
    accessToken.value || sessionStorage.getItem('y-code-access-token') || '';
  if (token) {
    initRequestConfig(token);
  }

  const { provider: lowCodeProvider, onReady } = createProvider({
    nodeEnv: import.meta.env.NODE_ENV,
    service: lowCodeService,
    project: { id: urlParams.value.projectId },
    adapter: {
      request,
      jsonp,
    },
  });

  provider.value = { provider: lowCodeProvider, onReady };
  return { provider: lowCodeProvider, onReady };
};

// 获取渲染组件
const getRenderComponent = async () => {
  isLoading.value = true;
  ElLoading.service({ text: '低代码文件加载中...' });

  try {
    // 1. 确保低代码引擎已初始化
    const { provider: lowCodeProvider, onReady } = await initLowCodeEngine();

    // 3. 获取渲染组件
    return new Promise<any>((resolve) => {
      onReady(async () => {
        const instance = getCurrentInstance();
        instance?.appContext.app.use(lowCodeProvider);
        try {
          const renderComponent = await lowCodeProvider.getRenderComponent(
            urlParams.value.fileId,
          );
          console.log('渲染组件获取成功');
          resolve(renderComponent);
        } catch (error) {
          console.error('获取渲染组件失败:', error);
          resolve(null);
        }
      });
    });
  } catch (error) {
    console.error('获取渲染组件过程出错:', error);
    return null;
  } finally {
    isLoading.value = false;
    ElLoading.service().close();
  }
};

// 使用 useQuery 管理渲染组件（但不实际使用）
const { data: rendererComponent } = useQuery({
  queryKey: ['getRenderer'],
  queryFn: getRenderComponent,
  enabled: false, // 初始不自动执行
});

// 当组件挂载时，将渲染器组件赋值给 renderer
watch(rendererComponent, (newVal) => {
  if (newVal) {
    renderer.value = newVal;
    console.log('渲染器组件已更新');
  }
});

// 监听握手完成状态
watch(handshakeCompleted, (newVal) => {
  if (newVal) {
    console.log('握手完成，开始获取渲染组件');
    getRenderComponent().then((component) => {
      if (component) {
        renderer.value = component;
      }
    });
  }
});

// 组件挂载后执行初始化
onMounted(async () => {
  // 1. 初始化低代码引擎
  await initLowCodeEngine();

  // 2. 开始获取渲染组件
  getRenderComponent().then((component) => {
    if (component) {
      renderer.value = component;
    }
  });

  // 3. 同时启动握手过程，但不阻塞主流程
  initPostmateHandshake().catch((error) => {
    console.warn('握手失败:', error);
  });
});
</script>

<template>
  <div style="padding: 20px">
    <component :is="renderer" v-if="renderer" />
    <div
      v-else-if="!isLoading"
      style="margin-top: 50px; color: red; text-align: center"
    >
      组件加载失败，请检查控制台日志
    </div>
  </div>
</template>
