<template>
	<div class="doc-parser-result">
		<!-- 统计摘要条 -->
		<div class="result-banner" v-if="fileResults.length > 0">
			<div class="banner-bg"></div>
			<div class="banner-content">
				<div class="banner-stat">
					<div class="banner-stat__value">{{ totalFiles }}</div>
					<div class="banner-stat__label">文件总数</div>
				</div>
				<div class="banner-divider"></div>
				<div class="banner-stat">
					<div class="banner-stat__value is-success">{{ successCount }}</div>
					<div class="banner-stat__label">
						<el-icon color="#52c41a" :size="12"><Check /></el-icon>
						解析成功
					</div>
				</div>
				<div class="banner-divider" v-if="failedCount > 0"></div>
				<div class="banner-stat" v-if="failedCount > 0">
					<div class="banner-stat__value is-danger">{{ failedCount }}</div>
					<div class="banner-stat__label">
						<el-icon color="#f56c6c" :size="12"><CloseBold /></el-icon>
						解析失败
					</div>
				</div>
			</div>
		</div>

		<!-- 文件卡片列表 -->
		<div class="file-cards">
			<div
				class="file-card"
				v-for="(file, idx) in fileResults"
				:key="idx"
				:class="{ 'is-failed': !file.success }"
				:style="{ '--card-delay': idx * 0.06 + 's' }"
			>
				<!-- 卡片头部 -->
				<div class="file-card__header">
					<div class="file-card__badge">{{ idx + 1 }}</div>
					<div class="file-card__meta">
						<div class="file-card__name" :title="file.fileName">{{ file.fileName }}</div>
						<div class="file-card__ext">{{ getFileExt(file.fileName) }}</div>
					</div>
					<el-tag
						:type="file.success ? 'success' : 'danger'"
						size="small"
						effect="dark"
						round
						class="file-card__status"
					>
						{{ file.success ? '识别完成' : '识别失败' }}
					</el-tag>
				</div>

				<!-- 失败提示 -->
				<div class="file-card__error" v-if="!file.success">
					<div class="error-box">
						<el-icon :size="20" color="#f56c6c"><WarningFilled /></el-icon>
						<span>{{ file.error || '文档解析失败，请检查文件格式是否支持' }}</span>
					</div>
				</div>

				<!-- 成功：图片 + OCR 对照 -->
				<div class="file-card__body" v-else>
					<!-- 左侧：原始图片 -->
					<div class="file-card__source" v-if="getImageUrl(file)">
						<div class="source-label">
							<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="m21 15-5-5L5 21"/></svg>
							原始文件
						</div>
						<div class="source-frame">
							<el-image
								:src="getImageUrl(file)"
								fit="contain"
								:preview-src-list="allImageUrls"
								:initial-index="getImageIndex(idx)"
								:z-index="3100"
								class="source-image"
							>
								<template #error>
									<div class="source-placeholder">
										<el-icon :size="36"><Picture /></el-icon>
										<span>图片加载失败</span>
									</div>
								</template>
								<template #placeholder>
									<div class="source-placeholder is-loading">
										<el-icon class="is-loading" :size="28"><Loading /></el-icon>
										<span>加载中...</span>
									</div>
								</template>
							</el-image>
							<div class="source-overlay">
								<el-icon :size="18"><ZoomIn /></el-icon>
								点击预览
							</div>
						</div>
					</div>

					<!-- 右侧：OCR 识别结果 -->
					<div class="file-card__ocr" :class="{ 'is-full': !getImageUrl(file) }">
						<div class="ocr-toolbar">
							<div class="ocr-toolbar__title">
								<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>
								OCR 识别结果
							</div>
							<el-button
								v-if="getFullMarkdown(file)"
								size="small"
								round
								class="copy-btn"
								@click="copyMarkdown(getFullMarkdown(file))"
							>
								<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
								复制文本
							</el-button>
						</div>
						<div class="ocr-body" v-if="getFullMarkdown(file)">
							<el-icon v-if="loadingFull" class="is-loading ocr-loading"><Loading /></el-icon>
							<cl-preview-md :content="getFullMarkdown(file)" />
						</div>
						<div class="ocr-empty" v-else>
							<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" opacity="0.3"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
							<span>无识别内容</span>
						</div>
					</div>
				</div>
			</div>
		</div>

		<!-- 空状态 -->
		<div class="empty-state" v-if="fileResults.length === 0">
			<svg width="56" height="56" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" opacity="0.25"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
			<span>暂无文档解析结果</span>
		</div>
	</div>
</template>

<script lang="ts" setup>
defineOptions({ name: 'doc-parser-result' });

import { computed, ref, watch } from 'vue';
import { Check, CloseBold, Picture, Loading, ZoomIn, WarningFilled } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { config } from '/@/config';

const props = defineProps<{
	result: any;
	taskId: string;
}>();

interface FileResult {
	success: boolean;
	fileName: string;
	markdown?: string;
	sourceFilePath?: string;
	error?: string;
}

/** 从 workspace 加载的完整 markdown（key = fileName） */
const fullMarkdownMap = ref<Record<string, string>>({});
const loadingFull = ref(false);

const fileResults = computed<FileResult[]>(() => {
	if (!props.result) return [];
	if (Array.isArray(props.result.results)) {
		return props.result.results;
	}
	if (props.result.fileName) {
		return [props.result];
	}
	return [];
});

/**
 * 获取文件的完整 markdown：优先用 workspace 加载的完整版，回退到 result 中的截断版
 */
function getFullMarkdown(file: FileResult): string {
	return fullMarkdownMap.value[file.fileName] || file.markdown || '';
}

/**
 * 从 workspace 加载每个文件的完整 OCR 结果（doc_results/{fileName}.json）
 */
async function loadFullResults() {
	if (!props.taskId || fileResults.value.length === 0) return;

	loadingFull.value = true;
	const successFiles = fileResults.value.filter(f => f.success);

	await Promise.all(successFiles.map(async (file) => {
		try {
			// 文件名做安全处理（与后端 writeJSON 一致）
			const safeFileName = (file.fileName || 'unknown')
				.replace(/[<>:"/\\|?*]/g, '_')
				.replace(/\s+/g, '_');
			const url = `${config.baseUrl}/open/netaclaw/workspace/file?taskId=${encodeURIComponent(props.taskId)}&path=${encodeURIComponent(`doc_results/${safeFileName}.json`)}`;
			const resp = await fetch(url);
			if (resp.ok) {
				const data = await resp.json();
				if (data?.markdown) {
					fullMarkdownMap.value[file.fileName] = data.markdown;
				}
			}
		} catch {
			// 加载失败静默忽略，回退到截断版
		}
	}));

	loadingFull.value = false;
}

// taskId 和 fileResults 就绪后自动加载完整结果
watch(
	() => [props.taskId, fileResults.value.length],
	() => {
		if (props.taskId && fileResults.value.length > 0) {
			loadFullResults();
		}
	},
	{ immediate: true }
);

const totalFiles = computed(() => props.result?.totalFiles || fileResults.value.length);
const successCount = computed(() => props.result?.successCount || fileResults.value.filter(f => f.success).length);
const failedCount = computed(() => props.result?.failedCount || fileResults.value.filter(f => !f.success).length);

/** 所有成功文件的图片URL列表（用于预览轮播） */
const allImageUrls = computed(() => {
	return fileResults.value
		.filter(f => f.success && f.sourceFilePath)
		.map(f => getImageUrl(f));
});

function getImageUrl(file: FileResult): string {
	if (!file.sourceFilePath || !props.taskId) return '';
	return `${config.baseUrl}/open/netaclaw/workspace/file?taskId=${encodeURIComponent(props.taskId)}&path=${encodeURIComponent(file.sourceFilePath)}`;
}

function getImageIndex(cardIdx: number): number {
	// 在 allImageUrls 中找到当前卡片对应的索引
	let imgIdx = 0;
	for (let i = 0; i < cardIdx; i++) {
		if (fileResults.value[i]?.success && fileResults.value[i]?.sourceFilePath) {
			imgIdx++;
		}
	}
	return imgIdx;
}

function getFileExt(name: string): string {
	const ext = name.split('.').pop()?.toUpperCase() || '';
	return ext ? `.${ext}` : '';
}

function copyMarkdown(text: string) {
	navigator.clipboard.writeText(text).then(() => {
		ElMessage({ message: '已复制到剪贴板', type: 'success', duration: 1500 });
	}).catch(() => {
		ElMessage.error('复制失败');
	});
}
</script>

<style lang="scss" scoped>
/* ── 变量 ── */
$radius-lg: 14px;
$radius-md: 10px;
$radius-sm: 6px;
$shadow-card: 0 1px 3px rgba(0, 0, 0, 0.04), 0 4px 16px rgba(0, 0, 0, 0.03);
$shadow-card-hover: 0 4px 20px rgba(0, 0, 0, 0.08);
$accent: #4f6ef7;
$accent-light: #eef1fe;
$success: #52c41a;
$danger: #f56c6c;

/* ── 统计条 ── */
.result-banner {
	position: relative;
	border-radius: $radius-lg;
	overflow: hidden;
	margin-bottom: 20px;

	.banner-bg {
		position: absolute;
		inset: 0;
		background: linear-gradient(135deg, #f0f4ff 0%, #e8ecfa 50%, #f5f0ff 100%);
		opacity: 0.85;
	}

	.banner-content {
		position: relative;
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 28px;
		padding: 18px 32px;
	}

	.banner-divider {
		width: 1px;
		height: 32px;
		background: rgba(0, 0, 0, 0.08);
	}

	.banner-stat {
		text-align: center;
		min-width: 72px;

		&__value {
			font-size: 28px;
			font-weight: 700;
			line-height: 1.1;
			color: var(--el-text-color-primary);
			font-variant-numeric: tabular-nums;
			letter-spacing: -0.5px;

			&.is-success { color: $success; }
			&.is-danger { color: $danger; }
		}

		&__label {
			display: flex;
			align-items: center;
			justify-content: center;
			gap: 4px;
			margin-top: 4px;
			font-size: 12px;
			color: var(--el-text-color-secondary);
			letter-spacing: 0.3px;
		}
	}
}

/* ── 文件卡片列表 ── */
.file-cards {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.file-card {
	border-radius: $radius-lg;
	background: var(--el-bg-color);
	border: 1px solid var(--el-border-color-extra-light);
	box-shadow: $shadow-card;
	overflow: hidden;
	animation: card-in 0.35s ease-out both;
	animation-delay: var(--card-delay, 0s);
	transition: box-shadow 0.25s, border-color 0.25s;

	&:hover {
		box-shadow: $shadow-card-hover;
		border-color: var(--el-border-color-lighter);
	}

	&.is-failed {
		border-color: rgba($danger, 0.25);
		.file-card__header { background: rgba($danger, 0.03); }
	}

	/* ── 头部 ── */
	&__header {
		display: flex;
		align-items: center;
		gap: 10px;
		padding: 10px 16px;
		background: var(--el-fill-color-lighter);
		border-bottom: 1px solid var(--el-border-color-extra-light);
	}

	&__badge {
		width: 22px;
		height: 22px;
		border-radius: 6px;
		background: $accent;
		color: #fff;
		display: flex;
		align-items: center;
		justify-content: center;
		font-size: 11px;
		font-weight: 700;
		flex-shrink: 0;
		letter-spacing: -0.3px;
	}

	&__meta {
		flex: 1;
		min-width: 0;
		display: flex;
		align-items: baseline;
		gap: 6px;
	}

	&__name {
		font-weight: 600;
		font-size: 13px;
		color: var(--el-text-color-primary);
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	&__ext {
		font-size: 11px;
		color: var(--el-text-color-placeholder);
		flex-shrink: 0;
		font-weight: 500;
	}

	&__status {
		flex-shrink: 0;
	}

	/* ── 失败 ── */
	&__error {
		padding: 20px;

		.error-box {
			display: flex;
			align-items: center;
			gap: 10px;
			padding: 14px 18px;
			background: rgba($danger, 0.04);
			border: 1px solid rgba($danger, 0.12);
			border-radius: $radius-md;
			font-size: 13px;
			color: var(--el-text-color-regular);
			line-height: 1.5;
		}
	}

	/* ── 内容区 ── */
	&__body {
		display: flex;
		min-height: 220px;
	}

	/* ── 左侧图片 ── */
	&__source {
		width: 38%;
		max-width: 380px;
		flex-shrink: 0;
		display: flex;
		flex-direction: column;
		border-right: 1px solid var(--el-border-color-extra-light);
		background: #fafbfc;

		.source-label {
			display: flex;
			align-items: center;
			gap: 6px;
			padding: 8px 14px;
			font-size: 11px;
			font-weight: 600;
			color: var(--el-text-color-placeholder);
			text-transform: uppercase;
			letter-spacing: 0.8px;
			border-bottom: 1px solid var(--el-border-color-extra-light);

			svg { opacity: 0.5; }
		}

		.source-frame {
			flex: 1;
			position: relative;
			display: flex;
			align-items: center;
			justify-content: center;
			padding: 14px;
			cursor: pointer;

			&:hover .source-overlay {
				opacity: 1;
			}
		}

		.source-image {
			max-width: 100%;
			max-height: 420px;
			border-radius: $radius-sm;
			overflow: hidden;

			:deep(img) {
				max-height: 420px;
				object-fit: contain;
				transition: transform 0.3s;
			}

			&:hover :deep(img) {
				transform: scale(1.01);
			}
		}

		.source-overlay {
			position: absolute;
			bottom: 20px;
			left: 50%;
			transform: translateX(-50%);
			display: flex;
			align-items: center;
			gap: 4px;
			padding: 5px 12px;
			background: rgba(0, 0, 0, 0.55);
			backdrop-filter: blur(6px);
			color: #fff;
			font-size: 11px;
			border-radius: 20px;
			opacity: 0;
			transition: opacity 0.25s;
			pointer-events: none;
		}

		.source-placeholder {
			display: flex;
			flex-direction: column;
			align-items: center;
			gap: 8px;
			padding: 40px 0;
			color: var(--el-text-color-placeholder);
			font-size: 12px;

			&.is-loading {
				color: $accent;
			}
		}
	}

	/* ── 右侧 OCR ── */
	&__ocr {
		flex: 1;
		min-width: 0;
		display: flex;
		flex-direction: column;

		&.is-full {
			border-left: none;
		}

		.ocr-toolbar {
			display: flex;
			align-items: center;
			justify-content: space-between;
			padding: 8px 14px;
			border-bottom: 1px solid var(--el-border-color-extra-light);
			background: var(--el-fill-color-lighter);

			&__title {
				display: flex;
				align-items: center;
				gap: 6px;
				font-size: 11px;
				font-weight: 600;
				color: var(--el-text-color-placeholder);
				text-transform: uppercase;
				letter-spacing: 0.8px;

				svg { opacity: 0.5; }
			}
		}

		.copy-btn {
			font-size: 12px;
			padding: 4px 12px;
			height: 26px;
			display: flex;
			align-items: center;
			gap: 4px;
			color: var(--el-text-color-secondary);
			border-color: var(--el-border-color-lighter);

			&:hover {
				color: $accent;
				border-color: $accent;
			}

			svg { flex-shrink: 0; }
		}

		.ocr-body {
			flex: 1;
			padding: 16px 18px;
			overflow-y: auto;
			max-height: 480px;
			font-size: 14px;
			line-height: 1.85;
			color: var(--el-text-color-regular);
			position: relative;

			.ocr-loading {
				position: absolute;
				top: 8px;
				right: 12px;
				color: $accent;
				font-size: 16px;
			}

			/* 表格样式 */
			:deep(table) {
				width: 100%;
				border-collapse: collapse;
				margin: 10px 0;
				font-size: 13px;

				th, td {
					border: 1px solid var(--el-border-color-lighter);
					padding: 7px 12px;
					text-align: left;
				}

				th {
					background: var(--el-fill-color-lighter);
					font-weight: 600;
					font-size: 12px;
					color: var(--el-text-color-secondary);
				}

				tr:hover td {
					background: var(--el-fill-color-blank);
				}
			}

			/* 段落间距 */
			:deep(p) {
				margin: 0.5em 0;
			}

			/* 代码块 */
			:deep(pre) {
				background: var(--el-fill-color);
				border-radius: $radius-sm;
				padding: 10px 14px;
				font-size: 12px;
				overflow-x: auto;
			}
		}

		.ocr-empty {
			flex: 1;
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;
			gap: 10px;
			padding: 40px 0;
			color: var(--el-text-color-placeholder);
			font-size: 13px;
		}
	}
}

/* ── 空状态 ── */
.empty-state {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 12px;
	padding: 60px 0;
	color: var(--el-text-color-placeholder);
	font-size: 13px;
}

/* ── 动画 ── */
@keyframes card-in {
	from {
		opacity: 0;
		transform: translateY(10px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}
</style>
