<template>
	<div class="management-container">
		<div class="page-header">
			<div class="header-copy">
				<h1>智能体管理</h1>
			</div>
		</div>

		<div class="stats-grid">
			<div class="stat-card">
				<div class="stat-icon coral">
					<SvgIcon name="platForm" size="20" />
				</div>
				<div>
					<div class="stat-value">{{ pageData.totalCount }}</div>
					<div class="stat-label">智能体总数</div>
				</div>
			</div>
			<div class="stat-card">
				<div class="stat-icon blue">
					<SvgIcon name="workflow" size="20" />
				</div>
				<div>
					<div class="stat-value">{{ agents.length }}</div>
					<div class="stat-label">当前页数量</div>
				</div>
			</div>
			<div class="stat-card">
				<div class="stat-icon green">
					<SvgIcon name="service" size="20" />
				</div>
				<div>
					<div class="stat-value">{{ totalConversationVariables }}</div>
					<div class="stat-label">会话变量数</div>
				</div>
			</div>
			<div class="stat-card">
				<div class="stat-icon orange">
					<SvgIcon name="setting" size="20" />
				</div>
				<div>
					<div class="stat-value">{{ totalEnvVariables }}</div>
					<div class="stat-label">环境变量数</div>
				</div>
			</div>
		</div>

		<div class="panel">
			<div class="toolbar">
				<el-input
					v-model="keyword"
					placeholder="搜索当前页的智能体名称或 ID"
					clearable
					class="search-input"
				>
					<template #prefix>
						<el-icon><Search /></el-icon>
					</template>
				</el-input>

				<div class="toolbar-meta">
					<el-button type="primary" link :loading="loading" @click="loadAgents(pageIndex)">
						<el-icon><RefreshRight /></el-icon>
					</el-button>

					<span class="meta-pill"
						>第 {{ pageData.currentPage || 1 }} / {{ pageData.totalPages || 1 }} 页</span
					>
					<span class="meta-pill">{{ pageData.pageSize }} 条/页</span>
				</div>
			</div>

			<div v-loading="loading" class="card-grid">
				<div
					v-for="row in filteredAgents"
					:key="row.id"
					class="agent-card"
					@click="handleRowClick(row)"
				>
					<div class="cover">
						<img
							v-if="row.profilePhoto"
							:src="row.profilePhoto"
							:alt="row.name"
							class="cover-image"
						/>
						<div v-else class="cover-fallback">
							<div class="fallback-monogram">{{ row.name?.slice(0, 1) || 'A' }}</div>
						</div>

						<div class="cover-gradient"></div>

						<div class="cover-top">
							<span class="cover-badge">智能体</span>
							<span class="cover-badge subtle">{{ row.env_variables.length }} 个环境变量</span>
						</div>
					</div>

					<div class="cover-bottom">
						<el-avatar :size="56" :src="row.profilePhoto || undefined" class="cover-avatar">
							{{ row.name?.slice(0, 1) || 'A' }}
						</el-avatar>
					</div>

					<div class="card-body">
						<div class="card-head">
							<div class="card-title-wrap">
								<div class="agent-name" :title="row.name || fallbackText.unnamed">
									{{ row.name || fallbackText.unnamed }}
								</div>
								<div class="agent-id" :title="row.id">{{ row.id }}</div>
							</div>
						</div>

						<div class="card-footer">
							<el-button type="primary" @click.stop="openAgent(row.id)">打开</el-button>
						</div>
					</div>
				</div>

				<el-empty
					v-if="!filteredAgents.length && !loading"
					:description="keyword ? emptyText.filtered : emptyText.default"
					class="empty-state"
				/>
			</div>

			<div class="pagination">
				<el-pagination
					background
					layout="prev, pager, next, total"
					:current-page="pageIndex"
					:page-size="pageData.pageSize || 10"
					:total="pageData.totalCount"
					@current-change="handlePageChange"
				/>
			</div>
		</div>
	</div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { RefreshRight, Search } from '@element-plus/icons-vue'
import { agent } from '@repo/api-service'

import SvgIcon from '@/components/SvgIcon/index.vue'

type AgentListResponse = Awaited<ReturnType<typeof agent.postAgentGetAgentList>>
type AgentListResult = NonNullable<AgentListResponse['result']>
type AgentListItem = AgentListResult['model'][number]

const createEmptyPageData = (): AgentListResult => ({
	currentPage: 1,
	hasNextPage: false,
	hasPreviousPage: false,
	model: [],
	pageSize: 10,
	totalCount: 0,
	totalPages: 0
})

const fallbackText = {
	unnamed: '未命名智能体',
	notConfiguredConversation: '未配置会话变量',
	notConfiguredEnv: '未配置环境变量'
} as const

const emptyText = {
	default: '暂无智能体数据',
	filtered: '当前筛选条件下暂无数据'
} as const

const separator = '、'

const router = useRouter()
const loading = ref(false)
const keyword = ref('')
const pageIndex = ref(1)
const pageData = ref<AgentListResult>(createEmptyPageData())

const agents = computed(() => pageData.value.model)

const filteredAgents = computed(() => {
	const searchValue = keyword.value.trim().toLowerCase()

	if (!searchValue) {
		return agents.value
	}

	return agents.value.filter((item) => {
		const name = item.name.toLowerCase()
		const id = item.id.toLowerCase()
		return name.includes(searchValue) || id.includes(searchValue)
	})
})

const totalConversationVariables = computed(() =>
	agents.value.reduce((total, item) => total + item.conversation_variables.length, 0)
)

const totalEnvVariables = computed(() =>
	agents.value.reduce((total, item) => total + item.env_variables.length, 0)
)

const formatConversationVariables = (variables: AgentListItem['conversation_variables']) => {
	if (!variables.length) {
		return fallbackText.notConfiguredConversation
	}

	return variables.slice(0, 4).join(separator) + (variables.length > 4 ? '...' : '')
}

const formatEnvVariables = (variables: AgentListItem['env_variables']) => {
	if (!variables.length) {
		return fallbackText.notConfiguredEnv
	}

	const labels = variables.slice(0, 3).map((item) => item.name || item.type)
	return labels.join(separator) + (variables.length > 3 ? '...' : '')
}

const openAgent = (id: string) => {
	router.push(`/workflow/${id}`)
}

const handleRowClick = (row: AgentListItem) => {
	openAgent(row.id)
}

const loadAgents = async (targetPage = 1) => {
	loading.value = true

	try {
		const response = await agent.postAgentGetAgentList({
			pageIndex: targetPage
		})

		if (!response.isSuccess || !response.result) {
			throw new Error('获取智能体列表失败')
		}

		pageData.value = response.result
		pageIndex.value = response.result.currentPage || targetPage
	} catch (error) {
		console.error('loadAgents error', error)
		ElMessage.error('加载智能体列表失败')
		pageData.value = createEmptyPageData()
	} finally {
		loading.value = false
	}
}

const handlePageChange = (nextPage: number) => {
	pageIndex.value = nextPage
	loadAgents(nextPage)
}

onMounted(() => {
	loadAgents(pageIndex.value)
})
</script>

<style lang="less" scoped>
.management-container {
	max-width: 1320px;
	margin: 0 auto;
	padding: 28px 24px 32px;
}

.page-header {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 20px;
	margin-bottom: 24px;
}

.header-copy {
	h1 {
		margin: 6px 0 8px;
		font-size: 30px;
		line-height: 1.1;
		color: var(--text-primary);
	}

	p {
		margin: 0;
		max-width: 720px;
		font-size: 14px;
		line-height: 1.7;
		color: var(--text-secondary);
	}
}

.eyebrow {
	display: inline-flex;
	align-items: center;
	padding: 6px 10px;
	border-radius: 999px;
	background: rgba(255, 107, 107, 0.1);
	color: var(--el-color-primary);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.stats-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: 16px;
	margin-bottom: 22px;
}

.stat-card {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 18px;
	border: 1px solid var(--border-light);
	border-radius: 18px;
	background:
		linear-gradient(180deg, rgba(255, 255, 255, 0.9), rgba(245, 247, 250, 0.8)), var(--bg-base);
	box-shadow: 0 14px 32px rgba(15, 23, 42, 0.05);
}

.stat-icon {
	width: 46px;
	height: 46px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 14px;

	&.coral {
		background: #fff1f0;
		color: #ff6b6b;
	}

	&.blue {
		background: #eef4ff;
		color: #3b82f6;
	}

	&.green {
		background: #ecfdf3;
		color: #10b981;
	}

	&.orange {
		background: #fff7ed;
		color: #f97316;
	}
}

.stat-value {
	font-size: 24px;
	font-weight: 700;
	color: var(--text-primary);
}

.stat-label {
	margin-top: 2px;
	font-size: 13px;
	color: var(--text-secondary);
}

.panel {
	padding: 22px;
	border: 1px solid var(--border-light);
	border-radius: 22px;
	background: var(--bg-base);
	box-shadow: 0 18px 42px rgba(15, 23, 42, 0.06);
}

.toolbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: 20px;
}

.search-input {
	max-width: 340px;
}

.toolbar-meta {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px;
}

.meta-pill {
	display: inline-flex;
	align-items: center;
	padding: 8px 12px;
	border: 1px solid var(--border-light);
	border-radius: 999px;
	background: var(--bg-container);
	font-size: 12px;
	color: var(--text-secondary);
}

.card-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
	gap: 20px;
	min-height: 240px;
}

.agent-card {
	display: flex;
	flex-direction: column;
	min-height: 100%;
	overflow: hidden;
	border: 1px solid var(--border-light);
	border-radius: 22px;
	background: var(--bg-base);
	box-shadow: 0 14px 32px rgba(15, 23, 42, 0.06);
	cursor: pointer;
	position: relative;
	transition:
		transform 0.18s ease,
		box-shadow 0.18s ease,
		border-color 0.18s ease;

	&:hover {
		transform: translateY(-6px);
		border-color: rgba(255, 107, 107, 0.24);
		box-shadow: 0 20px 46px rgba(15, 23, 42, 0.1);
	}
}

.cover {
	position: relative;
	height: 188px;
	overflow: hidden;
	background:
		radial-gradient(circle at top left, rgba(255, 107, 107, 0.28), transparent 38%),
		radial-gradient(circle at right bottom, rgba(59, 130, 246, 0.24), transparent 34%),
		linear-gradient(135deg, #f8fafc, #eef2ff);
}

.cover-image,
.cover-fallback {
	width: 100%;
	height: 100%;
}

.cover-image {
	display: block;
	object-fit: cover;
}

.cover-fallback {
	display: flex;
	align-items: center;
	justify-content: center;
}

.fallback-monogram {
	width: 84px;
	height: 84px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 24px;
	background: rgba(255, 255, 255, 0.7);
	backdrop-filter: blur(10px);
	font-size: 38px;
	font-weight: 800;
	color: #ff6b6b;
}

.cover-gradient {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(10, 10, 10, 0.02), rgba(10, 10, 10, 0.5));
}

.cover-top {
	position: absolute;
	top: 14px;
	left: 14px;
	right: 14px;
	display: flex;
	justify-content: space-between;
	gap: 8px;
}

.cover-badge {
	display: inline-flex;
	align-items: center;
	padding: 6px 10px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.92);
	color: #1f2937;
	font-size: 12px;
	font-weight: 600;
	backdrop-filter: blur(10px);

	&.subtle {
		background: rgba(15, 23, 42, 0.58);
		color: #fff;
	}
}

.cover-bottom {
	position: absolute;
	left: 18px;
	top: 160px;
}

.cover-avatar {
	border: 4px solid var(--bg-base);
	box-shadow: 0 10px 24px rgba(15, 23, 42, 0.12);
}

.card-body {
	display: flex;
	flex: 1;
	flex-direction: column;
	padding: 40px 18px 18px;
}

.card-head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
}

.card-title-wrap {
	min-width: 0;
}

.agent-name {
	overflow: hidden;
	font-size: 18px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--text-primary);
	text-overflow: ellipsis;
	white-space: nowrap;
}

.agent-id {
	margin-top: 6px;
	overflow: hidden;
	font-size: 12px;
	color: var(--text-secondary);
	text-overflow: ellipsis;
	white-space: nowrap;
}

.enter-link {
	padding-right: 0;
	padding-left: 0;
}

.metric-row {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 10px;
	margin-top: 18px;
}

.metric-card {
	padding: 12px 14px;
	border: 1px solid var(--border-light);
	border-radius: 16px;
	background: var(--bg-container);
}

.metric-label {
	font-size: 12px;
	color: var(--text-tertiary);
}

.metric-value {
	margin-top: 6px;
	font-size: 20px;
	font-weight: 700;
	line-height: 1;
	color: var(--text-primary);
}

.detail-panel {
	display: grid;
	gap: 12px;
	margin-top: 16px;
	padding: 14px;
	border-radius: 18px;
	background: linear-gradient(180deg, var(--bg-container), rgba(245, 247, 250, 0.4));
}

.detail-item {
	padding-bottom: 12px;
	border-bottom: 1px solid var(--border-light);

	&:last-child {
		padding-bottom: 0;
		border-bottom: 0;
	}
}

.detail-label {
	font-size: 12px;
	color: var(--text-tertiary);
}

.detail-value {
	margin-top: 6px;
	font-size: 13px;
	line-height: 1.65;
	color: var(--text-secondary);
	word-break: break-word;
}

.card-footer {
	display: flex;
	justify-content: flex-end;
	margin-top: auto;
	padding-top: 18px;
}

.empty-state {
	grid-column: 1 / -1;
	padding: 30px 0 18px;
}

.pagination {
	display: flex;
	justify-content: flex-end;
	margin-top: 20px;
}

@media (max-width: 960px) {
	.page-header,
	.toolbar {
		flex-direction: column;
		align-items: stretch;
	}

	.search-input {
		max-width: none;
	}

	.toolbar-meta,
	.pagination {
		justify-content: flex-start;
	}
}

@media (max-width: 640px) {
	.management-container {
		padding: 18px 14px 24px;
	}

	.panel {
		padding: 16px;
		border-radius: 18px;
	}

	.card-grid {
		grid-template-columns: 1fr;
	}

	.cover {
		height: 172px;
	}

	.card-head {
		flex-direction: column;
	}

	.enter-link,
	.card-footer :deep(.el-button) {
		width: 100%;
	}
}
</style>
