<template>
	<div class="wiki-manage">
		<!-- 索引视图 -->
		<el-scrollbar
			v-if="isIndexView"
			class="wiki-manage__scroll"
			v-loading="indexLoading || detailLoading"
		>
			<div class="wiki-index">
				<template v-if="renderedIndexContent">
					<div class="wiki-index__intro" @click="handleContentClick">
						<XMarkdown :markdown="renderedIndexContent" />
					</div>

					<div ref="catalogRef" class="wiki-index__sections">
						<section
							v-for="section in catalogSections"
							:key="section.key"
							class="wiki-index-section"
						>
							<h2 class="wiki-index-section__title">
								{{ section.label }} ({{ section.items.length }})
							</h2>

							<ul v-if="section.items.length" class="wiki-index-section__list">
								<li
									v-for="item in section.items"
									:key="item.id || item.slug"
									class="wiki-index-item"
								>
									<button
										type="button"
										class="wiki-index-item__link"
										@click="openWikiPage(item.slug)"
									>
										{{ item.title }}
									</button>
									<span v-if="getItemDescription(item)" class="wiki-index-item__text">
										{{ getItemDescription(item) }}
									</span>
								</li>
							</ul>
						</section>
					</div>
				</template>
				<template v-else>
					<el-empty description="暂无wiki内容" />
				</template>
			</div>
		</el-scrollbar>

		<!-- 详情视图 -->
		<el-scrollbar v-else class="wiki-manage__scroll" v-loading="indexLoading || detailLoading">
			<div class="wiki-detail">
				<div class="wiki-detail__header">
					<el-breadcrumb separator="/" class="wiki-detail__breadcrumb">
						<el-breadcrumb-item>
							<button type="button" class="wiki-detail__crumb" @click="backToIndex">索引</button>
						</el-breadcrumb-item>
						<el-breadcrumb-item v-for="(item, index) in pageTrail" :key="`${item.slug}-${index}`">
							<button
								type="button"
								class="wiki-detail__crumb"
								:disabled="index === pageTrail.length - 1"
								@click="handleBreadcrumbNavigate(index)"
							>
								{{ item.title }}
							</button>
						</el-breadcrumb-item>
					</el-breadcrumb>

					<div v-if="selectedPage" class="wiki-detail__meta">
						<span>{{ getPageTypeLabel(selectedPage.page_type) }}</span>
						<span>v{{ selectedPage.version }}</span>
					</div>
				</div>

				<template v-if="selectedPage">
					<!-- <h1 class="wiki-detail__title">{{ selectedPage.title }}</h1> -->
					<div class="wiki-detail__content" @click="handleContentClick">
						<XMarkdown :markdown="renderedSelectedPageContent" />
					</div>
				</template>
				<el-empty v-else description="页面加载失败" />
			</div>
		</el-scrollbar>
	</div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { XMarkdown } from 'vue-element-plus-x'
import { wiki } from '@repo/api-service'
import type { KnowledgeBaseItem } from './types'

type WikiPageType = 'summary' | 'entity' | 'concept' | 'index' | string

interface WikiPageItem {
	aliases?: string[]
	chunk_refs?: string[]
	content?: string
	creationTime?: string
	id: string
	in_links?: string[]
	knowledge_base_id?: string
	out_links?: string[]
	page_metadata?: Record<string, any>
	page_type: WikiPageType
	slug: string
	source_refs?: string[]
	status?: string
	summary?: string
	title: string
	updateTime?: string
	version: number
}

interface WikiIndexData {
	concept_pages: WikiPageItem[]
	entity_pages: WikiPageItem[]
	index: WikiPageItem
	summary_pages: WikiPageItem[]
}

const props = defineProps<{
	currentBase: KnowledgeBaseItem
}>()

const indexLoading = ref(false)
const detailLoading = ref(false)
const catalogRef = ref<HTMLDivElement>()

const wikiIndexData = ref<WikiIndexData | null>(null)
const selectedPage = ref<WikiPageItem | null>(null)
const pageTrail = ref<WikiPageItem[]>([])

const isIndexView = computed(() => !selectedPage.value)

const renderedIndexContent = computed(() =>
	transformWikiLinks(
		wikiIndexData.value?.index?.content || wikiIndexData.value?.index?.summary || ''
	)
)

const renderedSelectedPageContent = computed(() =>
	transformWikiLinks(selectedPage.value?.content || selectedPage.value?.summary || '暂无内容')
)

const catalogSections = computed(() => [
	{
		key: 'summary',
		label: '摘要',
		items: wikiIndexData.value?.summary_pages || []
	},
	{
		key: 'entity',
		label: '实体',
		items: wikiIndexData.value?.entity_pages || []
	},
	{
		key: 'concept',
		label: '概念',
		items: wikiIndexData.value?.concept_pages || []
	}
])

function transformWikiLinks(content: string) {
	return content.replace(/\[\[([^[\]|]+?)(?:\|([^[\]]+))?\]\]/g, (_match, rawSlug, rawLabel) => {
		const slug = `${rawSlug || ''}`.trim()
		const label = `${rawLabel || rawSlug || ''}`.trim()
		if (!slug || !label) return ''
		return `[${label}](wiki:${slug})`
	})
}

function stripMarkdown(content: string) {
	return content
		.replace(/\[\[([^[\]|]+?)(?:\|([^[\]]+))?\]\]/g, (_match, _slug, label) => label || '')
		.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1')
		.replace(/^#{1,6}\s+/gm, '')
		.replace(/\*\*([^*]+)\*\*/g, '$1')
		.replace(/\*([^*]+)\*/g, '$1')
		.replace(/`([^`]+)`/g, '$1')
		.replace(/^\s*[-+]\s+/gm, '')
		.replace(/\n+/g, ' ')
		.replace(/\s+/g, ' ')
		.trim()
}

function getItemDescription(item: WikiPageItem) {
	const rawText = stripMarkdown(item.summary || item.content || '')
	if (!rawText) return ''
	return `— ${rawText}`
}

function getPageTypeLabel(pageType: WikiPageType) {
	switch (pageType) {
		case 'summary':
			return '摘要'
		case 'entity':
			return '实体'
		case 'concept':
			return '概念'
		case 'index':
			return '索引'
		default:
			return pageType
	}
}

function normalizeIndexData(payload: any): WikiIndexData | null {
	if (!payload) return null

	if (payload.index) {
		return {
			index: payload.index,
			summary_pages: payload.summary_pages || [],
			entity_pages: payload.entity_pages || [],
			concept_pages: payload.concept_pages || []
		}
	}

	if (payload.page_type === 'index') {
		return {
			index: payload,
			summary_pages: [],
			entity_pages: [],
			concept_pages: []
		}
	}

	return null
}

function setSelectedPage(page: WikiPageItem, mode: 'reset' | 'push' | 'replace' = 'reset') {
	selectedPage.value = page

	if (mode === 'push') {
		const lastSlug = pageTrail.value[pageTrail.value.length - 1]?.slug
		pageTrail.value =
			lastSlug === page.slug ? [...pageTrail.value.slice(0, -1), page] : [...pageTrail.value, page]
		return
	}

	if (mode === 'replace') {
		pageTrail.value = pageTrail.value.length ? [...pageTrail.value.slice(0, -1), page] : [page]
		return
	}

	pageTrail.value = [page]
}

async function loadIndexPage() {
	if (!props.currentBase.id) return

	indexLoading.value = true
	try {
		const res = await wiki.postAiWikiIndex({ knowledge_base_id: props.currentBase.id })
		if (res?.isSuccess) {
			const normalizedData = normalizeIndexData(res.result)
			wikiIndexData.value = normalizedData
			selectedPage.value = null
			pageTrail.value = []
			if (normalizedData) {
				void hydrateIndexDescriptions(normalizedData, props.currentBase.id)
			}
		} else {
			// TODO: 错误处理
		}
	} finally {
		indexLoading.value = false
	}
}

async function fetchWikiPage(slug: string) {
	if (!props.currentBase.id || !slug) return null
	const res = await wiki.postAiWikiPage({
		knowledge_base_id: props.currentBase.id,
		slug
	})
	return res?.isSuccess ? (res.result as WikiPageItem) : null
}

async function openWikiPage(slug: string, mode: 'reset' | 'push' | 'replace' = 'reset') {
	if (!slug) return

	detailLoading.value = true
	try {
		const page = await fetchWikiPage(slug)
		if (page) {
			setSelectedPage(page, mode)
		}
	} finally {
		detailLoading.value = false
	}
}

async function hydrateIndexDescriptions(indexData: WikiIndexData, knowledgeBaseId: string) {
	const itemsNeedingDetails = [
		...indexData.summary_pages,
		...indexData.entity_pages,
		...indexData.concept_pages
	].filter((item) => item.slug && !item.summary && !item.content)

	if (!itemsNeedingDetails.length) return

	const detailResults = await Promise.all(
		itemsNeedingDetails.map(async (item) => {
			const page = await fetchWikiPage(item.slug)
			return [item.slug, page] as const
		})
	)

	if (!wikiIndexData.value || props.currentBase.id !== knowledgeBaseId) return

	const detailMap = new Map(
		detailResults
			.filter((entry): entry is readonly [string, WikiPageItem] => !!entry[0] && !!entry[1])
			.map(([slug, page]) => [slug, page])
	)

	const patchItems = (items: WikiPageItem[]) =>
		items.map((item) => {
			const detailPage = detailMap.get(item.slug)
			if (!detailPage) return item
			return {
				...item,
				summary: detailPage.summary || item.summary,
				content: detailPage.content || item.content
			}
		})

	wikiIndexData.value = {
		...wikiIndexData.value,
		summary_pages: patchItems(wikiIndexData.value.summary_pages),
		entity_pages: patchItems(wikiIndexData.value.entity_pages),
		concept_pages: patchItems(wikiIndexData.value.concept_pages)
	}
}

async function handleContentClick(event: MouseEvent) {
	const target = event.target as HTMLElement | null
	const anchor = target?.closest('a')
	const href = anchor?.getAttribute('href') || ''
	if (!href.startsWith('wiki:')) return

	event.preventDefault()
	const slug = href.slice(5).trim()
	if (!slug) return

	await openWikiPage(slug, selectedPage.value ? 'push' : 'reset')
}

function handleBreadcrumbNavigate(index: number) {
	const targetPage = pageTrail.value[index]
	if (!targetPage) return

	pageTrail.value = pageTrail.value.slice(0, index + 1)
	selectedPage.value = targetPage
}

function backToIndex() {
	selectedPage.value = null
	pageTrail.value = []
}

watch(
	() => props.currentBase.id,
	() => {
		wikiIndexData.value = null
		selectedPage.value = null
		pageTrail.value = []
		if (props.currentBase.id) {
			void loadIndexPage()
		}
	},
	{ immediate: true }
)
</script>

<style scoped lang="less">
.wiki-manage {
	position: absolute;
	inset: 0;
	width: 100%;
	max-width: 100%;
	height: 100%;
	min-height: 520px;
	border: 1px solid var(--border-light);
	border-radius: 10px;
	background: var(--bg-base);
	box-sizing: border-box;
}

.wiki-manage__scroll {
	height: 100%;
}

.wiki-manage__scroll :deep(.el-scrollbar__view) {
	min-height: 100%;
	width: 100%;
	max-width: 100%;
	padding: 18px 20px 24px;
	box-sizing: border-box;
}

.wiki-index,
.wiki-detail {
	width: 100%;
	max-width: 100%;
	min-width: 0;
	box-sizing: border-box;
}

.wiki-index__hero {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 8px;
	margin-bottom: 28px;
}

.wiki-index__title,
.wiki-detail__title {
	margin: 0;
	font-size: 26px;
	font-weight: 800;
	line-height: 1.2;
	color: var(--text-primary);
}

.wiki-index__catalog-btn,
.wiki-detail__crumb {
	padding: 0;
	border: 0;
	background: transparent;
	color: #0f766e;
	cursor: pointer;
}

.wiki-index__catalog-btn {
	padding: 4px 8px;
	border: 1px solid var(--border-base);
	border-radius: 6px;
	color: var(--text-primary);
	font-size: 13px;
}

.wiki-index__intro,
.wiki-detail__content {
	width: 100%;
	max-width: 100%;
	min-width: 0;
	overflow-x: hidden;
	color: var(--text-primary);
	font-size: 16px;
	line-height: 1.85;
	box-sizing: border-box;
}

.wiki-index__intro :deep(.markdown-body),
.wiki-detail__content :deep(.markdown-body) {
	width: 100%;
	max-width: 100%;
	min-width: 0;
	box-sizing: border-box;
}

.wiki-index__intro :deep(*),
.wiki-detail__content :deep(*) {
	max-width: 100%;
	box-sizing: border-box;
}

.wiki-index__sections {
	margin-top: 28px;
}

.wiki-index-section + .wiki-index-section {
	margin-top: 28px;
}

.wiki-index-section__title {
	margin: 0 0 16px;
	font-size: 18px;
	font-weight: 800;
	line-height: 1.35;
	color: var(--text-primary);
}

.wiki-index-section__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.wiki-index-item {
	font-size: 16px;
	line-height: 1.8;
	color: var(--text-primary);
}

.wiki-index-item__link {
	display: inline;
	padding: 0;
	border: 0;
	background: transparent;
	color: #0ea765;
	font-size: inherit;
	line-height: inherit;
	text-align: left;
	text-decoration: underline;
	text-decoration-style: dotted;
	text-underline-offset: 3px;
	cursor: pointer;
}

.wiki-index-item__text {
	color: var(--text-primary);
	white-space: pre-wrap;
}

.wiki-detail__header {
	display: flex;
	flex-direction: column;
	gap: 10px;
	margin-bottom: 18px;
}

.wiki-detail__breadcrumb {
	font-size: 13px;
}

.wiki-detail__crumb:disabled {
	color: var(--text-tertiary);
	cursor: default;
}

.wiki-detail__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	font-size: 12px;
	color: var(--text-tertiary);
}

.wiki-detail__meta span {
	padding: 4px 8px;
	border-radius: 999px;
	background: var(--bg-container);
}

.wiki-index__intro :deep(h1),
.wiki-index__intro :deep(h2),
.wiki-index__intro :deep(h3),
.wiki-detail__content :deep(h1),
.wiki-detail__content :deep(h2),
.wiki-detail__content :deep(h3) {
	margin: 0 0 18px;
	font-weight: 800;
	line-height: 1.3;
	color: var(--text-primary);
}

.wiki-index__intro :deep(h1),
.wiki-detail__content :deep(h1) {
	font-size: 26px;
}

.wiki-index__intro :deep(h2),
.wiki-detail__content :deep(h2) {
	margin-top: 30px;
	font-size: 18px;
}

.wiki-index__intro :deep(p),
.wiki-detail__content :deep(p) {
	margin: 0 0 14px;
	color: var(--text-primary);
	white-space: pre-wrap;
	overflow-wrap: anywhere;
	word-break: break-word;
}

.wiki-index__intro :deep(ul),
.wiki-index__intro :deep(ol),
.wiki-detail__content :deep(ul),
.wiki-detail__content :deep(ol) {
	margin: 0 0 16px 22px;
	padding: 0;
}

.wiki-index__intro :deep(li),
.wiki-detail__content :deep(li) {
	margin-bottom: 8px;
	color: var(--text-primary);
	overflow-wrap: anywhere;
	word-break: break-word;
}

.wiki-index__intro :deep(a),
.wiki-detail__content :deep(a) {
	color: #0ea765;
	text-decoration: underline;
	text-decoration-style: dotted;
	text-underline-offset: 3px;
	cursor: pointer;
	overflow-wrap: anywhere;
	word-break: break-word;
}

.wiki-index__intro :deep(strong),
.wiki-detail__content :deep(strong) {
	font-weight: 700;
}

.wiki-index__intro :deep(pre),
.wiki-detail__content :deep(pre),
.wiki-index__intro :deep(table),
.wiki-detail__content :deep(table) {
	max-width: 100%;
	overflow-x: auto;
	display: block;
}

.wiki-index__intro :deep(code),
.wiki-detail__content :deep(code) {
	white-space: pre-wrap;
	word-break: break-word;
}

.wiki-index__intro :deep(img),
.wiki-detail__content :deep(img) {
	max-width: 100%;
	height: auto;
}

@media (max-width: 960px) {
	.wiki-manage {
		height: auto;
		min-height: 0;
	}

	.wiki-manage__scroll :deep(.el-scrollbar__view) {
		padding: 16px;
	}

	.wiki-index__title,
	.wiki-detail__title,
	.wiki-index__intro :deep(h1),
	.wiki-detail__content :deep(h1) {
		font-size: 22px;
	}

	.wiki-index__intro,
	.wiki-detail__content,
	.wiki-index-item {
		font-size: 15px;
		line-height: 1.75;
	}
}
</style>
