<template>
  <div>
    <div style="width: 100%; display: inline-block; vertical-align: top; height: calc(100vh - 50px - 34px)">
      <umo-editor v-if="editorReady" v-bind="options" ref="editorRef" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { getCurrentInstance, nextTick, onMounted, onUnmounted, ref } from 'vue';
import { UmoEditor } from '@umoteam/editor';
import { getPrintTemplate } from '@/api/oa/base/printTemplate';
import { templateAssign } from '@/api/oa/base/templateVariable';
import { useRoute } from 'vue-router';

const route = useRoute();
const proxy = getCurrentInstance()?.proxy;

const template = ref<any>({});
const editorRef = ref();
const editorReady = ref(false);
let templateData: Record<string, any> = {};
let isUnmounted = false;
const defaultMargin = { left: 2.1, right: 2.1, top: 2.2, bottom: 2.2 };

const options = ref({
  document: {
    title: '',
    content: {
      type: 'doc',
      content: []
    },
    placeholder: {
      en_US: 'Please enter the document content...',
      zh_CN: '请输入文档内容...'
    },
    enableSpellcheck: true,
    enableMarkdown: false,
    enableBubbleMenu: true,
    enableBlockMenu: true,
    readOnly: false,
    autofocus: true,
    characterLimit: 0,
    typographyRules: {
      emDash: false
    },
    editorProps: {},
    parseOptions: {
      preserveWhitespace: 'full'
    },
    autoSave: {
      enabled: false
    }
  },
  toolbar: {
    menus: ['base', 'export']
  },
  disableExtensions: [
    'ordered-list',
    'quote',
    'code',
    'select-all',
    'import-word',
    'viewer',
    'print',
    'export-image',
    'export-text',
    'share',
    'embed'
  ],
  page: {
    showBreakMarks: false,
    defaultMargin
  },
  // 这里与合同预览保持同一导出入口配置，避免报价导出在 UMO 内部能力上再次分叉
  onSave: async () => {
    return true;
  },
  onFileUpload: async (file: any) => {
    return file;
  }
});

// 常量赋值
const renderTemplate = (str: string, data: Record<string, any>) => {
  return str.replace(/#\{(.*?)\}/g, (_, path) => {
    const arr = path.split('.');
    if (arr.length > 0) {
      arr[0] = `#{${arr[0]}}`;
    }
    return arr.reduce((o: any, k: string) => o?.[k], data) ?? ' ';
  });
};

// 数组赋值
const rowRenderTemplate = (str: string, index: number) => {
  let res = str;
  res = res.replace(/\^\{(.*?)\}/g, (_, path) => {
    return templateData[`^{${path}}`]?.[index] || ' ';
  });
  res = res.replace(/#\{(.*?)\}/g, (_, path) => {
    const arr = path.split('.');
    if (arr.length > 0) {
      arr[0] = `#{${arr[0]}}`;
    }
    return arr.reduce((o: any, k: string) => o?.[k] || ' ', templateData) ?? ' ';
  });
  return res;
};

// 判断是否包含数组占位符
const hasCaretPattern = (arr: any[]) => {
  const regex = /\^\{.*?\}/;
  let length = 0;
  let res = false;

  function traverse(items: any[]) {
    for (const item of items) {
      if (item.text && regex.test(item.text)) {
        length = Math.max(length, templateData[item.text]?.length || 0);
        res = true;
      }
      if (item.content && Array.isArray(item.content)) {
        traverse(item.content);
      }
    }
  }

  traverse(arr);
  return [res, length] as [boolean, number];
};

// 行数据填充
const fillRowData = (e: any, index: number) => {
  if (Array.isArray(e.content)) {
    e.content.forEach((item: any) => fillRowData(item, index));
  } else {
    e.text = rowRenderTemplate(e.text || ' ', index);
  }
  return e;
};

// 表格处理
const tableTemplate = (table: any[]) => {
  const data = JSON.parse(JSON.stringify(table));
  const arr: any[] = [];
  data.forEach((item: any) => {
    const [bol, length] = hasCaretPattern(JSON.parse(JSON.stringify(item.content)));
    if (bol) {
      const obj = JSON.parse(JSON.stringify(item));
      Array(length)
        .fill(0)
        .forEach((_, index) => {
          arr.push(fillRowData(JSON.parse(JSON.stringify(obj)), index));
        });
    } else {
      arr.push(fillData(item));
    }
  });
  return arr.filter((item) => item);
};

// 递归填充
const fillData = (e: any): any => {
  if (e.type === 'table') {
    e.content = tableTemplate(e.content);
  } else {
    if (Array.isArray(e.content)) {
      e.content.forEach((item: any) => fillData(item));
    } else {
      e.text = renderTemplate(e.text || ' ', templateData);
    }
  }
  return e;
};

const normalizeQueryValue = (value: unknown) => {
  return Array.isArray(value) ? value[0] : value;
};

const resolvePageMargin = (pageConfig: string | undefined) => {
  const config = JSON.parse(pageConfig || '{}');
  const margin = {
    ...defaultMargin,
    ...(config.pageMargin || {})
  };
  // UMO 的页边距对象里如果混入 layout 字段，导出时会和合同页表现不一致，这里统一剔除
  delete (margin as Record<string, any>).layout;
  return margin;
};

onUnmounted(() => {
  isUnmounted = true;
});

onMounted(async () => {
  try {
    const quoteIdParam = normalizeQueryValue(route.query.quoteId);
    const templateIdParam = normalizeQueryValue(route.query.templateId);
    // 报价单ID可能是 Long/雪花ID，前端这里保持字符串透传，避免 Number 转换后发生精度丢失导致串单
    const quoteId = quoteIdParam ? String(quoteIdParam) : undefined;
    const templateId = templateIdParam ? String(templateIdParam) : undefined;

    if (!quoteId || !templateId) {
      proxy?.$modal.msgError('缺少模板导出参数，请返回列表页重试');
      return;
    }

    const { data: assignData } = await templateAssign({ templateType: 4, quoteId });
    templateData = {};
    (assignData || []).forEach((item: any) => {
      templateData[item.varName] = item.varValue || ' ';
    });

    const tplResp = await getPrintTemplate(templateId);
    if (isUnmounted) {
      return;
    }
    template.value = tplResp.data;

    options.value.page.defaultMargin = resolvePageMargin(tplResp.data.pageConfig);

    const docData = JSON.parse(tplResp.data.templateData || '{}');
    const dataFilled = fillData(docData);
    // 先把模板和页边距准备完整再挂载编辑器，避免导出页在快速切换时出现空节点补丁异常
    editorReady.value = true;
    await nextTick();
    if (isUnmounted) {
      return;
    }
    editorRef.value?.setContent(dataFilled);
  } catch (error) {
    console.error('quoteView export init error', error);
    proxy?.$modal.msgError('加载报价模板失败，请稍后重试');
  }
});
</script>

<style scoped lang="scss">
::deep(.umo-toolbar-actions.ribbon) {
  display: none !important;
}

::deep(.umo-status-bar-left .umo-button:nth-child(4)) {
  display: none;
}

::deep(.umo-status-bar-left .umo-button:nth-child(5)) {
  display: none;
}

::deep(.t-button--theme-warning) {
  border-color: var(--td-warning-color-hover);
  background-color: var(--td-warning-color-hover);
}
</style>
<style>
.umo-footer {
  position: sticky;
  bottom: 0px;
}
</style>
