<template>
	<div class="channel-page">
		<div class="channel-page__header">
			<div class="channel-page__title">
				<h2>频道管理</h2>
				<p>支持两种模式：<strong>微信私聊助手</strong>（扫码登录独立 bot 账号，用于一对一私聊）；<strong>微信本地代理 weixin-db</strong>（从本机 PC 微信数据库读取消息，用于群聊场景，需 Windows + 已登录 PC 微信）。</p>
			</div>
			<div class="channel-page__actions">
				<el-select v-model="filters.loginStatus" clearable placeholder="连接状态" style="width: 140px">
					<el-option
						v-for="item in options.loginStatuses"
						:key="item.value"
						:label="item.label"
						:value="item.value"
					/>
				</el-select>
				<el-input
					v-model="filters.keyword"
					clearable
					placeholder="搜索频道名"
					style="width: 220px"
					@keyup.enter="loadData"
				/>
				<el-button @click="loadData">查询</el-button>
				<el-button type="primary" @click="handleAdd">新建频道</el-button>
			</div>
		</div>

		<div class="channel-grid" v-loading="loading">
			<div v-for="item in list" :key="item.id" class="channel-card">
				<div class="channel-card__top">
					<div>
						<div class="channel-card__name">{{ item.name }}</div>
						<div class="channel-card__meta">
							<el-tag size="small" type="success">
								{{ item.type === 'weixin-db' ? '微信本地代理' : '微信' }}
							</el-tag>
							<el-tag size="small" :type="statusTagType(item.loginStatus)">
								{{ loginStatusLabel(item.loginStatus) }}
							</el-tag>
							<el-tag size="small" :type="item.status === 1 ? 'primary' : 'info'">
								{{ item.status === 1 ? '启用' : '禁用' }}
							</el-tag>
							<el-tag
								v-if="(item.groupTotal ?? 0) > 0"
								size="small"
								type="info"
								:class="{ 'group-badge--inactive': (item.groupEnabled ?? 0) === 0 }"
							>
								群聊 {{ item.groupEnabled ?? 0 }}/{{ item.groupTotal }}
							</el-tag>
							<el-tag
								v-if="item.type === 'weixin-db' && item.wechatVersion"
								size="small"
								type="info"
							>
								版本 {{ item.wechatVersion }}
							</el-tag>
						</div>
					</div>
					<el-switch
						:model-value="item.status === 1"
						@change="(val) => handleToggleStatus(item, val)"
					/>
				</div>

				<div class="channel-card__body">
					<div class="info-row" v-if="item.type === 'weixin-db'">
						<span class="label">微信号</span>
						<span class="value">{{ item.wxid || '-' }}</span>
					</div>
					<div class="info-row" v-if="item.type === 'weixin-db'">
						<span class="label">微信版本</span>
						<span class="value">
							{{ item.wechatVersion || '-' }}
						</span>
					</div>
					<div class="info-row" v-if="item.type === 'weixin'">
						<span class="label">绑定 Agent</span>
						<span class="value">{{ agentLabel(item) }}</span>
					</div>
					<div class="info-row">
						<span class="label">最近连接</span>
						<span class="value">{{ item.lastConnectedAt || '-' }}</span>
					</div>
					<div class="info-row">
						<span class="label">说明</span>
						<span class="value">{{ item.description || '-' }}</span>
					</div>
					<div class="info-row" v-if="item.lastError">
						<span class="label">错误</span>
						<span class="value is-error">{{ item.lastError }}</span>
					</div>
				</div>

				<div class="channel-card__footer">
					<el-button link type="primary" @click="handleEdit(item)">编辑</el-button>
					<el-button v-if="item.type === 'weixin'" link type="success" @click="openQrDialog(item)">
						微信Bot 扫码登录
					</el-button>
					<el-button
						v-if="(item.type === 'weixin' && item.loginStatus === 'connected') || item.type === 'weixin-db'"
						link
						type="primary"
						@click="handleManageGroups(item)"
					>群聊管理</el-button>
					<el-button
						v-if="item.type === 'weixin'"
						link
						@click="handleRestart(item)"
						:disabled="item.loginStatus !== 'connected'"
					>重连</el-button>
					<el-button
						v-if="item.type === 'weixin'"
						link
						@click="handleDisconnect(item)"
						:disabled="item.loginStatus === 'disconnected'"
					>断开</el-button>
					<el-popconfirm title="确定清空该频道下所有微信会话上下文？" @confirm="handleClearSessions(item)">
						<template #reference>
							<el-button link type="warning">清空会话</el-button>
						</template>
					</el-popconfirm>
					<el-popconfirm title="确定删除该频道？" @confirm="handleDelete(item)">
						<template #reference>
							<el-button link type="danger">删除</el-button>
						</template>
					</el-popconfirm>
				</div>
			</div>
		</div>

		<div class="channel-page__pagination">
			<el-pagination
				v-model:current-page="pagination.page"
				v-model:page-size="pagination.size"
				:page-sizes="[12, 24, 48]"
				:total="pagination.total"
				layout="total, sizes, prev, pager, next, jumper"
				@size-change="loadData"
				@current-change="loadData"
			/>
		</div>

		<el-drawer v-model="drawer.visible" :title="drawer.isEdit ? '编辑频道' : '新建频道'" size="520px">
			<el-form ref="formRef" :model="drawer.form" :rules="rules" label-width="96px">
				<el-form-item label="频道名称" prop="name">
					<el-input v-model="drawer.form.name" placeholder="如：老板微信" />
				</el-form-item>
				<el-form-item label="频道类型" prop="type">
					<el-select v-model="drawer.form.type" style="width: 100%" :disabled="drawer.isEdit">
						<el-option v-for="item in options.types" :key="item.value" :label="item.label" :value="item.value" />
					</el-select>
					<div class="form-hint">微信本地代理 weixin-db 从本机 PC 微信数据库读取消息，仅 Windows 可用；微信Bot 通过扫码登录 iLink。编辑后不可修改类型。</div>
				</el-form-item>
				<el-form-item
					v-if="drawer.form.type === 'weixin'"
					label="绑定 Agent"
					prop="agentId"
				>
					<el-select v-model="drawer.form.agentId" style="width: 100%" filterable clearable>
						<el-option
							v-for="item in options.agents"
							:key="item.id"
							:label="item.label"
							:value="item.id"
						/>
					</el-select>
				</el-form-item>

				<!-- 微信Bot 专属字段 -->
				<template v-if="drawer.form.type === 'weixin'">
					<el-form-item label="机器人昵称" prop="botAlias">
						<el-input
							v-model="drawer.form.botAlias"
							placeholder="bot 在群里显示的昵称，用于 @ 匹配（如：小神）"
							clearable
						/>
						<div class="form-hint">必填项，否则群聊 "@机器人" 策略无法识别。</div>
					</el-form-item>
				</template>

				<!-- weixin-db 专属字段 -->
				<template v-if="drawer.form.type === 'weixin-db'">
					<el-form-item label="微信号 wxid" prop="wxid">
						<el-input
							v-model="drawer.form.wxid"
							placeholder="如：wxid_abc123（在 PC 微信 设置→关于 查看）"
							clearable
						/>
						<div class="form-hint">必填。同一 wxid 只能绑一个 weixin-db 渠道。本地代理按此 wxid 定位本机 PC 微信数据库。</div>
					</el-form-item>
					<el-alert
						type="info"
						:closable="false"
						show-icon
						title="请确保本机已登录 PC 微信，且当前为 Windows 环境。weixin-db 会从本机微信数据库按 wxid 读取群聊消息。"
					/>

				<el-divider>微信自动回复（v4 桌面操作）</el-divider>

				<el-form-item label="启用自动回复">
					<el-switch v-model="drawer.form.weixinReply.enabled" />
					<div class="form-hint">启用后,reply agent 通过 delegate_task 委托桌面操作 agent 在群里发消息。</div>
				</el-form-item>

				<template v-if="drawer.form.weixinReply.enabled">
					<el-form-item label="桌面操作 Agent" prop="weixinReply.desktopAgentId">
						<el-select
							v-model="drawer.form.weixinReply.desktopAgentId"
							placeholder="选择 multimodal model 的 agent(toolset 自动补齐)"
							clearable
							filterable
							style="width: 100%"
						>
							<el-option
								v-for="agent in desktopAgents"
								:key="agent.id"
								:value="agent.id"
								:label="`${agent.label || agent.name} (#${agent.id})`"
							/>
						</el-select>
						<div class="form-hint">
							必填。建议选 <strong>multimodal model</strong>(如火山 Seed-2.0-pro)的 agent;系统保存时会自动给它加 'weixin_desktop' toolset 并补齐 weixin_send_text 路由配置。
							当前候选 agent 数:{{ desktopAgents.length }}
						</div>
					</el-form-item>

					<el-form-item label="对话 Agent 提示">
						<el-alert
							type="info"
							:closable="false"
							show-icon
							title="建议(非强制):对话 Agent 开启 Subagent 功能,这样它才能通过 delegate_task 委托给桌面 Agent。若用其他方式让 reply agent 调 weixin_send_text 也可。"
						/>
					</el-form-item>

					<el-form-item label="每群每分钟">
						<el-input-number
							v-model="drawer.form.weixinReply.perGroupPerMinute"
							:min="1" :max="60" :step="1"
						/>
						<span style="margin-left: 8px; color: #909399;">条/分钟,默认 3</span>
					</el-form-item>

					<el-form-item label="每天上限">
						<el-input-number
							v-model="drawer.form.weixinReply.dailyLimit"
							:min="1" :max="10000" :step="1"
						/>
						<span style="margin-left: 8px; color: #909399;">条/天,默认 100</span>
					</el-form-item>

					<el-form-item label="小号安全模式">
						<el-switch v-model="drawer.form.weixinReply.safeMode" />
						<div class="form-hint">开启后:慢速 + 随机延迟,降低风控风险</div>
					</el-form-item>

					<el-form-item label="消息水印">
						<el-radio-group v-model="drawer.form.weixinReply.watermark">
							<el-radio value="none">不加</el-radio>
							<el-radio value="suffix">后缀 " —AI"</el-radio>
							<el-radio value="zero-width">零宽空格</el-radio>
						</el-radio-group>
					</el-form-item>

					<el-alert
						type="info"
						:closable="false"
						show-icon
						title="桌面操作 Agent 的模型 / prompt / toolset 请在 Agent 管理页配置(选 multimodal modelChannel,如火山 Seed-2.0-pro)"
					/>
				</template>
			</template>

				<el-form-item label="说明">
					<el-input v-model="drawer.form.description" type="textarea" :rows="3" placeholder="这个微信频道的用途" />
				</el-form-item>
			</el-form>
			<template #footer>
				<el-button @click="drawer.visible = false">取消</el-button>
				<el-button type="primary" :loading="saving" @click="handleSave">保存</el-button>
			</template>
		</el-drawer>

		<el-dialog v-model="qrDialog.visible" title="微信Bot 扫码登录（个人微信助手）" width="420px" @closed="stopQrPolling">
			<div class="qr-dialog" v-loading="qrDialog.loading">
				<template v-if="qrDialog.qrcodeUrl">
					<img class="qr-image" :src="qrImageSrc(qrDialog.qrcodeUrl)" alt="微信二维码" />
					<p class="qr-tip">{{ qrDialog.tip }}</p>
					<el-link
						class="qr-link"
						type="primary"
						:href="qrDialog.qrcodeUrl"
						target="_blank"
						underline="never"
					>
						新窗口打开二维码
					</el-link>
				</template>
				<el-empty v-else description="二维码获取中" :image-size="100" />
			</div>
			<template #footer>
				<el-button @click="stopQrPolling(); qrDialog.visible = false">关闭</el-button>
				<el-button type="primary" @click="refreshQr">刷新二维码</el-button>
			</template>
		</el-dialog>

		<channel-group-panel
			v-model="groupPanel.visible"
			:channel-id="groupPanel.channelId"
			:channel-name="groupPanel.channelName"
			:channel-type="groupPanel.channelType"
			:agent-id="groupPanel.agentId"
		/>
	</div>
</template>

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

import { computed, onMounted, reactive, ref } from 'vue';
import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
import { useBase } from '/$/base';
import { config } from '/@/config';
import type { AgentChannelInfo } from '../types/index.d';
import ChannelGroupPanel from '../components/channel-group-panel.vue';
import { useDbChannelValidation } from '../composables/useDbChannelValidation';

const { user } = useBase();

const loading = ref(false);
const saving = ref(false);
const formRef = ref<FormInstance>();
const list = ref<AgentChannelInfo[]>([]);
const allAgents = ref<Array<{ id: number; name: string; label?: string; toolsets?: string[] }>>([]);
// v4: 桌面操作 Agent 不过滤,显示所有 agent。
//      用户只需挑一个 multimodal model 的即可,toolset/路由系统在保存时自动 patch。
const desktopAgents = computed(() => allAgents.value);

const options = reactive({
	types: [
		{ value: 'weixin', label: '微信Bot（个人助手 · 仅私聊）' },
		{ value: 'weixin-db', label: '微信本地代理（群聊 · 需 Windows + PC 微信）' },
	],
	loginStatuses: [] as Array<{ value: string; label: string }>,
	agents: [] as Array<{ id: number; name: string; label: string; toolsets?: string[] }>
});

const filters = reactive({
	keyword: '',
	loginStatus: ''
});

const pagination = reactive({
	page: 1,
	size: 12,
	total: 0
});

const drawer = reactive({
	visible: false,
	isEdit: false,
	form: {
		id: null as number | null,
		name: '',
		type: 'weixin' as 'weixin' | 'weixin-db',
		agentId: null as number | null,
		description: '',
		botAlias: '',
		wxid: '',
		config: {} as Record<string, any>,
		credential: {} as Record<string, any>,
		weixinReply: {
			enabled: false,
			desktopAgentId: null as number | null,
			perGroupPerMinute: 3,
			dailyLimit: 100,
			safeMode: true,
			watermark: 'suffix' as 'none' | 'suffix' | 'zero-width',
		},
	}
});

const qrDialog = reactive({
	visible: false,
	channelId: 0,
	qrcodeUrl: '',
	tip: '请使用个人微信扫码（仅支持私聊场景）',
	loading: false,
	timer: 0 as number
});

const groupPanel = reactive({
	visible: false,
	channelId: null as number | null,
	channelName: '',
	agentId: null as number | null,
	channelType: 'weixin' as 'weixin' | 'weixin-db',
});

function handleManageGroups(item: AgentChannelInfo) {
	groupPanel.channelId = item.id ?? null;
	groupPanel.channelName = item.name;
	groupPanel.agentId = item.agentId ?? null;
	groupPanel.channelType = item.type;
	groupPanel.visible = true;
}

const rules = computed<FormRules>(() => ({
	name: [{ required: true, message: '请输入频道名称', trigger: 'blur' }],
	type: [{ required: true, message: '请选择频道类型', trigger: 'change' }],
	agentId: drawer.form.type === 'weixin'
		? [{ required: true, message: '请选择要绑定的 Agent', trigger: 'change' }]
		: [],
	botAlias: drawer.form.type === 'weixin'
		? [{ required: true, message: '微信Bot 渠道必须填写机器人昵称', trigger: 'blur' }]
		: [],
	wxid: drawer.form.type === 'weixin-db'
		? [{ required: true, message: 'weixin-db 渠道必须填写 wxid', trigger: 'blur' }]
		: [],
	'weixinReply.desktopAgentId': drawer.form.type === 'weixin-db' && drawer.form.weixinReply?.enabled
		? [
				{
					validator: (_rule: any, value: any, callback: any) => {
						// value 由 form 按 prop 路径自动注入(weixinReply.desktopAgentId)
						const v = value ?? drawer.form.weixinReply?.desktopAgentId;
						if (v === null || v === undefined || v === '') {
							return callback(new Error('启用自动回复时,必须选择桌面操作 Agent'));
						}
						if (v === drawer.form.agentId) {
							return callback(new Error('对话 Agent 与桌面操作 Agent 不能相同'));
						}
						callback();
					},
					trigger: 'change',
				},
			]
		: [],
}));

function authHeaders() {
	return {
		'Content-Type': 'application/json',
		Authorization: user.token || ''
	};
}

async function apiGet(url: string) {
	const resp = await fetch(`${config.baseUrl}${url}`, {
		headers: { Authorization: user.token || '' }
	});
	return resp.json();
}

async function apiPost(url: string, body: any) {
	const resp = await fetch(`${config.baseUrl}${url}`, {
		method: 'POST',
		headers: authHeaders(),
		body: JSON.stringify(body)
	});
	return resp.json();
}

async function loadOptions() {
	const data = await apiGet('/admin/netaclaw/agent_channel/options');
	if (data.code === 1000 && data.data) {
		const backendTypes = data.data.types || [];
		const merged = [...backendTypes];
		if (!merged.find((t: any) => t.value === 'weixin-db')) {
			merged.push({ value: 'weixin-db', label: '微信本地代理（群聊 · 需 Windows + PC 微信）' });
		}
		if (!merged.find((t: any) => t.value === 'weixin')) {
			merged.unshift({ value: 'weixin', label: '微信Bot（个人助手 · 仅私聊）' });
		}
		options.types = merged;
		options.loginStatuses = data.data.loginStatuses || [];
		options.agents = data.data.agents || [];
		// v4: 同步刷新 allAgents 以便桌面操作 Agent 下拉过滤
		refreshAllAgentsFromOptions();
	}
}

async function loadData() {
	loading.value = true;
	try {
		const data = await apiPost('/admin/netaclaw/agent_channel/page', {
			page: pagination.page,
			size: pagination.size,
			keyWord: filters.keyword,
			loginStatus: filters.loginStatus
		});
		if (data.code === 1000 && data.data) {
			list.value = data.data.list || [];
			pagination.total = data.data.pagination?.total || 0;
		}
	} catch {
		ElMessage.error('频道列表加载失败');
	} finally {
		loading.value = false;
	}
}

function resetForm() {
	drawer.form = {
		id: null,
		name: '',
		type: 'weixin',
		agentId: null,
		description: '',
		botAlias: '',
		wxid: '',
		config: {},
		credential: {},
		weixinReply: {
			enabled: false,
			desktopAgentId: null,
			perGroupPerMinute: 3,
			dailyLimit: 100,
			safeMode: true,
			watermark: 'suffix',
		},
	};
}

function handleAdd() {
	drawer.isEdit = false;
	resetForm();
	drawer.visible = true;
}

function handleEdit(item: AgentChannelInfo) {
	drawer.isEdit = true;
	const allowedTypes: Array<'weixin' | 'weixin-db'> = ['weixin', 'weixin-db'];
	const normalizedType: 'weixin' | 'weixin-db' =
		allowedTypes.includes(item.type as any) ? (item.type as 'weixin' | 'weixin-db') : 'weixin';
	if (item.type && !allowedTypes.includes(item.type as any)) {
		ElMessage.warning(`未知频道类型 "${item.type}",已退化为微信Bot`);
	}
	const wr = (item.config as any)?.weixinReply;
	drawer.form = {
		id: item.id || null,
		name: item.name,
		type: normalizedType,
		agentId: item.agentId || null,
		description: item.description || '',
		botAlias: (item.config as any)?.group?.botAlias ?? '',
		wxid: (item.credential as any)?.wxid ?? '',
		config: (item.config as Record<string, any>) || {},
		credential: (item.credential as Record<string, any>) || {},
		weixinReply: {
			enabled: wr?.enabled ?? false,
			desktopAgentId: wr?.desktopAgentId ?? null,
			perGroupPerMinute: wr?.perGroupPerMinute ?? 3,
			dailyLimit: wr?.dailyLimit ?? 100,
			safeMode: wr?.safeMode ?? true,
			watermark: wr?.watermark ?? 'suffix',
		},
	};
	drawer.visible = true;
}

async function handleSave() {
	const valid = await formRef.value?.validate().catch(() => false);
	if (!valid) return;

	// weixin-db 渠道:保存前查 wxid 唯一性(同一微信号只能绑一个 weixin-db 渠道)
	if (drawer.form.type === 'weixin-db') {
		const targetWxid = (drawer.form.wxid || '').trim();
		if (targetWxid) {
			const { findOtherDbChannelWithWxid } = useDbChannelValidation();
			const clash = await findOtherDbChannelWithWxid(targetWxid, drawer.form.id);
			if (clash) {
				ElMessage.error(`wxid ${targetWxid} 已绑定到频道 "${clash.name}",同一微信号只能绑一个 weixin-db 渠道`);
				return;
			}
		}
	}

	saving.value = true;
	try {
		const trimmedAlias = (drawer.form.botAlias || '').trim();
		const existingConfig = drawer.form.config || {};
		// 注意:微信Bot 不发送 credential,后端 normalizePayload 会保留 existing(包含 iLink token)
		//       weixin-db 把 wxid 合并到现有 credential 后整段写回(本地代理按 wxid 定位 PC 微信数据库)
		const payload: Record<string, any> = {
			id: drawer.form.id,
			name: drawer.form.name,
			type: drawer.form.type,
			agentId: drawer.form.type === 'weixin' ? drawer.form.agentId : null,
			description: drawer.form.description,
			config: {
				...existingConfig,
				...(drawer.form.type === 'weixin'
					? {
							group: {
								...((existingConfig as any)?.group || {}),
								botAlias: trimmedAlias,
							},
						}
					: {}),
			},
		};
		if (drawer.form.type === 'weixin-db') {
			payload.credential = {
				...(drawer.form.credential || {}),
				wxid: (drawer.form.wxid || '').trim(),
			};
			payload.config = {
				...(payload.config || {}),
				weixinReply: { ...drawer.form.weixinReply },
			};
		}

		const url = drawer.isEdit ? '/admin/netaclaw/agent_channel/update' : '/admin/netaclaw/agent_channel/add';
		const data = await apiPost(url, payload);
		if (data.code === 1000) {
			ElMessage.success(drawer.isEdit ? '频道已更新' : '频道已创建');
			drawer.visible = false;
			loadData();
			loadOptions();
		} else {
			ElMessage.error(data.message || '保存失败');
		}
	} catch {
		ElMessage.error('保存失败');
	} finally {
		saving.value = false;
	}
}

async function handleDelete(item: AgentChannelInfo) {
	try {
		const data = await apiPost('/admin/netaclaw/agent_channel/delete', { ids: [item.id] });
		if (data.code === 1000) {
			ElMessage.success('频道已删除');
			loadData();
		}
	} catch {
		ElMessage.error('删除失败');
	}
}

async function handleToggleStatus(item: AgentChannelInfo, val: string | number | boolean) {
	const enabled = val === true;
	try {
		const data = await apiPost('/admin/netaclaw/agent_channel/update', {
			id: item.id,
			status: enabled ? 1 : 0
		});
		if (data.code === 1000) {
			item.status = enabled ? 1 : 0;
			ElMessage.success(enabled ? '频道已启用' : '频道已禁用');
		}
	} catch {
		ElMessage.error('状态更新失败');
	}
}

async function handleDisconnect(item: AgentChannelInfo) {
	try {
		const data = await apiPost('/admin/netaclaw/agent_channel/disconnect', { id: item.id });
		if (data.code === 1000) {
			ElMessage.success('频道已断开');
			loadData();
		}
	} catch {
		ElMessage.error('断开失败');
	}
}

async function handleRestart(item: AgentChannelInfo) {
	try {
		const data = await apiPost('/admin/netaclaw/agent_channel/restart', { id: item.id });
		if (data.code === 1000) {
			ElMessage.success('已触发重连');
			loadData();
		}
	} catch {
		ElMessage.error('重连失败');
	}
}

async function handleClearSessions(item: AgentChannelInfo) {
	try {
		const data = await apiPost('/admin/netaclaw/agent_channel/clearSessions', { id: item.id });
		if (data.code === 1000) {
			const count = data.data?.cleared ?? 0;
			ElMessage.success(`已清空 ${count} 个微信会话`);
		}
	} catch {
		ElMessage.error('清空会话失败');
	}
}

function loginStatusLabel(status?: string) {
	if (status === 'unsupported_platform') return '非 Windows 环境不可用';
	return options.loginStatuses.find(item => item.value === status)?.label || status || '-';
}

function statusTagType(status?: string) {
	if (status === 'connected') return 'success';
	if (status === 'pending') return 'warning';
	if (status === 'error') return 'danger';
	if (status === 'unsupported_platform') return 'info';
	return 'info';
}

function qrImageSrc(url: string) {
	if (!url) return '';
	if (/^data:image\//.test(url)) return url;
	if (/\.(png|jpg|jpeg|gif|webp)(\?|$)/i.test(url)) return url;
	return `https://api.qrserver.com/v1/create-qr-code/?size=240x240&data=${encodeURIComponent(url)}`;
}

function agentLabel(item: AgentChannelInfo) {
	const agent = options.agents.find(v => v.id === item.agentId);
	return agent?.label || item.agentName || '-';
}

async function openQrDialog(item: AgentChannelInfo) {
	qrDialog.visible = true;
	qrDialog.channelId = item.id || 0;
	qrDialog.qrcodeUrl = '';
	qrDialog.tip = '请使用个人微信扫码（仅支持私聊场景）';
	await refreshQr();
}

function stopQrPolling() {
	if (qrDialog.timer) {
		window.clearInterval(qrDialog.timer);
		qrDialog.timer = 0;
	}
}

async function refreshQr() {
	if (!qrDialog.channelId) return;
	stopQrPolling();
	qrDialog.loading = true;
	try {
		const data = await apiPost('/admin/netaclaw/agent_channel/weixin/qr', { id: qrDialog.channelId });
		if (data.code === 1000) {
			qrDialog.qrcodeUrl = data.data.qrcodeUrl;
			qrDialog.tip = '请使用个人微信扫码登录，扫码后页面会自动确认登录状态';
			startQrPolling();
		} else {
			ElMessage.error(data.message || '二维码获取失败');
		}
	} catch {
		ElMessage.error('二维码获取失败');
	} finally {
		qrDialog.loading = false;
	}
}

function startQrPolling() {
	stopQrPolling();
	qrDialog.timer = window.setInterval(async () => {
		try {
			const data = await apiPost('/admin/netaclaw/agent_channel/weixin/qr/status', { id: qrDialog.channelId });
			if (data.code !== 1000) return;
			const status = data.data?.status;
			if (status === 'confirmed') {
				stopQrPolling();
				qrDialog.tip = '微信连接成功';
				ElMessage.success('微信连接成功');
				loadData();
				setTimeout(() => {
					qrDialog.visible = false;
				}, 800);
				return;
			}
			if (status === 'refresh') {
				qrDialog.qrcodeUrl = data.data.qrcodeUrl || qrDialog.qrcodeUrl;
				qrDialog.tip = '二维码已刷新，请重新扫码';
				return;
			}
			if (status === 'scaned') {
				qrDialog.tip = '已扫码，请在微信里确认登录';
				return;
			}
			if (status === 'expired') {
				stopQrPolling();
				qrDialog.tip = '二维码已过期，请刷新';
			}
		} catch {
			// ignore transient polling errors
		}
	}, 2000);
}

// v4: 复用 loadOptions 返回的 options.agents(后端已暴露 toolsets 字段)
function refreshAllAgentsFromOptions() {
	allAgents.value = (options.agents as any[]).map(a => ({
		id: a.id,
		name: a.name,
		label: a.label,
		toolsets: Array.isArray(a.toolsets) ? a.toolsets : [],
	}));
}

onMounted(async () => {
	await loadOptions();
	refreshAllAgentsFromOptions();
	await loadData();
});
</script>

<style lang="scss" scoped>
.channel-page {
	padding: 20px;
	display: flex;
	flex-direction: column;
	gap: 16px;
	min-height: 100%;
	background:
		radial-gradient(circle at top left, rgba(87, 181, 231, 0.12), transparent 32%),
		linear-gradient(180deg, rgba(8, 145, 178, 0.04), rgba(255, 255, 255, 0));

	&__header {
		display: flex;
		align-items: flex-start;
		justify-content: space-between;
		gap: 16px;
		padding: 18px 20px;
		border-radius: 16px;
		background: rgba(255, 255, 255, 0.92);
		border: 1px solid rgba(15, 23, 42, 0.08);
	}

	&__title {
		h2 {
			margin: 0;
			font-size: 22px;
			font-weight: 700;
			color: #0f172a;
		}

		p {
			margin: 8px 0 0;
			font-size: 13px;
			color: #475569;
			line-height: 1.6;
		}
	}

	&__actions {
		display: flex;
		align-items: center;
		gap: 10px;
		flex-wrap: wrap;
	}

	&__pagination {
		display: flex;
		justify-content: flex-end;
	}
}

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

.channel-card {
	display: flex;
	flex-direction: column;
	gap: 16px;
	padding: 18px;
	border-radius: 18px;
	background: rgba(255, 255, 255, 0.95);
	border: 1px solid rgba(15, 23, 42, 0.08);
	box-shadow: 0 14px 30px rgba(15, 23, 42, 0.06);

	&__top {
		display: flex;
		justify-content: space-between;
		align-items: flex-start;
		gap: 12px;
	}

	&__name {
		font-size: 18px;
		font-weight: 700;
		color: #0f172a;
	}

	&__meta {
		display: flex;
		gap: 8px;
		margin-top: 10px;
		flex-wrap: wrap;
	}

	&__body {
		display: grid;
		gap: 10px;
	}

	&__footer {
		display: flex;
		flex-wrap: wrap;
		gap: 4px;
		padding-top: 8px;
		border-top: 1px dashed rgba(15, 23, 42, 0.12);
	}
}

.info-row {
	display: grid;
	grid-template-columns: 88px 1fr;
	gap: 10px;
	font-size: 13px;
	line-height: 1.6;

	.label {
		color: #64748b;
	}

	.value {
		color: #0f172a;
		word-break: break-word;
	}

	.is-error {
		color: #dc2626;
	}
}

.qr-dialog {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	min-height: 280px;
	gap: 16px;
}

.qr-image {
	width: 220px;
	height: 220px;
	border-radius: 16px;
	border: 1px solid rgba(15, 23, 42, 0.08);
	background: #fff;
	object-fit: contain;
	padding: 10px;
	box-sizing: border-box;
}

.qr-tip {
	margin: 0;
	font-size: 13px;
	line-height: 1.6;
	color: #475569;
	text-align: center;
}

.qr-link {
	font-size: 13px;
}

.group-badge--inactive {
	opacity: 0.65;
}

.form-hint {
	margin-top: 4px;
	font-size: 12px;
	color: #8a9a90;
	line-height: 1.5;
}

@media (max-width: 900px) {
	.channel-page__header {
		flex-direction: column;
	}

	.channel-grid {
		grid-template-columns: 1fr;
	}
}
</style>
