<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" />
					<div class="switch-label switch-label-left">高亮实体</div>

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

					<div
						v-for="action in headerActions"
						:key="action.key"
						class="btn"
						@click="action.onClick"
					>
						<div :class="['icon', action.iconGapClass]">
							<img :src="action.icon" alt="" />
						</div>
						<div class="text">{{ action.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="no-content">暂无数据</div>
					<el-scrollbar v-else height="100%">
						<div
							v-for="item in displayReportData"
							:key="item.num"
							class="content-row"
							:class="{ 'high-light': isHighlight }"
						>
							<div class="content-cn" :class="{ 'translate-cn': !isTranslate }" v-html="item.content" />
							<div v-if="isTranslate" class="content-en" v-html="item.contentEn" />
						</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";

const props = defineProps({
	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([]);

const headerActions = [
	{
		key: "download",
		text: "下载",
		icon: defaultDownloadIcon,
		iconGapClass: "icon-gap-4",
		onClick: () => emits("download"),
	},
	{
		key: "search",
		text: "查找",
		icon: defaultSearchIcon,
		iconGapClass: "icon-gap-6",
		onClick: () => handleFindWord("open"),
	},
];

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

				.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-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>
