<template>
	<div class="layout-container">
		<div class="layout-main">
			<div class="header-main">
				<div class="layout-main-header">
					<div class="icon">
						<img :src="summaryInfo?.imageUrl" alt="" />
					</div>
					<div class="info">
						<div class="info-box1 one-line-ellipsis">{{ summaryInfo?.name || "--" }}</div>
						<div class="info-box2">
							<div class="info-box2-item">{{ summaryInfo?.postDate || "--" }}</div>
							|
							<div class="info-box2-item">{{ summaryInfo?.orgName || "--" }}</div>
							|
							<div class="info-box2-item one-line-ellipsis">{{ summaryInfo?.ename || "--" }}</div>
						</div>
					</div>
					<div class="layout-main-header-right-box">
						<div class="right-box-top">
							<div class="time">{{ summaryInfo?.postDate || "--" }}</div>
							<div class="name">{{ summaryInfo?.orgName || "--" }}</div>
						</div>
					</div>
				</div>
			</div>

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

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

					<el-switch v-model="isTranslate" />
					<div class="switch-label">原文显示</div>

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

					<div class="btn" @click="handleFindWord('open')">
						<div class="icon icon-gap-6">
							<img :src="defaultSearchIcon" 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">
					<div v-if="!displayReportData.length" class="noContent">{{ "暂无数据" }}</div>
					<el-scrollbar height="100%" v-else>
						<div
							v-for="item in displayReportData"
							:key="item.num"
							:class="['content-row', { 'high-light': isHighlight }]"
						>
							<div :class="['content-cn', { 'translate-cn': !isTranslate }]" v-html="item.content"></div>
							<div class="content-en" v-html="item.contentEn" v-if="isTranslate"></div>
						</div>
					</el-scrollbar>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup>
import defaultDownloadIcon from "./assets/icons/download.png";
import defaultSearchIcon from "./assets/icons/search.png";
import { nextTick, ref, watch } from "vue";
import { debounce } from "lodash";

// 该组件为公共展示组件：网络请求/下载等业务由父组件处理；查找、高亮、显示切换等通用交互在组件内部封装。
// 图标资源固定使用组件内置文件，保证组件资源自包含。
/**
 * 父组件需传入的数据结构说明
 *
 * @prop {Object} summaryInfo - 顶部摘要信息（用于展示 + 下载）
 * @prop {string} summaryInfo.imageUrl - 左上角图标/封面 URL
 * @prop {string} summaryInfo.name - 标题
 * @prop {string} summaryInfo.postDate - 发布时间（展示在头部与右侧信息）
 * @prop {string} summaryInfo.orgName - 发布机构（展示在头部与右侧信息）
 * @prop {string} summaryInfo.ename - 英文名/别名（头部展示）
 * @prop {string} [summaryInfo.url] - 原文 PDF 下载地址（父组件下载逻辑使用；组件点击“下载”仅触发事件）
 *
 * @prop {Array<Object>} reportData - 正文分段数组（用于原文渲染/查找高亮）
 * @prop {number|string} reportData[].num - 段落序号/唯一标识（用于列表 key）
 * @prop {string} reportData[].content - 中文段落 HTML 字符串（组件内使用 v-html 渲染）
 * @prop {string} reportData[].contentEn - 英文段落 HTML 字符串（组件内使用 v-html 渲染；关闭“原文显示”时不展示）
 */
const props = defineProps({
	summaryInfo: { type: Object, default: () => ({}) },
	reportData: { type: Array, default: () => [] },
});

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

const isHighlight = ref(false);
const isTranslate = ref(true);
const findWordTxt = ref("");
const findWordBox = ref(false);
const findWordNum = ref(0);
const findWordMax = ref(0);

const originReportData = ref([]);
const displayReportData = ref([]);

function escapeRegExp(text) {
	return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

function applyHighlightToText(text, searchTerm) {
	if (!text || !searchTerm) {
		return { html: text || "", count: 0 };
	}
	const escapedTerm = escapeRegExp(searchTerm);
	let count = 0;
	const html = String(text).replace(new RegExp(escapedTerm, "g"), (match) => {
		count += 1;
		return `<span class="highlight">${match}</span>`;
	});
	return { html, count };
}

function setDisplayFromOrigin() {
	displayReportData.value = originReportData.value.map((item) => ({
		...item,
		content: item.content || "",
		contentEn: item.contentEn || "",
	}));
}

function updateActiveHighlight() {
	const spans = document.querySelectorAll("span.highlight");
	spans.forEach((span, index) => {
		if (index + 1 === findWordNum.value) {
			span.scrollIntoView({});
			span.style.backgroundColor = "#ff9632";
		} else {
			span.style.backgroundColor = "#ffff00";
		}
	});
}

const doUpdateWord = () => {
	findWordNum.value = 0;
	findWordMax.value = 0;
	const term = findWordTxt.value?.trim();

	if (!term) {
		setDisplayFromOrigin();
		return;
	}

	displayReportData.value = originReportData.value.map((item) => {
		const cn = applyHighlightToText(item.content, term);
		const en = isTranslate.value ? applyHighlightToText(item.contentEn, term) : { html: item.contentEn, count: 0 };
		findWordMax.value += cn.count + en.count;
		return {
			...item,
			content: cn.html,
			contentEn: en.html,
		};
	});

	if (findWordMax.value > 0) {
		nextTick(() => {
			findWordNum.value = 1;
			updateActiveHighlight();
		});
	}
};

const handleUpdateWord = debounce(() => {
	doUpdateWord();
}, 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 = "";
			doUpdateWord();
			break;
	}
}

watch(
	() => props.reportData,
	(val) => {
		originReportData.value = (val || []).map((item) => ({
			content: item?.content || "",
			contentEn: item?.contentEn || "",
			num: item?.num,
		}));
		setDisplayFromOrigin();
		doUpdateWord();
	},
	{ deep: true, immediate: true },
);

watch(isTranslate, () => {
	doUpdateWord();
});
</script>

<style lang="scss" scoped>
.high-light {
	:deep(span.highlight) {
		background-color: #ffff00;
	}
}
.layout-container {
	width: 100%;
	height: 100%;
	background-color: #f7f8f9;

	.layout-main {
		height: 100%;
		display: flex;
		flex-direction: column;
		align-items: center;
		.header-main {
			padding: 17px 0;
			width: 100%;
			border-bottom: 1px solid rgba(234, 236, 238, 1);
			box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
			background: rgba(255, 255, 255, 1);
		}
		.layout-main-header {
			width: 1600px;
			display: flex;
			align-items: center;
			margin: 0 auto;

			.icon {
				width: 64px;
				height: 40px;
				overflow: hidden;

				img {
					width: 100%;
					height: 100%;
				}
			}

			.info {
				margin-left: 10px;
				margin-right: 40px;
				width: 20px;
				flex: auto;
				.info-box1 {
					width: 100%;
					color: rgba(59, 65, 75, 1);
					font-family: Microsoft YaHei;
					font-size: 20px;
					font-weight: 600;
					line-height: 22px;
					letter-spacing: 0px;
					text-align: left;
					margin-top: 5px;
				}

				.info-box2 {
					margin-top: 5px;
					height: 22px;
					line-height: 22px;
					color: rgba(132, 136, 142, 1);
					font-family: Microsoft YaHei;
					font-size: 14px;
					font-weight: 400;
					line-height: 22px;
					letter-spacing: 0px;
					text-align: left;
					display: flex;

					.info-box2-item {
						white-space: nowrap;
						padding: 0 10px;
					}
					.info-box2-item:first-child {
						padding-left: 0px;
					}
				}
			}

			.layout-main-header-right-box {
				.right-box-top {
					white-space: nowrap;
					.time {
						height: 24px;
						line-height: 24px;
						color: rgba(95, 101, 108, 1);
						font-family: Microsoft YaHei;
						font-size: 16px;
						font-weight: 400;
						line-height: 22px;
						letter-spacing: 0px;
						text-align: right;
					}

					.name {
						height: 24px;
						line-height: 24px;
						color: rgba(95, 101, 108, 1);
						font-family: Microsoft YaHei;
						font-size: 16px;
						font-weight: 400;
						line-height: 22px;
						letter-spacing: 0px;
						text-align: right;
					}
				}
			}
		}

		.layout-main-center {
			width: 1600px;
			background-color: white;
			padding: 0 60px;
			height: 20px;
			flex: auto;
			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 {
						width: 20px;
						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;
					width: 20px;
					flex: auto;
				}
				.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 {
				height: 20px;
				flex: auto;
				box-sizing: border-box;
				padding-top: 10px;

				&::-webkit-scrollbar {
					display: none;
				}

				&::-webkit-scrollbar-thumb {
					background: #c1c1c1;
					border-radius: 4px;
				}

				&::-webkit-scrollbar-track {
					background: #f1f1f1;
				}

				.noContent {
					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;

					&:last-child {
						border-bottom: none;
					}

					.content-en,
					.content-cn {
						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;
					}
					.translate-cn {
						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>
