<template>
	<el-drawer v-model="visible" :title="`群聊管理 · ${channelName}`" size="720px" @opened="loadList">
		<div class="group-panel" v-loading="loading">
			<div class="group-panel__header">
				<div class="group-panel__stats">
					已添加监管 {{ list.length }} 个群 · 已启用 {{ enabledCount }}
				</div>
				<div class="group-panel__actions-top">
					<el-button size="small" @click="loadList">刷新</el-button>
					<el-button size="small" type="primary" @click="openAddDialog">+ 添加群</el-button>
				</div>
			</div>

			<el-alert
				type="info"
				:closable="false"
				show-icon
				title="本地代理模式:请在下方手动添加要监管的群,群名必须与 PC 微信中显示的群名完全一致。"
			/>

			<div v-if="list.length === 0 && !loading" class="group-panel__empty">
				暂无监管的群聊。点击右上角"+ 添加群"开始。
			</div>

			<div v-for="group in visibleList" :key="group.id" class="group-card">
				<div class="group-card__top">
					<div class="group-card__name">{{ group.roomName || group.roomId }}</div>
				</div>
				<div class="group-card__meta">
					<span v-if="group.roomId">roomId: {{ group.roomId }}</span>
					<span v-if="group.firstSeenAt">首次发现 {{ formatTime(group.firstSeenAt) }}</span>
					<span v-if="group.lastSeenAt">最近消息 {{ formatTime(group.lastSeenAt) }}</span>
					<span v-if="group.lastActiveAt">最近回复 {{ formatTime(group.lastActiveAt) }}</span>
				</div>

				<div class="group-card__form">
					<div class="group-card__form-row">
						<label>状态</label>
						<el-switch
							:model-value="group.status === 1"
							:active-value="true"
							:inactive-value="false"
							@change="(v) => handleToggle(group, v as boolean)"
						/>
						<span class="group-card__status-hint">{{ group.status === 1 ? '启用中' : '已禁用' }}</span>
					</div>

					<div class="group-card__form-row">
						<label>触发策略</label>
						<el-radio-group v-model="group._pendingTrigger.mode">
							<el-radio value="at_mention">@机器人</el-radio>
							<el-radio value="all">所有消息</el-radio>
						</el-radio-group>
					</div>

					<template v-if="props.channelType === 'weixin-db' && group.status === 1">
						<div class="group-card__form-row">
							<label>绑定 Agent</label>
							<el-select
								v-model="group._pendingBoundAgentId"
								placeholder="请选择 Agent"
								style="width: 280px"
							>
								<el-option
									v-for="agent in agentOptions"
									:key="agent.id"
									:label="agent.label"
									:value="agent.id"
								/>
							</el-select>
						</div>
						<div class="group-card__form-row">
							<label>回复身份</label>
							<el-radio-group v-model="group._pendingIdentity">
								<el-radio value="silent">隐形</el-radio>
								<el-radio value="ai_prefix">【AI 助手】前缀</el-radio>
							</el-radio-group>
						</div>
					</template>

					<div class="group-card__actions">
						<el-button
							size="small"
							:loading="group._syncing"
							@click="handleSync(group)"
						>
							{{ group._syncing ? '同步中...' : '同步聊天记录' }}
						</el-button>
						<el-button size="small" @click="jumpToChat(group)">查看对话记录</el-button>
						<el-button size="small" type="primary" @click="handleSavePolicy(group)">保存策略</el-button>
						<el-button size="small" type="danger" link @click="handleDelete(group)">删除</el-button>
					</div>
				</div>
			</div>

			<el-alert
				type="info"
				:closable="false"
				title="📌 禁用后不再处理该群消息;删除后本地代理不再读取该群。如需让 bot 离开群,请在手机微信中移除。"
			/>
		</div>

		<el-dialog v-model="addDialog.visible" title="添加群聊" width="420px">
			<el-form :model="addDialog.form" label-width="80px">
				<el-form-item label="群名" required>
					<el-input
						v-model="addDialog.form.roomName"
						placeholder="必须与 PC 微信中显示的群名完全一致"
						clearable
					/>
				</el-form-item>
				<el-form-item label="触发策略">
					<el-radio-group v-model="addDialog.form.triggerMode">
						<el-radio value="at_mention">@机器人</el-radio>
						<el-radio value="all">所有消息</el-radio>
					</el-radio-group>
				</el-form-item>
				<template v-if="props.channelType === 'weixin-db'">
					<el-form-item label="绑定 Agent" required>
						<el-select
							v-model="addDialog.form.boundAgentId"
							filterable
							placeholder="请选择 Agent"
							style="width: 100%"
						>
							<el-option
								v-for="agent in agentOptions"
								:key="agent.id"
								:label="agent.label"
								:value="agent.id"
							/>
						</el-select>
					</el-form-item>
					<el-form-item label="回复身份" required>
						<el-radio-group v-model="addDialog.form.replyIdentity">
							<el-radio value="silent">隐形</el-radio>
							<el-radio value="ai_prefix">【AI 助手】前缀</el-radio>
						</el-radio-group>
					</el-form-item>
				</template>
			</el-form>
			<template #footer>
				<el-button @click="addDialog.visible = false">取消</el-button>
				<el-button type="primary" :loading="addDialog.saving" @click="handleAdd">添加</el-button>
			</template>
		</el-dialog>
	</el-drawer>
</template>

<script setup lang="ts">
import { ref, computed, reactive, watch } from 'vue';
import { useRouter } from 'vue-router';
import { ElMessage, ElMessageBox } from 'element-plus';
import { useBase } from '/$/base';
import { config } from '/@/config';

interface GroupItem {
	id: number;
	channelId: number;
	roomId: string;
	roomName: string | null;
	status: 0 | 1;
	triggerMode: string;
	triggerPrefix: string | null;
	boundAgentId: number | null;
	replyIdentityOverride: 'silent' | 'ai_prefix' | null;
	firstSeenAt: string | null;
	lastSeenAt: string | null;
	lastActiveAt: string | null;
	_pendingTrigger: { mode: 'at_mention' | 'all' };
	_pendingBoundAgentId: number | null;
	_pendingIdentity: 'silent' | 'ai_prefix';
	_syncing?: boolean;
}

function normalizeTriggerMode(m: string): 'at_mention' | 'all' {
	if (m === 'at_mention' || m === 'all') return m;
	return 'at_mention'; // prefix / 未知值 fallback
}

const props = defineProps<{
	modelValue: boolean;
	channelId: number | null;
	channelName: string;
	channelType: 'weixin' | 'weixin-db';
	agentId: number | null;
}>();

const emit = defineEmits<{
	(e: 'update:modelValue', value: boolean): void;
}>();

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

const visible = computed({
	get: () => props.modelValue,
	set: (val) => emit('update:modelValue', val),
});

const list = ref<GroupItem[]>([]);
const loading = ref(false);
const agentOptions = ref<Array<{ id: number; label: string }>>([]);

const addDialog = reactive({
	visible: false,
	saving: false,
	form: {
		roomName: '',
		triggerMode: 'at_mention' as 'at_mention' | 'all',
		boundAgentId: null as number | null,
		replyIdentity: 'silent' as 'silent' | 'ai_prefix',
	},
});

async function loadAgentOptions() {
	try {
		const data = await apiGet('/admin/netaclaw/agent_channel/options');
		if (data.code === 1000) {
			const agents = data.data?.agents ?? [];
			agentOptions.value = agents.map((a: any) => ({
				id: a.id,
				label: a.label || a.name,
			}));
		}
	} catch {
		// 静默失败,下拉为空
	}
}

const enabledCount = computed(() => list.value.filter(g => g.status === 1).length);

// 只有 0 / 1 两种 status,全部展示
const visibleList = computed(() => list.value);

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();
}

function formatTime(value: string | null): string {
	if (!value) return '-';
	try {
		return new Date(value).toLocaleString('zh-CN', { hour12: false });
	} catch {
		return value;
	}
}

async function loadList() {
	if (!props.channelId) return;
	loading.value = true;
	try {
		const data = await apiPost('/admin/netaclaw/agent_channel_group/list', {
			channelId: props.channelId,
		});
		if (data.code === 1000) {
			list.value = (data.data as any[]).map(item => ({
				...item,
				status: (item.status === 1 ? 1 : 0) as 0 | 1,
				boundAgentId: item.boundAgentId ?? null,
				replyIdentityOverride: item.replyIdentityOverride ?? null,
				_pendingTrigger: {
					mode: normalizeTriggerMode(item.triggerMode || 'at_mention'),
				},
				_pendingBoundAgentId: item.boundAgentId ?? null,
				_pendingIdentity: item.replyIdentityOverride ?? 'silent',
			}));
		}
	} finally {
		loading.value = false;
	}
}

function openAddDialog() {
	addDialog.form.roomName = '';
	addDialog.form.triggerMode = 'at_mention';
	addDialog.form.boundAgentId = null;
	addDialog.form.replyIdentity = 'silent';
	addDialog.visible = true;
}

async function handleAdd() {
	const name = addDialog.form.roomName.trim();
	if (!name) {
		ElMessage.warning('请输入群名');
		return;
	}
	if (!props.channelId) {
		ElMessage.error('渠道未就绪');
		return;
	}
	if (props.channelType === 'weixin-db' && !addDialog.form.boundAgentId) {
		ElMessage.warning('请选择绑定 Agent');
		return;
	}
	addDialog.saving = true;
	try {
		const resp = await apiPost('/admin/netaclaw/agent_channel_group/add', {
			channelId: props.channelId,
			roomName: name,
			triggerMode: addDialog.form.triggerMode,
			agentId: props.channelType === 'weixin-db' ? addDialog.form.boundAgentId : undefined,
			replyIdentity: props.channelType === 'weixin-db' ? addDialog.form.replyIdentity : undefined,
		});
		if (resp.code !== 1000) {
			ElMessage.error(resp.message || '添加失败');
			return;
		}
		if (resp.data && resp.data.created === false) {
			ElMessage.info('该群已添加');
		} else {
			ElMessage.success('已添加');
		}
		addDialog.visible = false;
		addDialog.form.roomName = '';
		addDialog.form.boundAgentId = null;
		addDialog.form.replyIdentity = 'silent';
		await loadList();
	} finally {
		addDialog.saving = false;
	}
}

async function handleToggle(group: GroupItem, on: boolean) {
	const status: 0 | 1 = on ? 1 : 0;
	const data = await apiPost('/admin/netaclaw/agent_channel_group/toggle', {
		id: group.id, status,
	});
	if (data.code === 1000) {
		group.status = status;
		ElMessage.success(on ? '已启用' : '已禁用');
	} else {
		ElMessage.error(data.message || '操作失败');
	}
}

async function handleDelete(group: GroupItem) {
	try {
		await ElMessageBox.confirm(
			`确定移除群 "${group.roomName || group.roomId}" 的监管?`,
			'确认删除',
			{ type: 'warning', confirmButtonText: '删除', cancelButtonText: '取消' },
		);
	} catch {
		return; // 用户取消
	}
	const resp = await apiPost('/admin/netaclaw/agent_channel_group/delete', { ids: [group.id] });
	if (resp.code !== 1000) {
		ElMessage.error(resp.message || '删除失败');
		return;
	}
	ElMessage.success('已移除');
	await loadList();
}

async function handleSavePolicy(group: GroupItem) {
	// 1. 触发策略(通用)
	const mode = normalizeTriggerMode(group._pendingTrigger.mode);
	const r1 = await apiPost('/admin/netaclaw/agent_channel_group/updatePolicy', {
		id: group.id,
		triggerMode: mode,
	});
	if (r1.code !== 1000) {
		ElMessage.error(r1.message || '保存触发策略失败');
		return;
	}
	group.triggerMode = mode;
	group.triggerPrefix = null;

	// 2 + 3. weixin-db 渠道:绑定 agent + 回复身份
	if (props.channelType === 'weixin-db') {
		if (!group._pendingBoundAgentId) {
			ElMessage.warning('请选择绑定 Agent');
			return;
		}
		const r2 = await apiPost('/admin/netaclaw/agent_channel_group/setBoundAgent', {
			id: group.id,
			agentId: group._pendingBoundAgentId,
		});
		if (r2.code !== 1000) {
			ElMessage.error(r2.message || '保存绑定 Agent 失败');
			return;
		}
		group.boundAgentId = group._pendingBoundAgentId;

		const r3 = await apiPost('/admin/netaclaw/agent_channel_group/setReplyIdentity', {
			id: group.id,
			value: group._pendingIdentity,
		});
		if (r3.code !== 1000) {
			ElMessage.error(r3.message || '保存回复身份失败');
			return;
		}
		group.replyIdentityOverride = group._pendingIdentity;
	}

	ElMessage.success('已保存');
}

async function handleSync(group: GroupItem) {
	if (group._syncing) return;
	group._syncing = true;
	try {
		const resp = await apiPost('/admin/netaclaw/agent_channel_group/sync', { groupId: group.id });
		if (resp.code !== 1000) {
			ElMessage.error(resp.message || '同步失败');
			return;
		}
		const { newCount, totalCount, durationMs } = resp.data as {
			newCount: number; totalCount: number; durationMs: number;
		};
		ElMessage.success(`已同步 ${newCount} 条新消息(总计 ${totalCount} 条,${(durationMs / 1000).toFixed(1)}s)`);
	} catch (err: any) {
		ElMessage.error(err?.message || '同步失败');
	} finally {
		group._syncing = false;
	}
}

function jumpToChat(group: GroupItem) {
	const targetAgentId = props.channelType === 'weixin-db'
		? (group.boundAgentId ?? group._pendingBoundAgentId)
		: props.agentId;
	if (!targetAgentId) {
		ElMessage.warning('该群未绑定 Agent,无法跳转');
		return;
	}
	const sessionId = `channel:${group.channelId}:weixin:group:${group.roomId}`;
	router.push({ path: '/agent/chat', query: { sessionId, agentId: String(targetAgentId) } });
}

watch(visible, (v) => {
	if (v) {
		void loadList();
		void loadAgentOptions();
	}
});
</script>

<style scoped>
.group-panel { display: flex; flex-direction: column; gap: 16px; padding: 8px; }
.group-panel__header { display: flex; justify-content: space-between; align-items: center; }
.group-panel__stats { font-size: 14px; color: #333; }
.group-panel__actions-top { display: flex; gap: 8px; }
.group-panel__empty { padding: 24px; text-align: center; color: #999; border: 1px dashed #ddd; border-radius: 4px; }
.group-card { border: 1px solid #eee; border-radius: 8px; padding: 14px; background: #fafafa; }
.group-card__top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.group-card__name { font-weight: 600; }
.group-card__meta { color: #666; font-size: 12px; display: flex; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
.group-card__form { display: flex; flex-direction: column; gap: 10px; }
.group-card__form label { font-size: 14px; color: #333; min-width: 72px; }
.group-card__form-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.group-card__status-hint { font-size: 12px; color: #666; }
.group-card__actions { display: flex; gap: 8px; margin-top: 4px; }
</style>
