<template>
	<div class="agent-list">
		<!-- 顶部工具栏 -->
		<div class="agent-list__header">
			<div class="header-stats">
				<div class="stat-chip">
					<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="12" height="12" rx="3"/><circle cx="6" cy="7" r="1.5" fill="currentColor" stroke="none"/><circle cx="10" cy="7" r="1.5" fill="currentColor" stroke="none"/><path d="M5.5 10.5c0 0 1 1.5 2.5 1.5s2.5-1.5 2.5-1.5"/></svg>
					<span class="stat-num">{{ agents.length }}</span>
					<span class="stat-label">个 Agent</span>
				</div>
				<div class="stat-chip is-live">
					<span class="live-dot"></span>
					<span class="stat-num">{{ agents.filter(a => a.status === 1).length }}</span>
					<span class="stat-label">已发布</span>
				</div>
			</div>
			<div class="header-actions">
				<button class="icon-btn" @click="loadAgents" title="刷新">
					<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 8a6 6 0 0 1 10.3-4.1M14 8a6 6 0 0 1-10.3 4.1"/><polyline points="2 3 2 7 6 7"/><polyline points="14 13 14 9 10 9"/></svg>
				</button>
				<el-input
					v-model="searchText"
					placeholder="搜索 Agent..."
					clearable
					class="search-input"
				>
					<template #prefix>
						<el-icon><Search /></el-icon>
					</template>
				</el-input>
				<button class="create-btn" @click="handleCreate">
					<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="3" x2="8" y2="13"/><line x1="3" y1="8" x2="13" y2="8"/></svg>
					新建 Agent
				</button>
			</div>
		</div>

		<!-- 卡片网格 -->
		<el-scrollbar class="agent-list__content">
			<div class="agent-grid" v-if="filteredAgents.length > 0">
				<div
					class="agent-card"
					v-for="(item, idx) in filteredAgents"
					:key="item.id"
					:class="{ 'is-published': item.status === 1 }"
					:style="{ '--stagger': idx }"
				>
					<!-- 顶部高光条 -->
					<div class="agent-card__glow"></div>

					<!-- 卡片头部 -->
					<div class="agent-card__header">
						<div class="agent-card__icon">
							<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="18" height="18" rx="4"/><circle cx="9" cy="10" r="2" fill="currentColor" stroke="none"/><circle cx="15" cy="10" r="2" fill="currentColor" stroke="none"/><path d="M8 15c0 0 1.5 2 4 2s4-2 4-2"/></svg>
						</div>
						<div class="agent-card__title">
							<p class="name">{{ item.label || item.name }}</p>
							<div class="agent-card__tags">
								<span class="status-badge" :class="item.status === 1 ? 'is-live' : 'is-draft'">
									<span class="status-dot"></span>
									{{ item.status === 1 ? '已发布' : '草稿' }}
								</span>
								<span class="skill-count" v-if="getSkills(item).length > 0">
									{{ getSkills(item).length }} Skills
								</span>
							</div>
						</div>
					</div>

					<!-- 描述 -->
					<p class="agent-card__desc">{{ item.description || '暂无描述' }}</p>

					<!-- API 信息，仅已发布时显示 -->
					<div class="agent-card__api" v-if="item.status === 1">
						<code>POST /open/agent/run/invoke</code>
						<button class="copy-btn" @click.stop="copyApiInfo(item)" title="复制">
							<svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="5" y="5" width="9" height="9" rx="1.5"/><path d="M5 11H3.5A1.5 1.5 0 0 1 2 9.5V3.5A1.5 1.5 0 0 1 3.5 2h6A1.5 1.5 0 0 1 11 3.5V5"/></svg>
						</button>
					</div>

					<!-- 底部操作 -->
					<div class="agent-card__footer">
						<el-switch
							:model-value="item.status === 1"
							size="small"
							@change="handleToggleStatus(item)"
						/>
						<div class="agent-card__actions">
							<button class="action-link" @click="handleEdit(item)">编辑</button>
							<button class="action-link" :disabled="item.status !== 1" @click="handleTest(item)">测试</button>
							<el-popconfirm
								title="确定删除这个 Agent 吗？"
								@confirm="handleDelete(item)"
							>
								<template #reference>
									<button class="action-link is-danger" @click.stop>删除</button>
								</template>
							</el-popconfirm>
						</div>
					</div>
				</div>
			</div>

			<!-- 空状态 -->
			<div class="empty-state" v-if="!loading && filteredAgents.length === 0">
				<svg viewBox="0 0 64 64" width="56" height="56" fill="none" stroke="currentColor" stroke-width="1.2" opacity="0.25">
					<rect x="12" y="8" width="40" height="48" rx="6"/>
					<circle cx="26" cy="26" r="4"/><circle cx="38" cy="26" r="4"/>
					<path d="M22 38c0 0 3 4 10 4s10-4 10-4"/>
				</svg>
				<p>暂无 Agent</p>
				<span>点击右上角“新建 Agent”开始创建</span>
			</div>
		</el-scrollbar>

		<!-- 编辑抽屉 -->
		<agent-edit
			v-model:visible="editVisible"
			:agent-id="editAgentId"
			@saved="loadAgents"
		/>
	</div>
</template>

<script lang="ts" setup>
defineOptions({ name: 'agent-list' });

import { ref, computed, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { Search } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { useBase } from '/$/base';
import { config } from '/@/config';
import type { AgentInfo } from '../types/index.d';
import AgentEdit from './agent-edit.vue';

const router = useRouter();
const { user } = useBase();

const searchText = ref('');
const loading = ref(false);
const agents = ref<AgentInfo[]>([]);
const editVisible = ref(false);
const editAgentId = ref<number | null>(null);

const filteredAgents = computed(() => {
	if (!searchText.value) return agents.value;
	const s = searchText.value.toLowerCase();
	return agents.value.filter(
		(a) =>
			a.name?.toLowerCase().includes(s) ||
			a.label?.toLowerCase().includes(s) ||
			a.description?.toLowerCase().includes(s)
	);
});

// 安全获取 skills 数组，后端可能返回 JSON 字符串或数组
function getSkills(agent: AgentInfo): string[] {
	if (!agent.skills) return [];
	if (Array.isArray(agent.skills)) return agent.skills;
	if (typeof agent.skills === 'string') {
		try {
			const parsed = JSON.parse(agent.skills);
			return Array.isArray(parsed) ? parsed : [];
		} catch {
			return [];
		}
	}
	return [];
}

// 加载 Agent 列表
async function loadAgents() {
	loading.value = true;
	try {
		const resp = await fetch(`${config.baseUrl}/admin/netaclaw/agent/page`, {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
				Authorization: user.token || ''
			},
			body: JSON.stringify({ page: 1, size: 100 })
		});
		const data = await resp.json();
		if (data.code === 1000 && data.data?.list) {
			agents.value = data.data.list;
		}
	} catch {
		ElMessage.error('加载 Agent 列表失败');
	} finally {
		loading.value = false;
	}
}

// 新建
function handleCreate() {
	editAgentId.value = null;
	editVisible.value = true;
}

// 编辑
function handleEdit(agent: AgentInfo) {
	editAgentId.value = agent.id!;
	editVisible.value = true;
}

// 对话测试
function handleTest(agent: AgentInfo) {
	router.push({ path: '/agent/chat', query: { agentId: String(agent.id) } });
}

// 发布/取消发布
async function handleToggleStatus(agent: AgentInfo) {
	try {
		const newStatus = agent.status === 1 ? 0 : 1;
		const resp = await fetch(`${config.baseUrl}/admin/netaclaw/agent/update`, {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
				Authorization: user.token || ''
			},
			body: JSON.stringify({ id: agent.id, status: newStatus })
		});
		const data = await resp.json();
		if (data.code === 1000) {
			agent.status = newStatus;
			ElMessage.success(newStatus === 1 ? '已发布' : '已取消发布');
		}
	} catch {
		ElMessage.error('操作失败');
	}
}

// 删除
async function handleDelete(agent: AgentInfo) {
	try {
		const resp = await fetch(`${config.baseUrl}/admin/netaclaw/agent/delete`, {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
				Authorization: user.token || ''
			},
			body: JSON.stringify({ ids: [agent.id] })
		});
		const data = await resp.json();
		if (data.code === 1000) {
			ElMessage.success('删除成功');
			loadAgents();
		}
	} catch {
		ElMessage.error('删除失败');
	}
}

// 复制 API 信息
function copyApiInfo(agent: AgentInfo) {
	const text = JSON.stringify(
		{
			url: 'POST /open/agent/run/invoke',
			body: { agentId: agent.id, input: { videoUrl: 'https://...' } }
		},
		null,
		2
	);
	navigator.clipboard.writeText(text).then(() => {
		ElMessage.success('API 调用示例已复制');
	});
}

onMounted(() => {
	loadAgents();
});
</script>

<style lang="scss" scoped>
$live-green: #22c55e;

.agent-list {
	height: 100%;
	display: flex;
	flex-direction: column;
	background:
		radial-gradient(ellipse 50% 40% at 50% 0%, var(--el-color-primary-light-9) 0%, transparent 70%),
		var(--el-bg-color-page);

	&__header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 14px 20px;
		background: var(--el-bg-color);
		border-bottom: 1px solid var(--el-border-color-lighter);
		backdrop-filter: blur(8px);
		flex-shrink: 0;

		.header-stats {
			display: flex;
			gap: 12px;
		}

		.stat-chip {
			display: inline-flex;
			align-items: center;
			gap: 5px;
			padding: 5px 12px;
			border-radius: 8px;
			background: var(--el-color-primary-light-9);
			border: 1px solid var(--el-color-primary-light-7);
			font-size: 12px;
			color: var(--el-color-primary);

			&.is-live {
				background: rgba(34, 197, 94, 0.08);
				border-color: rgba(34, 197, 94, 0.2);
				color: $live-green;
			}

			.stat-num {
				font-weight: 700;
				font-size: 14px;
				font-variant-numeric: tabular-nums;
			}

			.stat-label {
				color: var(--el-text-color-secondary);
				font-size: 11px;
			}

			.live-dot {
				width: 6px;
				height: 6px;
				border-radius: 50%;
				background: $live-green;
				box-shadow: 0 0 6px $live-green;
				animation: pulse-dot 2s ease-in-out infinite;
			}
		}

		.header-actions {
			display: flex;
			align-items: center;
			gap: 10px;
		}

		.icon-btn {
			width: 34px;
			height: 34px;
			border-radius: 8px;
			border: 1px solid var(--el-border-color-lighter);
			background: transparent;
			color: var(--el-text-color-regular);
			cursor: pointer;
			display: flex;
			align-items: center;
			justify-content: center;
			transition: all 0.25s;

			&:hover {
				border-color: var(--el-color-primary);
				color: var(--el-color-primary);
				background: var(--el-color-primary-light-9);
			}
		}

		.search-input {
			width: 220px;

			:deep(.el-input__wrapper) {
				border-radius: 8px;
				transition: box-shadow 0.3s;

				&.is-focus {
					box-shadow: 0 0 0 1px var(--el-color-primary), 0 0 0 4px var(--el-color-primary-light-7) !important;
				}
			}
		}

		.create-btn {
			display: inline-flex;
			align-items: center;
			gap: 6px;
			padding: 8px 18px;
			border-radius: 10px;
			border: none;
			background: var(--el-color-primary);
			color: #fff;
			font-size: 13px;
			font-weight: 500;
			cursor: pointer;
			transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);

			&:hover {
				box-shadow: 0 4px 16px var(--el-color-primary-light-5);
				transform: translateY(-1px);
				background: var(--el-color-primary-light-3);
			}
		}
	}

	&__content {
		flex: 1;
		padding: 20px;
	}
}

.agent-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
	gap: 16px;
}

.agent-card {
	background: var(--el-bg-color);
	border-radius: 14px;
	padding: 20px;
	min-height: 200px;
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	cursor: default;
	transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
	border: 1px solid var(--el-border-color-lighter);
	position: relative;
	overflow: hidden;
	animation: card-enter 0.35s ease-out both;
	animation-delay: calc(var(--stagger, 0) * 50ms);

	&__glow {
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		height: 3px;
		background: linear-gradient(90deg, transparent, var(--el-color-primary-light-5), transparent);
		opacity: 0;
		transition: opacity 0.3s;
	}

	&:hover {
		border-color: var(--el-color-primary-light-5);
		box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06), 0 0 16px var(--el-color-primary-light-9);
		transform: translateY(-2px);

		.agent-card__glow {
			opacity: 1;
		}
	}

	&.is-published {
		.agent-card__glow {
			background: linear-gradient(90deg, transparent, rgba(34, 197, 94, 0.3), transparent);
		}

		&:hover .agent-card__glow {
			background: linear-gradient(90deg, transparent, rgba(34, 197, 94, 0.5), transparent);
		}
	}

	&__header {
		display: flex;
		align-items: center;
		gap: 12px;
		margin-bottom: 12px;
	}

	&__icon {
		width: 44px;
		height: 44px;
		border-radius: 12px;
		background: var(--el-color-primary-light-9);
		border: 1px solid var(--el-color-primary-light-7);
		display: flex;
		align-items: center;
		justify-content: center;
		color: var(--el-color-primary);
		flex-shrink: 0;
	}

	&__title {
		flex: 1;
		overflow: hidden;

		.name {
			font-size: 15px;
			font-weight: 600;
			margin: 0 0 4px 0;
			overflow: hidden;
			text-overflow: ellipsis;
			white-space: nowrap;
			color: var(--el-text-color-primary);
		}
	}

	&__tags {
		display: flex;
		gap: 6px;
		align-items: center;

		.status-badge {
			display: inline-flex;
			align-items: center;
			gap: 4px;
			padding: 2px 8px;
			border-radius: 6px;
			font-size: 11px;
			font-weight: 500;

			.status-dot {
				width: 5px;
				height: 5px;
				border-radius: 50%;
			}

			&.is-live {
				background: rgba(34, 197, 94, 0.1);
				color: $live-green;

				.status-dot {
					background: $live-green;
					box-shadow: 0 0 4px $live-green;
				}
			}

			&.is-draft {
				background: var(--el-fill-color-light);
				color: var(--el-text-color-placeholder);

				.status-dot {
					background: var(--el-text-color-placeholder);
				}
			}
		}

		.skill-count {
			font-size: 11px;
			color: var(--el-text-color-secondary);
			padding: 2px 8px;
			border-radius: 6px;
			background: var(--el-fill-color-light);
		}
	}

	&__desc {
		font-size: 13px;
		color: var(--el-text-color-secondary);
		flex: 1;
		overflow: hidden;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		margin: 0;
		line-height: 1.6;
	}

	&__api {
		margin-top: 10px;
		padding: 6px 10px;
		background: var(--el-color-primary-light-9);
		border: 1px solid var(--el-color-primary-light-7);
		border-radius: 8px;
		font-size: 11px;
		display: flex;
		align-items: center;
		justify-content: space-between;

		code {
			color: var(--el-color-primary);
			font-weight: 500;
			font-family: 'SF Mono', 'Fira Code', monospace;
		}

		.copy-btn {
			width: 24px;
			height: 24px;
			border-radius: 6px;
			border: none;
			background: transparent;
			color: var(--el-color-primary);
			cursor: pointer;
			display: flex;
			align-items: center;
			justify-content: center;
			transition: background 0.2s;

			&:hover {
				background: var(--el-color-primary-light-7);
			}
		}
	}

	&__footer {
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin-top: auto;
		padding-top: 12px;
		border-top: 1px solid var(--el-border-color-extra-light);
	}

	&__actions {
		display: flex;
		align-items: center;
		gap: 2px;

		.action-link {
			padding: 4px 10px;
			border: none;
			background: transparent;
			color: var(--el-color-primary);
			font-size: 12px;
			cursor: pointer;
			border-radius: 6px;
			transition: all 0.2s;

			&:hover:not(:disabled) {
				background: var(--el-color-primary-light-9);
			}

			&:disabled {
				color: var(--el-text-color-placeholder);
				cursor: not-allowed;
			}

			&.is-danger {
				color: var(--el-color-danger);

				&:hover {
					background: rgba(245, 108, 108, 0.08);
				}
			}
		}
	}
}

.empty-state {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 60px 20px;
	gap: 8px;

	p {
		margin: 0;
		font-size: 15px;
		font-weight: 500;
		color: var(--el-text-color-secondary);
	}

	span {
		font-size: 12px;
		color: var(--el-text-color-placeholder);
	}
}

@keyframes card-enter {
	from { opacity: 0; transform: translateY(12px); }
	to { opacity: 1; transform: translateY(0); }
}

@keyframes pulse-dot {
	0%, 100% { opacity: 1; }
	50% { opacity: 0.4; }
}
</style>
