<template>
  <!-- 节点渲染 -->

  <!-- 图片 -->
  <Image
    v-if="node.tag === 'img'" 
    :id="node.attrs?.id" 
    mode="widthFix" 
    :class="'_img ' + (node.attrs?.class || '')" 
    :style="node.attrs?.style || {}" 
    :src="node.attrs?.src as string || ''" 
    :touchable="true"
    @click="preview(node.attrs?.src as string)"
  />
  
  <!-- 换行 -->
  <!-- #ifdef H5 -->
  <br v-else-if="node.tag === 'br'" />
  <!-- #endif -->
  <!-- #ifndef H5 -->
  <text v-else-if="node.tag === 'br'">\n</text>
  <!-- #endif -->
  
  <!-- 链接 -->
  <view 
    v-else-if="node.tag === 'a'" 
    :id="node.attrs?.id" 
    :class="(node.attrs?.href ? '_a ' : '') + (node.attrs?.class || '')" 
    hover-class="_hover" 
    :style="'display:inline;' + (node.attrs?.style || '')" 
    @tap.stop="linkTap" 
  >
    <ParseNodeRender 
      v-for="(child, index) in node.children" 
      :key="index" 
      :node="child" 
    />
  </view>
  
  <!-- 视频 -->
  <video 
    v-else-if="node.tag === 'video'" 
    :id="node.attrs?.id" 
    :class="node.attrs?.class || ''" 
    :style="node.attrs?.style || {}" 
    :autoplay="Boolean(node.attrs?.autoplay || false)" 
    :controls="Boolean(node.attrs?.controls || true)" 
    :loop="Boolean(node.attrs?.loop || false)" 
    :muted="Boolean(node.attrs?.muted || false)" 
    :object-fit="node.attrs?.['object-fit'] || 'contain'" 
    :poster="node.attrs?.poster as string || ''" 
    :src="node.attrs?.src as string || ''" 
  />
  
  <!-- 音频 -->
  <!-- #ifndef H5 -->
  <audio 
    v-else-if="node.tag === 'audio'" 
    :id="node.attrs?.id" 
    :class="node.attrs?.class || ''" 
    :style="node.attrs?.style || {}" 
    :author="node.attrs?.author || ''" 
    :controls="Boolean(node.attrs?.controls || true)" 
    :loop="Boolean(node.attrs?.loop || false)" 
    :name="node.attrs?.name || ''" 
    :poster="node.attrs?.poster || ''" 
    :src="node.attrs?.src as string || ''" 
  />
  <!-- #endif -->
  
  <!-- 嵌入小程序内容 -->
  <view v-else-if="node.tag === 'inject-mp'">
    <InjectMPRender :type="node.attrs?.type as string || ''" v-bind="node.attrs" />
  </view>

  <!-- 表格 -->
  <view
    v-else-if="node.tag === 'table'"
    :id="node.attrs?.id"
    :class="'_parse_table ' + (node.attrs?.class || '')"
    :style="style"
  >
    <ParseNodeRender
      v-for="(child, index) in node.children"
      :key="index"
      :node="child"
    />
  </view>
  <view
    v-else-if="node.tag === 'thead' || node.tag === 'tbody'"
    :class="node.tag === 'thead' ? '_parse_thead' : '_parse_tbody'"
    :style="style"
  >
    <ParseNodeRender
      v-for="(child, index) in node.children"
      :key="index"
      :node="child"
    />
  </view>
  <view
    v-else-if="node.tag === 'tr'"
    :class="'_parse_tr ' + (node.attrs?.class || '')"
    :style="style"
  >
    <ParseNodeRender
      v-for="(child, index) in node.children"
      :key="index"
      :node="child"
    />
  </view>
  <view
    v-else-if="node.tag === 'th'"
    :class="'_parse_th ' + (node.attrs?.class || '')"
    :style="style"
  >
    <ParseNodeRender
      v-for="(child, index) in node.children"
      :key="index"
      :node="child"
    />
  </view>
  <view
    v-else-if="node.tag === 'td'"
    :class="'_parse_td ' + (node.attrs?.class || '')"
    :style="style"
  >
    <ParseNodeRender
      v-for="(child, index) in node.children"
      :key="index"
      :node="child"
    />
  </view>

  <!-- 特殊标签，例如 ol ul 需要在前缀加序号 -->
  <view v-else-if="node.tag === 'li'" 
    class="_ol_ul_container"
    :style="style"
    :class="node.attrs?.class || ''"
  >
    <text v-if="node.parentTag === 'ol'" class="_ol_prefix">·</text>
    <text v-else class="_ul_prefix">{{ (node.index || 0) + 1 }}.</text>
    
    <ParseNodeRender
      v-for="(child, index) in node.children"
      :key="index"
      :node="child"
    />
  </view>

  <!-- 其他标签 -->
  <view
    v-else-if="node.tag !== 'text'"
    :id="node.attrs?.id"
    :data-tag="node.tag"
    :class="node.attrs?.class || ''"
    :style="style"
    @click="viewTap(node.attrs?.id)"
  >
    <ParseNodeRender
      v-for="(child, index) in node.children"
      :key="index"
      :node="child"
    />
  </view>

  <!-- 文本 -->
  <text 
    v-else
    :style="style"
    :class="node.attrs?.class || ''" 
  >
    {{ node.attrs?.content }}
  </text>
</template>

<script setup lang="ts">
import { computed, inject, ref, type Ref } from 'vue';
import ParseNodeRender from './ParseNodeRender.vue';
import type { ParseNode } from './Parse';
import InjectMPRender from '@/common/components/rich/InjectMPRender.vue';
import Image from '@/components/basic/Image.vue';

const props = withDefaults(defineProps<{
  node: ParseNode;
}>(), {
});

const emit = defineEmits(['linkTap', 'viewTap']);
const tagStyle = inject<Ref<Record<string, string>>>('tagStyle', ref({}));
const classStyle = inject<Ref<Record<string, string>>>('classStyle', ref({}));
const praseImages = inject<Ref<string[]>>('praseImages', ref([]));
// 与 HTML 标准默认样式（UA 样式）一致，参考 CSS 2.1 / HTML5 规范
const builtInStyles = {
  // 标题标签 (CSS 2.1 suggested defaults)
  'h1': 'font-size: 2em; font-weight: bold; margin: 0.67em 0;',
  'h2': 'font-size: 1.5em; font-weight: bold; margin: 0.75em 0;',
  'h3': 'font-size: 1.17em; font-weight: bold; margin: 0.83em 0;',
  'h4': 'font-size: 1em; font-weight: bold; margin: 1.12em 0;',
  'h5': 'font-size: 0.83em; font-weight: bold; margin: 1.5em 0;',
  'h6': 'font-size: 0.67em; font-weight: bold; margin: 2.33em 0;',

  // 段落和引用
  'p': 'margin: 1em 0;',
  'blockquote': 'margin: 1em 0; border-left: 4px solid #ddd; padding-left: 1em; color: #666;',

  // 列表
  'ul': 'margin: 1em 0; padding-left: 40px;',
  'ol': 'margin: 1em 0; padding-left: 40px;',
  'li': 'margin: 0.5em 0;',

  // 强调标签
  'b': 'font-weight: bold;',
  'strong': 'font-weight: bold;',
  'i': 'font-style: italic;',
  'em': 'font-style: italic;',
  'u': 'text-decoration: underline;',
  'del': 'text-decoration: line-through;',

  // 代码相关 (UA 仅 monospace，无背景)
  'code': 'font-family: monospace;',
  'pre': 'font-family: monospace; white-space: pre; margin: 1em 0;',

  // 其他内联标签
  'mark': 'background-color: yellow; color: black;',
  'sup': 'font-size: smaller; vertical-align: super;',
  'sub': 'font-size: smaller; vertical-align: sub;',
  'small': 'font-size: smaller;',
  'large': 'font-size: larger;',

  // 分隔线 (CSS 2.1: margin 0.5em 0，inset 在小程序端用 solid 兼容)
  'hr': 'border: none; border-top: 1px solid #ccc; margin: 0.5em 0;',

  // 表格（简单布局，无 table-layout）
  'table': 'display: block; width: 100%; margin: 1em 0; overflow-x: auto;',
  'thead': 'display: block;',
  'tbody': 'display: block;',
  'tr': 'display: flex; flex-direction: row;',
  'th': 'font-weight: bold; padding: 8px 10px; border-right: 1px solid #ddd; border-bottom: 1px solid #ddd; flex: 1; min-width: 0; box-sizing: border-box;',
  'td': 'padding: 8px 10px; border-right: 1px solid #ddd; border-bottom: 1px solid #ddd; flex: 1; min-width: 0; box-sizing: border-box;'
} as Record<string, string>;
const style = computed(() => 
  [
    (builtInStyles[props.node.tag] || ''),
    (tagStyle.value[props.node.tag] || ''),
    (classStyle.value[props.node.attrs?.class as string] || ''),
    isInline.value ? 'display:inline' : '',
    (props.node.attrs?.style || ''), 
  ].join(';'),
);
const isInline = computed(() => [
  'span', 'a', 'large','small',
  'i', 'b', 'em', 'strong', 'u', 'del',
  'code', 'sup', 'sub', 'mark'
].includes(props.node.tag));

// 链接点击事件
const linkTap = (e: any) => {
  const href = props.node.attrs?.href as string;
  emit('linkTap', href);
  if (href) {
    if (href[0] === '#') {
      // 跳转锚点
      // 实现锚点跳转逻辑
    } else if (href.includes('://')) {
      // 外部链接
      uni.showModal({
        title: '打开链接',
        content: href,
        success: (res) => {
          if (res.confirm) {
            // #ifdef H5
            window.open(href);
            // #endif
            // #ifdef MP
            uni.setClipboardData({
              data: href,
              success: () => {
                uni.showToast({
                  title: '链接已复制',
                  duration: 2000
                });
              }
            });
            // #endif
            // #ifdef APP-PLUS
            plus.runtime.openWeb(href);
            // #endif
          }
        }
      });
    } else {
      // 跳转页面
      uni.navigateTo({
        url: href,
        fail: () => {
          uni.switchTab({
            url: href,
            fail: () => {}
          });
        }
      });
    }
  }
};

const viewTap = (e: any) => {
  emit('viewTap', e);
};

function preview(url: string) {
  if (url) {
    if (praseImages.value.includes(url)) {
      uni.previewImage({
        urls: praseImages.value,
        current: praseImages.value.indexOf(url),
      })
    } else {
      uni.previewImage({
        urls: [url],
      })
    }
  }
}

defineOptions({
  options: {
    inheritAttrs: false,
    virtualHost: true,
  }
})
</script>

<style scoped>
/* a 标签默认效果 */
._a {
  padding: 1.5px 0;
  color: #366092;
  word-break: break-all;
}

/* a 标签点击态效果 */
._hover {
  text-decoration: underline;
  opacity: 0.7;
}

/* 图片默认效果 */
._img {
  max-width: 100%;
  -webkit-touch-callout: none;
}

/* ol ul 容器 */
._ol_ul_container {
  display: block;
}
/* ol/ul 前缀 */
._ol_prefix,
._ul_prefix {
  display: inline-block;
  padding-right: 10px;
}

/* 表格：用 view + flex 模拟，无 table 标签；仅画右、下边框，首列补左边框，首行补上边框 */
._parse_table {
  border: 1px solid #ddd;
  border-radius: 4px;
}
._parse_thead ._parse_tr {
  background-color: #f5f5f5;
}
._parse_thead ._parse_tr ._parse_th,
._parse_thead ._parse_tr ._parse_td {
  border-top: 1px solid #ddd;
}
._parse_tbody ._parse_tr:first-child ._parse_th,
._parse_tbody ._parse_tr:first-child ._parse_td {
  border-top: 1px solid #ddd;
}
._parse_tr ._parse_th:first-child,
._parse_tr ._parse_td:first-child {
  border-left: 1px solid #ddd;
}
._parse_th,
._parse_td {
  word-break: break-all;
}

/* 视频默认效果 */
._video {
  width: 300px;
  height: 225px;
}
</style>
