<template>
  <ContentWrap>
    <el-form
      class="-mb-15px"
      :model="queryParams"
      ref="queryFormRef"
      :inline="true"
      label-width="95px"
    >
      <el-form-item label="新任命链接" prop="urls" class="!w-100%" :required="true">
        <el-input
          v-model="queryParams.urls"
          class="!w-75%"
          type="textarea"
          :rows="2"
          placeholder="请输入需要解析的新任命链接"
        />
        <el-button
					type="primary"
					class="ml-10px"
					plain
					@click="handleAnalysis"
				>抓取网页信息</el-button>
      </el-form-item>
    </el-form>
  </ContentWrap>

  <el-row v-if="contents.length" :gutter="20">
    <el-col v-for="(content, index) in contents" :key="index" :span="24">
      <el-card class="!h-600px" v-loading="!content.data">
        <template #header>
          <div class="flex items-center justify-between">
            <el-text class="flex-1" truncated>{{ content.url }}</el-text>
          </div>
        </template>
        <iframe
          :id="content.id"
          class="!w-100% !h-[calc(100vh-90px)]"
          src=""
          frameborder="0"
        ></iframe>
      </el-card>
    </el-col>
  </el-row>
</template>

<script setup>
/** 人才采集 网页解析 */
defineOptions({ name: 'WebPageParsing' })
import axios from 'axios'
import TurndownService from 'turndown'
import { talentWebParsingApi } from '@/api/menduner/system/talentMap/webParsing.ts'
import { generateUUID } from '@/utils'
import { ElLoading } from 'element-plus'
import { timesTampChange } from '@/utils/transform/date.js'

const emit = defineEmits(['analysis', 'reset'])
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化

const queryParams = reactive({
  urls: ''
})
const queryFormRef = ref()
const contents = ref([])
const drawer = ref(false)

// 创建转换服务
const turndownService = new TurndownService({
  headingStyle: 'atx',
  codeBlockStyle: 'fenced',
  bulletListMarker: '-'
})

// 添加自定义规则处理微信公众号特有内容
turndownService.addRule('wechatImages', {
  filter: 'img',
  replacement: (content, node) => {
    const alt = node.getAttribute('alt') || ''
    const src = node.getAttribute('src') || node.getAttribute('data-src') || ''
    return `![${alt}](${src})`
  }
})

// 提取主要内容并转换为Markdown文件
const wechatHtmlToMarkdown = (html) => {
  // 创建一个临时DOM解析器
  const parser = new DOMParser()
  const doc = parser.parseFromString(html, 'text/html')

  // 获取文章标题作为文件名
  let filename = '新任命.md'
  const title = doc.getElementById('activity-name')?.innerText
  if (title) {
    // 检查标题中是否包含"先生"或"女士"
    const mrIndex = title.indexOf('先生')
    const msIndex = title.indexOf('女士')
    
    if (mrIndex !== -1) {
      // 如果包含"先生"，截取前面的部分
      filename = title.substring(0, mrIndex).trim() + '.md'
    } else if (msIndex !== -1) {
      // 如果包含"女士"，截取前面的部分
      filename = title.substring(0, msIndex).trim() + '.md'
    } else {
      // 如果不包含，使用原标题
      filename = title.trim() + '.md'
    }
  }

  // 提取正文内容 - 微信公众号文章通常在id="js_content"的div中
  const content = doc.querySelector('#js_content') || doc.body

  // 移除不需要的元素
  const elementsToRemove = [
    'script', 'style', 'iframe', 'button',
    '.qr_code', '.rich_media_extra', '.copyright'
  ]

  elementsToRemove.forEach(selector => {
    content.querySelectorAll(selector).forEach(el => el.remove())
  })

  // 转换为Markdown
  const result = turndownService.turndown(content.innerHTML)

  const blob = new Blob([result], { type: 'text/markdown' })
  return new File([blob], filename, { type: 'text/markdown' })
}

function extractPublishTime(doc, html) {
  // 1. 通过 id
  let timeEl = doc.getElementById('publish_time')
  if (timeEl && timeEl.innerText) return timeEl.innerText.trim()

  // 2. 通过 class
  let metaEls = doc.querySelectorAll('.rich_media_meta.rich_media_meta_text')
  for (let el of metaEls) {
    if (el.innerText && /\d{4}年\d{1,2}月\d{1,2}日/.test(el.innerText)) {
      return el.innerText.trim()
    }
  }

  // 3. 通过 meta 标签
  let meta = doc.querySelector('meta[property="article:published_time"]')
  if (meta && meta.content) return meta.content.trim()

  // 4. 通过正则从 html 里提取
  let match = html.match(/(\d{4}年\d{1,2}月\d{1,2}日)/)
  if (match) return match[1]

  return ''
}

function tryExtractPublishTime(doc, html, cb, maxTry = 10, interval = 200) {
  let tryCount = 0
  const timer = setInterval(() => {
    const publishTime = extractPublishTime(doc, html)
    if (publishTime || tryCount >= maxTry) {
      clearInterval(timer)
      cb(publishTime)
    }
    tryCount++
  }, interval)
}

// 查看原网页
const showPage = (res) => {
  let html = res.data
  if (!html) return

   // 将 data-src 转化为 src
  html = html.replace(/data-src/g, 'src')
    // 需要获取文章发布时间的话需注释下一行代码
    // 移除HTML内容中所有的<script>标签，这样可以避免在iframe中执行潜在的不受信任的脚本。
    // .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/g, '')
    // 将HTML内容中所有的https替换为http，可能是为了避免在HTTPS环境下加载非HTTPS资源导致浏览器警告
    .replace(/https/g, 'http')
  
  nextTick(() => {
    const iframe = document.getElementById(res.id)
    if (!iframe) return
    const doc = iframe.contentDocument || iframe.document
    // 设置 iframe 中请求不发送 referrer，以绕过图片防盗链
    const htmlArr = html.split('</head>')
    const html_src_add = htmlArr[0] + '<meta name="referrer" content="never"></head>' + htmlArr[1]
    doc.open()
    doc.write(html_src_add)
    doc.close()

    // 通过延时获取文档高度赋值Iframe去除滚动条，根据实际情况增加延时时间
    setTimeout(() => {
      const jsContent = doc.getElementById('js_content')
			if (jsContent) {
        jsContent.style.visibility = 'visible'
        jsContent.style.opacity = 1
      }
    }, 100)

    // 获取发布时间
    setTimeout(() => {
      tryExtractPublishTime(doc, html, (publishTime) => {
        if (publishTime) {
          res.publish_time = publishTime && !['null', 'undefined'].includes(publishTime) ? publishTime
            .replace("年", "-")
            .replace("月", "-")
            .replace("日", "")
            .split(" ")[0] : timesTampChange(new Date().getTime(), 'Y-M-D')
        }
      });
    }, 100); // 先等100ms让iframe初步渲染，再开始轮询
  })
}

// 解析
const handleAnalysis = async () => {
	if (!queryParams.urls) return message.warning('请输入要抓取的新任命链接')

  if (contents.value?.length > 0) {
    await message.confirm('是否确认重新抓取？确认后当前内容将会清空！')
    // 重置右侧标签及表单
    emit('reset')
  }

  const loading = ElLoading.service({
    lock: true,
    text: '网页信息抓取中...',
    background: 'rgba(0, 0, 0, 0.7)',
  })

	contents.value = []

	const urlArr = queryParams.urls.split(',').map(url => url.trim()).filter(Boolean)

	const isWeChatUrl = urlArr.every(url => url.includes('https://mp.weixin.qq.com'))
	if (!isWeChatUrl) {
		message.warning('只支持微信公众号链接')
		return
	}

	if (urlArr.length > 1) return message.warning('只支持单个链接抓取')

  
  try {
    const data = await talentWebParsingApi.processUrls({ urlArr })
    const list = data?.contents || []
    if (!list || !list.length) return

    list.forEach(e => {
			contents.value.push({
				...e,
				publish_time: null,
				id: generateUUID(),
        file: wechatHtmlToMarkdown(e.data)
			})
		})
		contents.value.forEach(e => {
			showPage(e)
		})

    emit('analysis', contents.value)
  } finally {
    loading.close()
  }
}
</script>

<style scoped>
</style>