<template>
	<el-drawer v-model="drawerVisible" title="操作日志" size="70%" direction="rtl" :close-on-click-modal="true" :modal="true" append-to-body>
		<div class="log-container" v-loading="loading" style="padding: 20px;">
			<div class="log-layout">
				<!-- 左侧时间线 -->
				<div class="timeline-panel">
					<el-scrollbar height="100%">
						<el-timeline>
							<el-timeline-item
								v-for="(log, index) in logList"
								:key="log.id"
								:type="getOperationTagType(log.operation)"
								:hollow="selectedLogIndex !== index"
								:timestamp="log.createdAt"
								placement="top"
								@click="selectLog(index)"
								:class="{ 'timeline-item-active': selectedLogIndex === index }"
							>
								<div class="timeline-content" @click="selectLog(index)">
									<div class="timeline-header">
										<el-tag size="small" :type="getOperationTagType(log.operation)">{{ getOperationLabel(log.operation) }}</el-tag>
									</div>
									<div class="timeline-info">
										<span class="creator">{{ log.creator }}</span>
									</div>
								</div>
							</el-timeline-item>
						</el-timeline>
						<!-- 加载更多 -->
						<div class="load-more" v-if="logList.length > 0 && logList.length < total">
							<el-button text type="primary" @click="loadMore" :loading="loadingMore">加载更多</el-button>
						</div>
						<el-empty v-if="!loading && logList.length === 0" description="暂无日志记录" />
					</el-scrollbar>
				</div>
				<!-- 右侧详情表格 -->
				<div class="detail-panel">
					<template v-if="selectedLog">
						<div class="detail-header">
							<el-tag :type="getOperationTagType(selectedLog.operation)">{{ getOperationLabel(selectedLog.operation) }}</el-tag>
							<span class="detail-time">{{ selectedLog.createdAt }}</span>
							<span class="detail-creator">操作人：{{ selectedLog.creator }}</span>
						</div>
						<el-table :data="selectedLogWithOldValue" border style="width: 100%" max-height="calc(100vh - 200px)">
							<el-table-column prop="FieldName" label="字段名" width="150" />
							<el-table-column prop="OldValue" label="原值" min-width="200">
								<template #default="scope">
									<span class="cell-value old-value">{{ formatFieldValue(scope.row.OldValue) }}</span>
								</template>
							</el-table-column>
							<el-table-column prop="NewValue" label="新值" min-width="200">
								<template #default="scope">
									<span class="cell-value new-value">{{ formatFieldValue(scope.row.NewValue) }}</span>
								</template>
							</el-table-column>
						</el-table>
						<el-empty v-if="selectedLogWithOldValue.length === 0" description="无变更内容" />
					</template>
					<el-empty v-else description="请选择左侧日志记录查看详情" />
				</div>
			</div>
		</div>
	</el-drawer>
</template>

<script setup lang="ts">
import { ref, reactive, computed } from 'vue';
import { listLogs, OperationLogInfo } from '/@/api/assets/asset';

const drawerVisible = ref(false);
const loading = ref(false);
const loadingMore = ref(false);
const logList = ref<OperationLogInfo[]>([]);
const total = ref(0);
const selectedLogIndex = ref<number | null>(null);

const queryParams = reactive({
	collection_id: '',
	pageNum: 1,
	pageSize: 20,
});

// 当前选中的日志
const selectedLog = computed(() => {
	if (selectedLogIndex.value !== null && logList.value[selectedLogIndex.value]) {
		return logList.value[selectedLogIndex.value];
	}
	return null;
});

// 获取下一条日志（更早的记录）中某字段的值作为原值
const getOldValue = (fieldName: string) => {
	if (selectedLogIndex.value === null) return null;
	// 日志按时间倒序，下一条是更早的记录
	const nextIndex = selectedLogIndex.value + 1;
	if (nextIndex >= logList.value.length) {
		// 没有更早的记录，返回 null
		return null;
	}
	const nextLog = logList.value[nextIndex];
	if (!nextLog.data) return null;
	const field = nextLog.data.find((item) => item.FieldName === fieldName);
	return field ? field.FieldValue : null;
};

// 带有原值的选中日志数据
const selectedLogWithOldValue = computed(() => {
	if (!selectedLog.value || !selectedLog.value.data) return [];
	return selectedLog.value.data.map((item) => ({
		FieldName: item.FieldName,
		OldValue: getOldValue(item.FieldName),
		NewValue: item.FieldValue,
	}));
});

// 打开抽屉
const openDialog = (collectionId: string) => {
	queryParams.collection_id = collectionId;
	queryParams.pageNum = 1;
	logList.value = [];
	selectedLogIndex.value = null;
	drawerVisible.value = true;
	fetchLogs();
};

// 获取日志列表
const fetchLogs = async () => {
	loading.value = true;
	try {
		const res: any = await listLogs(queryParams);
		if (res.code === 0 && res.data) {
			logList.value = res.data.logs || [];
			total.value = res.data.total || 0;
			// 默认选中第一条
			if (logList.value.length > 0) {
				selectedLogIndex.value = 0;
			}
		}
	} catch (error) {
		// 错误已由拦截器处理
	} finally {
		loading.value = false;
	}
};

// 加载更多
const loadMore = async () => {
	loadingMore.value = true;
	queryParams.pageNum++;
	try {
		const res: any = await listLogs(queryParams);
		if (res.code === 0 && res.data) {
			logList.value.push(...(res.data.logs || []));
			total.value = res.data.total || 0;
		}
	} catch (error) {
		queryParams.pageNum--;
	} finally {
		loadingMore.value = false;
	}
};

// 选择日志
const selectLog = (index: number) => {
	selectedLogIndex.value = index;
};

// 操作类型标签
const getOperationTagType = (operation: string) => {
	switch (operation) {
		case 'insert':
			return 'success';
		case 'update':
			return 'warning';
		case 'delete':
			return 'danger';
		default:
			return 'info';
	}
};

// 操作类型文本
const getOperationLabel = (operation: string) => {
	switch (operation) {
		case 'insert':
			return '新增';
		case 'update':
			return '修改';
		case 'delete':
			return '删除';
		default:
			return operation;
	}
};

// 格式化字段值
const formatFieldValue = (value: any) => {
	if (value === null || value === undefined) return '-';
	if (typeof value === 'boolean') return value ? '是' : '否';
	if (typeof value === 'object') return JSON.stringify(value);
	return String(value);
};

defineExpose({
	openDialog,
});
</script>

<style scoped lang="scss">
.log-container {
	height: calc(100vh - 120px);
	padding: 20px !important;
}
.log-layout {
	display: flex;
	height: 100%;
	gap: 24px;
}
.timeline-panel {
	width: 260px;
	flex-shrink: 0;
	border-right: 1px solid #ebeef5;
	padding-right: 16px;
	height: 100%;
	:deep(.el-timeline) {
		padding-top: 4px;
		padding-left: 4px;
	}
	:deep(.el-timeline-item) {
		cursor: pointer;
		padding-bottom: 16px;
		.el-timeline-item__timestamp {
			margin-bottom: 8px;
		}
		&.timeline-item-active {
			.el-timeline-item__node {
				transform: scale(1.3);
			}
			.timeline-content {
				background: #f0f9ff;
				border-color: #409eff;
			}
		}
	}
	.timeline-content {
		padding: 10px 12px;
		border-radius: 6px;
		border: 1px solid #ebeef5;
		transition: all 0.2s;
		&:hover {
			border-color: #c0c4cc;
			background: #fafafa;
		}
	}
	.timeline-header {
		margin-bottom: 6px;
	}
	.timeline-info {
		font-size: 12px;
		color: #909399;
		display: flex;
		justify-content: space-between;
		.creator {
			font-weight: 500;
			color: #606266;
		}
	}
	.load-more {
		text-align: center;
		padding: 10px 0;
	}
}
.detail-panel {
	flex: 1;
	overflow: hidden;
	padding-right: 10px;
	.detail-header {
		margin-bottom: 12px;
		padding-bottom: 12px;
		border-bottom: 1px solid #ebeef5;
		display: flex;
		align-items: center;
		gap: 16px;
		.detail-time {
			color: #909399;
			font-size: 14px;
		}
		.detail-creator {
			color: #606266;
			font-size: 14px;
		}
	}
	.cell-value {
		word-break: break-all;
		display: block;
		max-height: 100px;
		overflow-y: auto;
	}
	.old-value {
		color: #f56c6c;
	}
	.new-value {
		color: #67c23a;
	}
}
</style>
