<template>
	<div class="management-page">
		<div class="page-head">
			<div>
				<h1>{{ t('pages.mcp.title') }}</h1>
				<p>{{ t('pages.mcp.subtitle') }}</p>
			</div>
		</div>

		<el-card class="list-card">
			<div class="toolbar">
				<div class="toolbar-left">
					<el-input
						v-model="keyword"
						clearable
						:placeholder="t('pages.mcp.searchPlaceholder')"
						class="search-input"
						@keyup.enter="loadList(1)"
					>
						<template #prefix>
							<el-icon>
								<Search />
							</el-icon>
						</template>
					</el-input>
					<el-select
						v-model="transportType"
						clearable
						:placeholder="t('pages.mcp.transferType')"
						style="width: 160px"
						@change="loadList(1)"
					>
						<el-option label="stdio" value="stdio" />
						<el-option label="sse" value="sse" />
						<el-option label="streamable" value="streamable" />
						<el-option label="http" value="http" />
					</el-select>
					<div class="toolbar-actions">
						<el-button type="primary" @click="loadList(1)">
							<el-icon><Search /></el-icon>
							{{ t('common.search') }}
						</el-button>
						<el-button @click="handleReset">
							<el-icon><RefreshRight /></el-icon>
							{{ t('common.reset') }}
						</el-button>
					</div>
				</div>
				<div class="toolbar-right">
					<el-button type="primary" @click="openCreate">
						<el-icon>
							<Plus />
						</el-icon>
						{{ t('pages.mcp.createMcp') }}
					</el-button>
				</div>
			</div>

			<div class="toolbar-meta">
				<span class="pill">{{ t('pages.mcp.totalServices', { count: pagination.totalCount }) }}</span>
				<span class="pill">{{ t('pages.mcp.enabledCount', { count: enabledCount }) }}</span>
			</div>

			<!-- <div class="summary-grid">
			<div class="summary-card">
				<div class="summary-value">{{ pagination.totalCount }}</div>
				<div class="summary-label">MCP 总数</div>
			</div>
			<div class="summary-card">
				<div class="summary-value">{{ enabledCount }}</div>
				<div class="summary-label">启用中</div>
			</div>
			<div class="summary-card">
				<div class="summary-value">{{ transportCount }}</div>
				<div class="summary-label">传输类型</div>
			</div>
		</div> -->

			<div v-loading="loading" class="grid">
				<el-empty class="empty" v-if="!list.length && !loading" :description="t('pages.mcp.noMcp')" />
				<div v-for="row in list" :key="row.id" class="card">
					<div class="card-head">
						<div class="card-head__top">
							<div class="title-block">
								<div class="title">{{ row.name || t('pages.mcp.unnamedMcp') }}</div>
								<div class="subtitle">{{ row.url || t('pages.mcp.noAddress') }}</div>
							</div>
							<div class="actions">
								<el-dropdown>
									<span class="actions-trigger">
										<el-icon>
											<MoreFilled />
										</el-icon>
									</span>
									<template #dropdown>
										<el-dropdown-menu>
											<el-dropdown-item @click="checkItem(row.id!)">{{ t('pages.mcp.test') }}</el-dropdown-item>
											<el-dropdown-item @click="openTools(row.id!)">{{ t('pages.mcp.tools') }}</el-dropdown-item>
											<el-dropdown-item @click="openEditById(row.id!)">{{ t('common.edit') }}</el-dropdown-item>
											<el-dropdown-item divided @click="removeItem(row.id!)">
												<span class="danger-text">{{ t('common.delete') }}</span>
											</el-dropdown-item>
										</el-dropdown-menu>
									</template>
								</el-dropdown>
							</div>
						</div>
						<div class="badge-row">
							<el-tag :type="row.enabled ? 'success' : 'warining'" class="badge subtle">{{
								row.enabled ? t('pages.mcp.enabled') : t('pages.mcp.disabled')
							}}</el-tag>
							<el-tag class="badge">{{ row.transport_type || t('pages.mcp.noTransferType') }}</el-tag>
						</div>
					</div>

					<div class="desc">{{ row.description || t('pages.mcp.noDescription') }}</div>
				</div>
			</div>

			<div v-if="pagination.totalCount > 0" class="pagination">
				<el-pagination
					v-model:current-page="pagination.pageIndex"
					v-model:page-size="pagination.pageSize"
					background
					layout="total, prev, pager, next"
					:total="pagination.totalCount"
					@current-change="handlePageChange"
					@size-change="handleSizeChange"
				/>
			</div>
		</el-card>

		<el-drawer
			v-model="drawerVisible"
			:title="currentId ? t('pages.mcp.editMcp') : t('pages.mcp.createMcpTitle')"
			direction="rtl"
			size="760px"
		>
			<el-form ref="formRef" :model="form" :rules="rules" label-position="top">
				<el-form-item :label="t('pages.mcp.name')" prop="name">
					<el-input v-model="form.name" />
				</el-form-item>
				<el-form-item :label="t('pages.mcp.description')" prop="description">
					<el-input v-model="form.description" type="textarea" :rows="2" />
				</el-form-item>
				<div class="grid-2">
					<el-form-item :label="t('pages.mcp.transferType')" prop="transport_type">
						<el-select v-model="form.transport_type" style="width: 100%">
							<el-option label="SSE(Server-Sent Events)" value="sse" />
							<el-option label="HTTP Streamable" value="http-streamable" />
						</el-select>
					</el-form-item>
					<el-form-item :label="t('pages.mcp.enableLabel')" prop="enabled">
						<el-switch v-model="form.enabled" />
					</el-form-item>
				</div>
				<el-form-item :label="t('pages.mcp.address')" prop="url">
					<el-input v-model="form.url" />
				</el-form-item>
				<el-form-item :label="t('pages.mcp.timeout')" prop="advanced_config.timeout">
					<el-input-number v-model="form.advanced_config.timeout" :min="0" style="width: 100%" />
				</el-form-item>
				<div class="grid-2">
					<el-form-item :label="t('pages.mcp.retryCount')" prop="advanced_config.retry_count">
						<el-input-number
							v-model="form.advanced_config.retry_count"
							:min="0"
							style="width: 100%"
						/>
					</el-form-item>
					<el-form-item :label="t('pages.mcp.retryInterval')" prop="advanced_config.retry_delay">
						<el-input-number
							v-model="form.advanced_config.retry_delay"
							:min="0"
							style="width: 100%"
						/>
					</el-form-item>
				</div>
				<el-form-item label="Headers">
					<div class="kv-config">
						<div class="kv-config__top">
							<span>{{ t('pages.mcp.requestHeaders') }}</span>
							<el-button type="primary" link @click="addHeaderRow">
								<el-icon> <Plus /> </el-icon>{{ t('pages.mcp.add') }}
							</el-button>
						</div>
						<div class="kv-config__rows">
							<div
								v-for="(item, index) in headerList"
								:key="`header-${index}`"
								class="kv-config__row"
							>
								<el-input v-model="item.key" :placeholder="t('pages.mcp.headerName')" />
								<el-input v-model="item.value" :placeholder="t('pages.mcp.headerValue')" />
								<el-button
									link
									type="danger"
									:disabled="headerList.length === 1"
									@click="removeHeaderRow(index)"
								>
									{{ t('common.delete') }}
								</el-button>
							</div>
						</div>
					</div>
				</el-form-item>
				<el-form-item label="Auth Config">
					<div class="kv-config">
						<div class="kv-config__top">
							<span>{{ t('pages.mcp.authConfig') }}</span>
							<el-button type="primary" link @click="addAuthRow">
								<el-icon> <Plus /> </el-icon>{{ t('pages.mcp.add') }}
							</el-button>
						</div>
						<div class="kv-config__rows">
							<div v-for="(item, index) in authList" :key="`auth-${index}`" class="kv-config__row">
								<el-input v-model="item.key" :placeholder="t('pages.mcp.configName')" />
								<el-input v-model="item.value" :placeholder="t('pages.mcp.configValue')" />
								<el-button
									link
									type="danger"
									:disabled="authList.length === 1"
									@click="removeAuthRow(index)"
								>
									{{ t('common.delete') }}
								</el-button>
							</div>
						</div>
					</div>
				</el-form-item>
				<el-form-item label="Env Vars">
					<div class="kv-config">
						<div class="kv-config__top">
							<span>{{ t('pages.mcp.envVariables') }}</span>
							<el-button type="primary" link @click="addEnvRow">
								<el-icon> <Plus /> </el-icon>{{ t('pages.mcp.add') }}
							</el-button>
						</div>
						<div class="kv-config__rows">
							<div v-for="(item, index) in envList" :key="`env-${index}`" class="kv-config__row">
								<el-input v-model="item.key" :placeholder="t('pages.mcp.envVarName')" />
								<el-input v-model="item.value" :placeholder="t('pages.mcp.envVarValue')" />
								<el-button
									link
									type="danger"
									:disabled="envList.length === 1"
									@click="removeEnvRow(index)"
								>
									{{ t('common.delete') }}
								</el-button>
							</div>
						</div>
					</div>
				</el-form-item>
				<el-form-item>
					<div class="check-box">
						<el-button :loading="checkLoading" :disabled="!currentId" @click="checkItemByForm">
							{{ t('pages.mcp.testConnection') }}
						</el-button>
						<el-alert
							v-if="checkMessage"
							:title="checkMessage"
							:type="checkSuccess ? 'success' : 'error'"
							:closable="false"
							show-icon
						/>
					</div>
				</el-form-item>
			</el-form>
			<template #footer>
				<div class="drawer-footer">
					<el-button @click="drawerVisible = false">{{ t('common.cancel') }}</el-button>
					<el-button type="primary" :loading="submitLoading" @click="handleSubmit">{{ t('common.save') }}</el-button>
				</div>
			</template>
		</el-drawer>

		<el-dialog v-model="detailVisible" :title="t('pages.mcp.mcpDetail')" width="720px">
			<el-descriptions v-if="detailItem" :column="1" border>
				<el-descriptions-item :label="t('pages.mcp.name')">{{ detailItem.name }}</el-descriptions-item>
				<el-descriptions-item :label="t('pages.mcp.transferType')">{{
					detailItem.transport_type
				}}</el-descriptions-item>
				<el-descriptions-item :label="t('pages.mcp.address')">{{ detailItem.url || '-' }}</el-descriptions-item>
				<el-descriptions-item :label="t('pages.mcp.description')">{{
					detailItem.description || '-'
				}}</el-descriptions-item>
			</el-descriptions>
		</el-dialog>

		<el-dialog v-model="resourcesVisible" :title="t('pages.mcp.mcpResources')" width="720px">
			<el-empty v-if="!resourceList.length" :description="t('pages.mcp.noResources')" />
			<el-space v-else wrap>
				<el-tag v-for="item in resourceList" :key="item">{{ item }}</el-tag>
			</el-space>
		</el-dialog>

		<el-dialog v-model="toolsVisible" :title="t('pages.mcp.mcpTools')" width="720px" class="tool-modal">
			<div class="tool-dialog">
				<el-input
					v-model="toolKeyword"
					clearable
					:placeholder="t('pages.mcp.searchToolPlaceholder')"
					class="tool-search-input"
				>
					<template #prefix>
						<el-icon>
							<Search />
						</el-icon>
					</template>
				</el-input>
				<el-empty v-if="!filteredToolDetailList.length" :description="t('pages.mcp.noTools')" />
				<el-scrollbar v-else max-height="420px">
					<el-collapse>
						<el-collapse-item v-for="item in filteredToolDetailList" :key="item.name">
							<template #title>
								<div>
									<div class="tool-desc text-16px text-primary mb-4px">{{ item.name }}</div>
									<div class="tool-desc text-12px">{{ item.description }}</div>
								</div>
							</template>
							<el-card>
								<el-descriptions direction="vertical" :column="1">
									<el-descriptions-item :label="t('pages.mcp.paramSchema')">
										<CodeEditor
											:model-value="JSON.stringify(item.inputSchema, null, 2)"
											language="json"
											:height="260"
											:tools="false"
											readonly
										/>
									</el-descriptions-item>
								</el-descriptions>
							</el-card>
						</el-collapse-item>
					</el-collapse>
				</el-scrollbar>
			</div>
		</el-dialog>
	</div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Search, MoreFilled, RefreshRight } from '@element-plus/icons-vue'
import { resource } from '@repo/api-service'
import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
import { useI18n } from '@/composables/useI18n'

type McpPageResponse = Awaited<ReturnType<typeof resource.postMcpPageList>>
type McpItem = NonNullable<McpPageResponse['result']>['model'][number]
type McpInfoResponse = Awaited<ReturnType<typeof resource.postMcpInfo>>
type McpInfoItem = NonNullable<McpInfoResponse['result']>
type McpCheckResponse = Awaited<ReturnType<typeof resource.postMcpCheck>>
type McpToolItem = NonNullable<McpCheckResponse['result']>['tools'][number]
type KvRow = { key: string; value: string }

const { t } = useI18n()

const keyword = ref('')
const transportType = ref('')
const loading = ref(false)
const submitLoading = ref(false)
const checkLoading = ref(false)
const drawerVisible = ref(false)
const detailVisible = ref(false)
const resourcesVisible = ref(false)
const toolsVisible = ref(false)
const currentId = ref('')
const detailItem = ref<McpInfoItem | null>(null)
const resourceList = ref<string[]>([])
const toolDetailList = ref<McpToolItem[]>([])
const toolKeyword = ref('')
const checkMessage = ref('')
const checkSuccess = ref(false)
const headerList = ref<KvRow[]>([{ key: '', value: '' }])
const authList = ref<KvRow[]>([{ key: '', value: '' }])
const envList = ref<KvRow[]>([{ key: '', value: '' }])
const formRef = ref()

const pagination = reactive({
	pageIndex: 1,
	pageSize: 20,
	totalCount: 0
})

const list = ref<McpItem[]>([])

const form = reactive({
	name: '',
	description: '',
	transport_type: 'http-streamable',
	url: '',
	enabled: true,
	headers: {} as Record<string, any>,
	auth_config: {} as Record<string, any>,
	advanced_config: {
		timeout: 30,
		retry_count: 3,
		retry_delay: 1
	},
	env_vars: {} as Record<string, any>
})

const rules = {
	name: [{ required: true, message: t('pages.mcp.pleaseInputName'), trigger: 'blur' }],
	transport_type: [{ required: true, message: t('pages.mcp.pleaseSelectTransferType'), trigger: 'change' }],
	url: [{ required: true, message: t('pages.mcp.pleaseInputAddress'), trigger: 'blur' }]
}

const enabledCount = computed(() => list.value.filter((item) => item.enabled).length)
const transportCount = computed(() => new Set(list.value.map((item) => item.transport_type)).size)
const filteredToolDetailList = computed(() => {
	const keywordValue = toolKeyword.value.trim().toLowerCase()
	if (!keywordValue) return toolDetailList.value
	return toolDetailList.value.filter((item) => {
		const name = item.name?.toLowerCase() || ''
		const description = item.description?.toLowerCase() || ''
		return name.includes(keywordValue) || description.includes(keywordValue)
	})
})

function toKvRows(record?: Record<string, any>) {
	const rows = Object.entries(record || {}).map(([key, value]) => ({
		key,
		value: String(value ?? '')
	}))
	return rows.length ? rows : [{ key: '', value: '' }]
}

function toRecord(rows: KvRow[]) {
	const record: Record<string, string> = {}
	for (const item of rows) {
		const key = item.key.trim()
		if (!key) continue
		record[key] = item.value
	}
	return record
}

function resetForm() {
	currentId.value = ''
	checkMessage.value = ''
	checkSuccess.value = false
	form.name = ''
	form.description = ''
	form.transport_type = 'http-streamable'
	form.url = ''
	form.enabled = true
	form.headers = {}
	form.auth_config = {}
	form.advanced_config.timeout = 30
	form.advanced_config.retry_count = 3
	form.advanced_config.retry_delay = 1
	form.env_vars = {}
	headerList.value = [{ key: '', value: '' }]
	authList.value = [{ key: '', value: '' }]
	envList.value = [{ key: '', value: '' }]
}

function addHeaderRow() {
	headerList.value.push({ key: '', value: '' })
}

function removeHeaderRow(index: number) {
	if (headerList.value.length === 1) {
		headerList.value[0] = { key: '', value: '' }
		return
	}
	headerList.value.splice(index, 1)
}

function addAuthRow() {
	authList.value.push({ key: '', value: '' })
}

function removeAuthRow(index: number) {
	if (authList.value.length === 1) {
		authList.value[0] = { key: '', value: '' }
		return
	}
	authList.value.splice(index, 1)
}

function addEnvRow() {
	envList.value.push({ key: '', value: '' })
}

function removeEnvRow(index: number) {
	if (envList.value.length === 1) {
		envList.value[0] = { key: '', value: '' }
		return
	}
	envList.value.splice(index, 1)
}

async function loadList(pageIndex = 1) {
	loading.value = true
	try {
		const res = await resource.postMcpPageList({
			keyword: keyword.value,
			transport_type: transportType.value,
			pageIndex,
			pageSize: pagination.pageSize
		})
		if (res.isSuccess && res.result) {
			list.value = (res.result.model || []) as McpItem[]
			pagination.pageIndex = res.result.currentPage || pageIndex
			pagination.pageSize = res.result.pageSize || pagination.pageSize
			pagination.totalCount = res.result.totalCount || 0
		}
	} finally {
		loading.value = false
	}
}

function handlePageChange(page: number) {
	pagination.pageIndex = page
	loadList(page)
}

function handleSizeChange(size: number) {
	pagination.pageSize = size
	loadList(1)
}

function handleReset() {
	keyword.value = ''
	transportType.value = ''
	loadList(1)
}

function openCreate() {
	resetForm()
	drawerVisible.value = true
}

async function openEditById(id: string) {
	const res = await resource.postMcpInfo({ id })
	if (!res.isSuccess || !res.result) {
		ElMessage.error(t('pages.mcp.fetchDetailFailed'))
		return
	}
	resetForm()
	currentId.value = id
	form.name = res.result.name || ''
	form.description = res.result.description || ''
	form.transport_type = res.result.transport_type || 'http-streamable'
	form.url = res.result.url || ''
	form.enabled = !!res.result.enabled
	form.headers = res.result.headers || {}
	form.auth_config = res.result.auth_config || {}
	form.advanced_config.timeout = res.result.advanced_config?.timeout ?? 30
	form.advanced_config.retry_count = res.result.advanced_config?.retry_count ?? 1
	form.advanced_config.retry_delay = res.result.advanced_config?.retry_delay ?? 1
	form.env_vars = res.result.env_vars || {}
	headerList.value = toKvRows(form.headers)
	authList.value = toKvRows(form.auth_config)
	envList.value = toKvRows(form.env_vars)
	drawerVisible.value = true
}

async function checkItem(id: string) {
	try {
		const res = await resource.postMcpCheck({ id })
		if (res.isSuccess) {
			ElMessage.success(res.result?.message || t('pages.mcp.connectSuccess'))
		} else {
			ElMessage.error(t('pages.mcp.connectFailed'))
		}
	} catch {
		ElMessage.error(t('pages.mcp.connectFailed'))
	}
}

async function checkItemByForm() {
	if (!currentId.value) {
		checkSuccess.value = false
		checkMessage.value = t('pages.mcp.pleaseSaveFirst')
		return
	}
	checkLoading.value = true
	checkMessage.value = ''
	try {
		const res = await resource.postMcpCheck({ id: currentId.value })
		checkSuccess.value = !!res.isSuccess
		checkMessage.value = res.isSuccess ? res.result?.message || t('pages.mcp.connectSuccess') : t('pages.mcp.connectFailed')
	} catch {
		checkSuccess.value = false
		checkMessage.value = t('pages.mcp.connectFailed')
	} finally {
		checkLoading.value = false
	}
}

async function handleSubmit() {
	await formRef.value?.validate(async (valid: boolean) => {
		if (!valid) return
		submitLoading.value = true
		try {
			const payload = {
				name: form.name,
				description: form.description,
				transport_type: form.transport_type,
				url: form.url,
				enabled: form.enabled,
				headers: toRecord(headerList.value),
				auth_config: toRecord(authList.value),
				advanced_config: {
					timeout: form.advanced_config.timeout,
					retry_count: form.advanced_config.retry_count,
					retry_delay: form.advanced_config.retry_delay
				},
				env_vars: toRecord(envList.value)
			}
			if (currentId.value) {
				await resource.postMcpUpdate({ id: currentId.value, ...(payload as any) })
				ElMessage.success(t('pages.mcp.updateSuccess'))
			} else {
				await resource.postMcpCreate(payload as any)
				ElMessage.success(t('pages.mcp.createSuccess'))
			}
			drawerVisible.value = false
			loadList(pagination.pageIndex)
		} catch {
			ElMessage.error(t('pages.mcp.saveFailed'))
		} finally {
			submitLoading.value = false
		}
	})
}

async function removeItem(id: string) {
	try {
		await ElMessageBox.confirm(t('pages.mcp.confirmDelete'), t('pages.mcp.tip'), { type: 'warning' })
		await resource.postMcpOpenApiDelete({ id })
		ElMessage.success(t('pages.mcp.deleteSuccess'))
		loadList(pagination.pageIndex)
	} catch {
		// ignore
	}
}

async function openResources(id: string) {
	const res = await resource.postMcpResources({ id })
	resourceList.value = res.isSuccess ? res.result || [] : []
	resourcesVisible.value = true
}

async function openTools(id: string) {
	const res = await resource.postMcpTools({ id })
	toolKeyword.value = ''
	toolDetailList.value = res.isSuccess ? res.result || [] : []
	toolsVisible.value = true
}

onMounted(() => {
	loadList(1)
})
</script>

<style scoped lang="less">
.management-page {
	padding: 24px;
	min-height: 100%;
	box-sizing: border-box;
}

.page-head {
	margin-bottom: 20px;

	h1 {
		margin: 0;
		font-size: 28px;
		color: var(--text-primary);
	}

	p {
		margin: 6px 0 0;
		font-size: 14px;
		color: var(--text-secondary);
	}
}

:deep(.el-collapse-item__header) {
	height: 80px;
}

.list-card {
	border-radius: 18px;
	margin-bottom: 16px;
}

.section-title {
	margin: 10px 0 12px;
	font-size: 14px;
	font-weight: 700;
	color: var(--text-primary);
	display: flex;
	align-items: center;
	gap: 12px;
}

.toolbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	flex-wrap: wrap;
}

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

.toolbar-actions {
	display: flex;
	align-items: center;
	gap: 8px;

	.el-button + .el-button {
		margin-left: 0;
	}
}

.search-input {
	width: 280px;
}

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

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

.summary-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
	gap: 12px;
}

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

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

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

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

	.empty {
		grid-column: span 4;
	}
}

.card {
	overflow: hidden;
	border-radius: 20px;
	border: 1px solid var(--border-light);
	background: var(--bg-base);
	box-shadow: var(--shadow-sm);
	padding: 16px;
	display: flex;
	flex-direction: column;
	gap: 14px;
	transition:
		transform 0.22s ease,
		box-shadow 0.22s ease,
		border-color 0.22s ease;
}

.card:hover {
	transform: translateY(-3px);
	border-color: var(--border-base);
	box-shadow: var(--shadow-md);
}

.card-head {
	padding: 14px 16px;
	border-radius: 18px;
	background: var(--card-bg-unselected);
}

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

.actions {
	display: flex;
	justify-content: flex-end;
}

.actions-trigger {
	width: 30px;
	height: 30px;
	border-radius: 999px;
	display: grid;
	place-items: center;
	color: var(--text-secondary);
	background: var(--bg-overlay);
	transition:
		background 0.2s ease,
		color 0.2s ease;
}

.actions-trigger:hover {
	background: var(--bg-container);
	color: var(--text-strong);
}

.title {
	font-size: 18px;
	font-weight: 700;
	line-height: 1.25;
	color: var(--text-strong);
	word-break: break-word;
}

.subtitle {
	margin-top: 6px;
	font-size: 13px;
	color: var(--text-secondary);
	word-break: break-all;
}

.badge-row {
	margin-top: 10px;
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.badge {
	padding: 5px 10px;
	border-radius: 999px;
	background: var(--bg-overlay);
	font-size: 12px;
	color: var(--text-primary);
	border: 1px solid var(--border-light);
}

.desc {
	min-height: 44px;
	color: var(--text-secondary);
	font-size: 14px;
	line-height: 1.65;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.tags {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.meta-list {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 10px;
}

.meta-item {
	padding: 10px 12px;
	border-radius: 14px;
	background: var(--bg-container);
	border: 1px solid var(--border-light);
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

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

.meta-value {
	font-size: 13px;
	color: var(--text-primary);
	word-break: break-word;
}

.danger-text {
	color: var(--el-color-danger);
}

.pagination {
	display: flex;
	justify-content: flex-end;
}

.grid-2 {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 12px;
}

.drawer-footer {
	display: flex;
	justify-content: flex-end;
	gap: 10px;
}

.tool-dialog {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.tool-search-input {
	width: 100%;
}

.kv-config {
	width: 100%;
}

.kv-config__top {
	display: flex;
	align-items: center;
	justify-content: space-between;
}

.kv-config__desc {
	margin: 4px 0 10px;
	font-size: 12px;
	color: var(--text-secondary);
}

.kv-config__rows {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.kv-config__row {
	display: grid;
	grid-template-columns: 1fr 1fr auto;
	gap: 8px;
	align-items: center;
}

.check-box {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.tool-desc {
	color: var(--text-secondary);
	line-height: 1.6;
}

@media (max-width: 768px) {
	.search-input {
		width: 100%;
	}

	.grid-2,
	.meta-list,
	.kv-config__row {
		grid-template-columns: 1fr;
	}
}
</style>
