<template>
	<div class="layout-container">
		<div class="layout-main">
			<div class="layout-main-center">
				<div class="report-header">
					<div class="report-title">政令原文</div>

					<el-switch v-model="isHighlight" @change="handleHighlight" />
					<div class="switch-label switch-label-left">高亮实体</div>

					<el-switch v-model="isTranslate" @change="handleTranslate" />
					<div class="switch-label">译文显示</div>

					<div class="btn" @click="emits('download')">
						<div class="icon icon-gap-4">
							<img src="./assets/icons/download.png" alt="" />
						</div>
						<div class="text">下载</div>
					</div>

          <div class="btn" @click="handleFindWord('open')">
						<div class="icon icon-gap-6">
							<img src="./assets/icons/search.png" alt="" />
						</div>
						<div class="text">查找</div>
					</div>

					<div class="find-word-box" v-if="findWordBox">
						<div class="find-word-input">
							<el-input v-model="findWordTxt" placeholder="查找原文内容" @input="handleUpdateWord" />
						</div>
						<div class="find-word-limit">{{ findWordNum }}/{{ findWordMax }}</div>
						<div class="find-word-icon" @click="handleFindWord('last')">
							<el-icon><ArrowUp /></el-icon>
						</div>
						<div class="find-word-icon" @click="handleFindWord('next')">
							<el-icon><ArrowDown /></el-icon>
						</div>
						<div class="find-word-icon" @click="handleFindWord('close')">
							<el-icon><Close /></el-icon>
						</div>
					</div>
				</div>

				<div :class="['report-main', {'is-highlight': isHighlight}]">
					<div v-if="!formatData.length" class="no-content">暂无数据</div>
					<el-scrollbar v-else height="100%">
						<div v-for="(item, index) in formatData" :key="index" class="content-row">
							<div class="content-en" :class="{ 'only-show': !isTranslate }">
                <template v-for="(node, num) in item.contentEn" :key="num">
                  <el-icon v-if="node.icon && isHighlight" color="#508fd4" size="14"><Search /></el-icon>
                  <span v-else-if="node.point" class="find-light-point"></span>
                  <span v-else-if="node.fill" :class="node.class" @click="handleHighLight(node)">{{ node.txt }}</span>
                  <span v-else :class="node.class">{{ node.txt }}</span>
                </template>
              </div>
							<div class="content-ch" v-if="isTranslate">
                <template v-for="(node, num) in item.contentCh" :key="num">
                  <el-icon v-if="node.icon && isHighlight" color="#508fd4" size="14"><Search /></el-icon>
                  <span v-else-if="node.point" class="find-light-point"></span>
                  <span v-else-if="node.fill" :class="node.class" @click="handleHighLight(node)">{{ node.txt }}</span>
                  <span v-else :class="node.class">{{ node.txt }}</span>
                </template>
              </div>
						</div>
					</el-scrollbar>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup>
import { nextTick, ref } from "vue";
import { debounce } from "lodash";
import { extractTextEntity } from "@/api/intelligent";

const emits = defineEmits(["download"]);

const isHighlight = ref(true); // 是否高亮实体
const isTranslate = ref(true); // 是否显示译文
const handleTranslate = () => {
  if (findWordTxt.value?.trim()) handleUpdateWord()
}

const findWordTxt = ref("");
const findWordBox = ref(false);
const findWordNum = ref(0);
const findWordMax = ref(0);
const formatData = ref([])
const handleUpdateWord = debounce(() => {
	findWordNum.value = 0;
	findWordMax.value = 0;

  formatData.value = originData.map(item => {
    return {
      contentEn: onHighlightedText(item.contentEn, keywordEn),
      contentCh: isTranslate.value ? onHighlightedText(item.contentCh, keywordCh) : [],
    }
  })

  if (findWordMax.value) {
    findWordNum.value = 1;
    nextTick(updateActiveHighlight)
  }
}, 300);

function handleFindWord(event) {
	switch (event) {
		case "open":
			findWordBox.value = true;
			break;
		case "last":
			if (findWordMax.value > 1) {
				findWordNum.value = findWordNum.value === 1 ? findWordMax.value : findWordNum.value - 1;
				updateActiveHighlight();
			}
			break;
		case "next":
			if (findWordMax.value > 1) {
				findWordNum.value = findWordNum.value === findWordMax.value ? 1 : findWordNum.value + 1;
				updateActiveHighlight();
			}
			break;
		case "close":
			findWordBox.value = false;
			findWordTxt.value = "";
			handleUpdateWord();
			break;
	}
}

const updateActiveHighlight = () => {
  if (!findWordNum.value) return
	const spans = document.querySelectorAll("span.find-light-point");
	spans.forEach((span, index) => {
		if (index + 1 === findWordNum.value) span.scrollIntoView({});
	});
}

// 政令原文信息
let originData = []
let keywordCh = []
let keywordEn = []
const setOriginalData = (data) => {
  originData = []
  let num = Math.max(data.content.length, data.contentEn.length)
  for (let i = 0; i < num; i++) {
    let obj = {
      contentCh: data.content[i] || "",
      contentEn: data.contentEn[i] || "",
    }
    originData.push(obj);
  }

	let allEn = ""
	let allCh = ""

	formatData.value = originData.map(item => {
		allEn += item.contentEn + "。"
		allCh += item.contentCh + "。"
		return {
			contentEn: [{txt: item.contentEn, class: ""}],
			contentCh: [{txt: item.contentCh, class: ""}]
		}
	})

	extractTextEntity(allEn || "").then(res => {
		if (res?.result?.length) keywordEn = res.result || []
		originData.forEach((item, index) => {
			formatData.value[index].contentEn = onHighlightedText(item.contentEn, keywordEn);
		})
	})

	extractTextEntity(allCh || "").then(res => {
		if (res?.result?.length) keywordCh = res.result || []
		if (isTranslate.value) {
			originData.forEach((item, index) => {
				formatData.value[index].contentCh = onHighlightedText(item.contentCh, keywordCh);
			})
		}
	})
}

defineExpose({ setOriginalData })

// 文本分割
const onHighlightedText = (text, nounList) => {
  if (text === "") return []
  // 获取区间（合并相邻/重叠），并自动过滤空关键词
  const getIntervals = (str, keywords) => {
    const intervals = [];
    for (const kw of keywords) {
      if (!kw) continue; // 跳过空字符串，防止无限循环
      let idx = 0;
      while ((idx = str.indexOf(kw, idx)) !== -1) {
        intervals.push({ start: idx, end: idx + kw.length });
        idx += kw.length;
      }
    }
    if (!intervals.length) return [];
    intervals.sort((a, b) => a.start - b.start);
    const merged = [intervals[0]];
    for (let i = 1; i < intervals.length; i++) {
      const prev = merged[merged.length - 1];
      const curr = intervals[i];
      if (curr.start <= prev.end) {
        prev.end = Math.max(prev.end, curr.end);
      } else {
        merged.push(curr);
      }
    }
    return merged;
  };

  // 处理空搜索文本
	let textTrim = findWordTxt.value.trim() || "";
  const searchIntervals = textTrim ? getIntervals(text, [textTrim]) : [];
  const nounIntervals = getIntervals(text, nounList.map(n => n.text_span));

  // 收集分割点
  const points = new Set([0, text.length]);
  [...searchIntervals, ...nounIntervals].forEach(({ start, end }) => {
    points.add(start);
    points.add(end);
  });
  const sortedPoints = Array.from(points).sort((a, b) => a - b);

  const list = [];

  for (let i = 0; i < sortedPoints.length - 1; i++) {
    const start = sortedPoints[i];
    const end = sortedPoints[i + 1];
    if (start === end) continue;

    const fragment = text.slice(start, end);
    const findLight = searchIntervals.some(s => start >= s.start && end <= s.end);
    const highLight = nounIntervals.some(n => start >= n.start && end <= n.end);

    const classes = [];
    if (findLight) classes.push("find-light");
    if (highLight) classes.push("high-light");
    const textItem = { txt: fragment, class: classes.join(" ") };
    if (highLight) {
      const nounInterval = nounIntervals.find(n => start >= n.start && end <= n.end);
      if (nounInterval) {
        textItem.fill = text.slice(nounInterval.start, nounInterval.end);
      }
    }
    list.push(textItem);

    // 实体区间结束后添加图标
    const iconAdded = new Set();
    for (const nounInterval of nounIntervals) {
      const key = `${nounInterval.start}-${nounInterval.end}`;
      if (end === nounInterval.end && !iconAdded.has(key)) {
        list.push({ icon: true, class: "" });
        iconAdded.add(key);
        break;
      }
    }
    // 搜索区间结束后添加锚点
    const pointAdded = new Set();
    for (const searchInterval of searchIntervals) {
      const key = `${searchInterval.start}-${searchInterval.end}`;
      if (end === searchInterval.end && !pointAdded.has(key)) {
        findWordMax.value++;
        list.push({ point: true, class: "" });
        pointAdded.add(key);
        break;
      }
    }
  }
  return list;
};

// 点击高亮实体
import { useGotoSearchResults } from "@/router/modules/comprehensiveSearch";
const gotoSearchResults = useGotoSearchResults();
const handleHighLight = (node) => {
	gotoSearchResults(node.fill, '')
}
</script>

<style lang="scss" scoped>
.is-highlight .high-light {
  color: var(--color-primary-100);
  cursor: pointer;
}
.find-light {
  background-color: #ffff00;
}
.layout-container {
	width: 100%;
	height: 100%;
	background-color: #f7f8f9;

	.layout-main {
		height: 100%;
		display: flex;
		flex-direction: column;
		align-items: center;
		.layout-main-center {
			width: 1600px;
			background-color: white;
			padding: 0 60px;
			flex: auto;
				height: 100%;
				min-height: 0;
			display: flex;
			flex-direction: column;
			.report-header {
				height: 80px;
				display: flex;
				align-items: center;
				border-bottom: solid 1px rgba(234, 236, 238, 1);
				margin: 0 20px 10px;
				position: relative;
				.find-word-box {
					position: absolute;
					top: -50px;
					right: 0px;
					width: 430px;
					height: 60px;
					border: 1px solid rgba(230, 231, 232, 1);
					background-color: white;
					border-radius: 6px;
					display: flex;
					align-items: center;
					.find-word-input {
						flex: auto;
					}
					.find-word-limit {
						border-right: solid 1px rgba(230, 231, 232, 1);
						color: #5f656c;
						padding-right: 16px;
					}
					.find-word-icon {
						padding: 10px 12px;
						margin: 0 2px;
						cursor: pointer;
					}
				}
				.report-title {
					color: rgba(59, 65, 75, 1);
					font-family: Microsoft YaHei;
					font-size: 20px;
					line-height: 20px;
					font-weight: 700;
					flex: 1;
				}
				.btn {
					margin-left: 10px;
					width: 88px;
					height: 32px;
					box-sizing: border-box;
					border: 1px solid rgba(230, 231, 232, 1);
					border-radius: 6px;
					background: rgba(255, 255, 255, 1);
					display: flex;
					justify-content: center;
					align-items: center;
					cursor: pointer;
					.text {
						height: 24px;
						color: rgba(95, 101, 108, 1);
						font-family: Microsoft YaHei;
						font-style: Regular;
						font-size: 14px;
						font-weight: 400;
						line-height: 24px;
						letter-spacing: 0px;
						text-align: left;
					}
					.icon {
						width: 16px;
						height: 16px;
						font-size: 0px;
						img {
							width: 100%;
							height: 100%;
						}
					}
					.icon-gap-4 {
						margin-right: 4px;
					}
					.icon-gap-6 {
						margin-right: 6px;
					}
				}
			}

			.report-main {
				flex: auto;
				height: 20px;
				padding: 10px 0;

				:deep(.el-scrollbar) {
					height: 100%;
				}

				.no-content {
					height: 100%;
					display: flex;
					align-items: center;
					justify-content: center;
					color: rgba(59, 65, 75, 1);
					font-family: Microsoft YaHei;
					font-style: Regular;
					font-size: 20px;
					font-weight: 400;
				}

				.content-row {
					display: flex;
					width: 100%;
					padding: 0 20px;
					min-height: 100px;
					gap: 80px;

					.content-en,
					.content-ch {
						width: 50%;
						flex: auto;
						padding-bottom: 40px;
						box-sizing: border-box;
						font-size: 16px;
						line-height: 1.8;
						color: #3b414b;
						font-family: Microsoft YaHei;
						text-align: justify;
						white-space: pre-wrap;
					}
					.only-show {
						padding-bottom: 10px;
					}
				}
			}
		}
	}
}

.switch-label {
	margin-left: 6px;
}
.switch-label-left {
	margin-right: 10px;
}

:deep(.el-scrollbar__bar.is-vertical) {
	right: 0px;
	width: 4px;
	background: transparent;
	border-radius: 2px;
	& > div {
		background: #c5c7c9;
		opacity: 1;
	}
	& > div:hover {
		background: #505357;
	}
}
</style>
