<template>
	<cl-crud ref="Crud">
		<cl-row>
			<cl-refresh-btn />
			<el-button type="primary" @click="openAddDialog">{{ t('新增账号') }}</el-button>
			<cl-multi-delete-btn />
			<cl-flex1 />
			<cl-search-key :placeholder="t('搜索昵称、登录账号、sessionName')" />
		</cl-row>

		<cl-row>
			<cl-table ref="Table" />
		</cl-row>

		<cl-row>
			<cl-flex1 />
			<cl-pagination />
		</cl-row>

		<cl-upsert ref="Upsert" />

		<!-- 编辑 Dialog（自定义，支持 IP 模式切换） -->
		<el-dialog v-model="editDialogVisible" :title="t('编辑账号')" width="560px" destroy-on-close>
			<el-form ref="editFormRef" :model="editForm" :rules="editFormRules" label-width="120px">
				<el-form-item :label="t('账号昵称')" prop="name">
					<el-input v-model="editForm.name" />
				</el-form-item>
				<el-form-item :label="t('平台')" prop="platform">
					<el-select v-model="editForm.platform" style="width: 100%">
						<el-option v-for="(label, value) in PLATFORM_LABELS" :key="value" :label="label" :value="value" />
					</el-select>
				</el-form-item>
				<el-form-item :label="t('登录账号')" prop="loginAccount">
					<el-input v-model="editForm.loginAccount" :placeholder="t('登录后自动获取')" />
				</el-form-item>
				<el-form-item :label="t('执行 Agent')" prop="agentId">
					<el-select v-model="editForm.agentId" style="width: 100%" filterable clearable>
						<el-option v-for="a in agentList" :key="a.id" :label="a.label || a.name" :value="a.id" />
					</el-select>
				</el-form-item>
				<el-form-item :label="t('IP 模式')" prop="ipMode">
					<el-radio-group v-model="editForm.ipMode">
						<el-radio value="local">{{ t('本地（直连）') }}</el-radio>
						<el-radio value="third_party">{{ t('第三方独立 IP') }}</el-radio>
					</el-radio-group>
				</el-form-item>
				<el-form-item v-if="editForm.ipMode === 'third_party'" :label="t('选择 IP')" prop="proxyId">
					<el-select v-model="editForm.proxyId" style="width: 100%" filterable :loading="ipListLoading">
						<el-option
							v-for="ip in availableIpList"
							:key="ip.id"
							:label="`${ip.name} - ${ip.host}:${ip.port}${ip.city ? ' (' + ip.city + ')' : ''}`"
							:value="ip.id"
						/>
					</el-select>
				</el-form-item>
				<el-form-item label="SessionName">
					<el-input v-model="editForm.sessionName" disabled />
				</el-form-item>
			</el-form>
			<template #footer>
				<el-button @click="editDialogVisible = false">{{ t('取消') }}</el-button>
				<el-button type="primary" :loading="editSubmitting" @click="submitEditForm">{{ t('保存') }}</el-button>
			</template>
		</el-dialog>

		<!-- 新增账号 Dialog -->
		<el-dialog v-model="addDialogVisible" :title="t('新增账号')" width="540px" destroy-on-close>
			<el-form ref="addFormRef" :model="addForm" :rules="addFormRules" label-width="120px">
				<el-form-item :label="t('账号昵称')" prop="name">
					<el-input v-model="addForm.name" :placeholder="t('用于自己识别的备注名')" />
				</el-form-item>

				<el-form-item :label="t('平台')" prop="platform">
					<el-select v-model="addForm.platform" :placeholder="t('请选择平台')" style="width: 100%">
						<el-option v-for="(label, value) in PLATFORM_LABELS" :key="value" :label="label" :value="value" />
					</el-select>
				</el-form-item>

				<el-form-item :label="t('IP 模式')" prop="ipMode">
					<el-radio-group v-model="addForm.ipMode">
						<el-radio value="local">{{ t('本地（直连）') }}</el-radio>
						<el-radio value="third_party">{{ t('第三方独立 IP') }}</el-radio>
					</el-radio-group>
				</el-form-item>

				<el-form-item v-if="addForm.ipMode === 'third_party'" :label="t('选择 IP')" prop="proxyId">
					<el-select
						v-model="addForm.proxyId"
						:placeholder="t('请选择未绑定的 IP')"
						style="width: 100%"
						:loading="ipListLoading"
						filterable
					>
						<el-option
							v-for="ip in availableIpList"
							:key="ip.id"
							:label="`${ip.name} - ${ip.host}:${ip.port}${ip.city ? ' (' + ip.city + ')' : ''}`"
							:value="ip.id"
						/>
					</el-select>
				</el-form-item>

				<el-form-item :label="t('执行 Agent')" prop="agentId">
					<el-select
						v-model="addForm.agentId"
						:placeholder="t('选择哪个 Agent 执行账号管理（登录、运营等）')"
						style="width: 100%"
						:loading="agentListLoading"
						filterable
						clearable
					>
						<el-option
							v-for="a in agentList"
							:key="a.id"
							:label="a.label || a.name"
							:value="a.id"
						/>
					</el-select>
				</el-form-item>

				<el-form-item :label="t('SessionName')" prop="sessionName">
					<el-input
						v-model="addForm.sessionName"
						:placeholder="t('留空自动生成 platform-id（推荐）')"
					/>
					<div class="form-tip">{{ t('netabrowser-cli 用它定位 profile 目录，相同名字会自动恢复登录态') }}</div>
				</el-form-item>
			</el-form>

			<template #footer>
				<el-button @click="addDialogVisible = false">{{ t('取消') }}</el-button>
				<el-button type="primary" :loading="addSubmitting" @click="submitAddForm">{{ t('确认') }}</el-button>
			</template>
		</el-dialog>
	</cl-crud>
</template>

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

import { reactive, ref, onMounted, computed } from 'vue';
import { useCrud, useTable, useUpsert } from '@cool-vue/crud';
import { useCool } from '/@/cool';
import { useI18n } from 'vue-i18n';
import { ElMessage, ElMessageBox } from 'element-plus';
import type { FormInstance, FormRules } from 'element-plus';

const { service } = useCool();
const { t } = useI18n();

const PLATFORM_LABELS: Record<string, string> = {
	taobao: '淘宝',
	xiaohongshu: '小红书',
	douyin: '抖音',
	weibo: '微博',
	zhihu: '知乎',
	wechat: '微信',
};

// =================== 新增账号 Dialog ===================
const addDialogVisible = ref(false);
const addSubmitting = ref(false);
const addFormRef = ref<FormInstance>();

const availableIpList = ref<any[]>([]);
const ipListLoading = ref(false);
const agentList = ref<any[]>([]);
const agentListLoading = ref(false);

// id → 显示名 映射（label 优先，否则 name）
const agentNameMap = computed<Record<number, string>>(() => {
	const m: Record<number, string> = {};
	for (const a of agentList.value) {
		m[a.id] = a.label || a.name || `#${a.id}`;
	}
	return m;
});

// 格式化 cookie 过期时间：显示日期 + 剩余天数
function formatCookieExpires(row: any): string {
	if (!row.cookieExpiresAt) return '-';
	const ts = new Date(row.cookieExpiresAt).getTime();
	if (Number.isNaN(ts)) return '-';
	const days = Math.ceil((ts - Date.now()) / 86400000);
	const dateStr = new Date(ts).toLocaleString('zh-CN', { hour12: false });
	if (days <= 0) return `${dateStr} ⚠️ 已过期`;
	if (days <= 7) return `${dateStr} (剩 ${days}天)`;
	return `${dateStr} (剩 ${days}天)`;
}

interface AddForm {
	name: string;
	platform: string;
	ipMode: 'local' | 'third_party';
	proxyId: number | null;
	agentId: number | null;
	sessionName: string;
}

const addForm = reactive<AddForm>({
	name: '',
	platform: '',
	ipMode: 'local',
	proxyId: null,
	agentId: null,
	sessionName: '',
});

const addFormRules: FormRules = {
	name: [{ required: true, message: t('请输入账号昵称'), trigger: 'blur' }],
	platform: [{ required: true, message: t('请选择平台'), trigger: 'change' }],
	ipMode: [{ required: true, message: t('请选择 IP 模式'), trigger: 'change' }],
	proxyId: [
		{
			validator: (_rule, value, cb) => {
				if (addForm.ipMode === 'third_party' && !value) {
					cb(new Error(t('选择第三方 IP 时必须指定一个 IP')));
				} else cb();
			},
			trigger: 'change',
		},
	],
};

// 全部 IP 列表（用于表格显示 id → name 映射，含已绑定的）
const allIpList = ref<any[]>([]);
const ipNameMap = computed<Record<number, string>>(() => {
	const m: Record<number, string> = {};
	for (const ip of allIpList.value) {
		// 显示格式："name | host:port (city)"
		const cityPart = ip.city ? ` (${ip.city})` : '';
		m[ip.id] = `${ip.name || ip.host} | ${ip.host}:${ip.port}${cityPart}`;
	}
	return m;
});

async function loadAllIps() {
	try {
		const res: any = await service.geo.proxy_ip.list({});
		allIpList.value = Array.isArray(res) ? res : (res?.list ?? []);
	} catch (e: any) {
		console.warn('[geo-accounts] load all ips failed:', e?.message);
	}
}

async function loadAvailableIps(includeIpId?: number | null) {
	ipListLoading.value = true;
	try {
		const res: any = await service.geo.proxy_ip.list({});
		const all: any[] = Array.isArray(res) ? res : (res?.list ?? []);
		availableIpList.value = all.filter(ip =>
			ip.status !== 'deleted' && (!ip.bindAccountId || ip.id === includeIpId)
		);
	} catch (e: any) {
		ElMessage.error(e?.message || t('加载 IP 列表失败'));
	} finally {
		ipListLoading.value = false;
	}
}

async function loadAgents() {
	agentListLoading.value = true;
	try {
		// 用 options 接口拿已发布的 agent 列表（专为下拉框设计）
		const res: any = await service.request({
			url: '/admin/netaclaw/agent/options',
			method: 'POST',
		});
		agentList.value = Array.isArray(res) ? res : (res?.list ?? res ?? []);
	} catch (e: any) {
		// 拉不到也不阻塞，agent 是可选项
		console.warn('[geo-accounts] load agents failed:', e?.message);
		agentList.value = [];
	} finally {
		agentListLoading.value = false;
	}
}

function openAddDialog() {
	Object.assign(addForm, {
		name: '',
		platform: '',
		ipMode: 'local',
		proxyId: null,
		agentId: null,
		sessionName: '',
	});
	addDialogVisible.value = true;
	loadAvailableIps();
	loadAgents();
}

async function submitAddForm() {
	if (!addFormRef.value) return;
	await addFormRef.value.validate(async (valid) => {
		if (!valid) return;
		addSubmitting.value = true;
		try {
			await service.request({
				url: '/admin/geo/account/add',
				method: 'POST',
				data: {
					name: addForm.name,
					platform: addForm.platform,
					proxyId: addForm.ipMode === 'third_party' ? addForm.proxyId : undefined,
					agentId: addForm.agentId || undefined,
					sessionName: addForm.sessionName?.trim() || undefined,
				},
			});
			ElMessage.success(t('账号创建成功'));
			addDialogVisible.value = false;
			Crud.value?.refresh();
		} catch (e: any) {
			ElMessage.error(e?.message || t('创建失败'));
		} finally {
			addSubmitting.value = false;
		}
	});
}

// =================== 启动登录 ===================
async function launchAccount(row: any) {
	try {
		await service.request({
			url: '/admin/geo/account/launch',
			method: 'POST',
			data: { id: row.id },
		});
		ElMessageBox.alert(
			t('浏览器已打开（sessionName: {s}），请在窗口中完成登录后点「抓 Cookie」按钮保存登录态。', { s: row.sessionName }),
			t('请在浏览器中登录'),
			{ type: 'info', confirmButtonText: t('知道了') },
		);
		Crud.value?.refresh();
	} catch (e: any) {
		ElMessage.error(e?.message || t('启动失败'));
	}
}

async function captureCookies(row: any) {
	try {
		const res: any = await service.request({
			url: '/admin/geo/account/captureCookies',
			method: 'POST',
			data: { id: row.id },
		});
		const captured: number = res?.captured ?? 0;
		if (captured === 0) {
			ElMessage.warning(t('未捕获到 Cookie，请先在浏览器中完成登录'));
		} else {
			ElMessage.success(`成功抓取 ${captured} 条 Cookie`);
			Crud.value?.refresh();
		}
	} catch (e: any) {
		ElMessage.error(e?.message || t('抓取失败'));
	}
}

async function closeAccount(row: any) {
	try {
		await service.request({
			url: '/admin/geo/account/close',
			method: 'POST',
			data: { id: row.id },
		});
		ElMessage.success(t('已关闭浏览器'));
	} catch (e: any) {
		ElMessage.error(e?.message || t('关闭失败'));
	}
}

async function resetAccount(row: any) {
	try {
		await ElMessageBox.confirm(
			t('重置会清空 cookie + 生成新 sessionName + 新指纹 + 删除浏览器 profile 目录。下次启动等于全新设备。IP 绑定不变。确认重置？'),
			t('重置确认'),
			{ type: 'warning', confirmButtonText: t('确认重置'), cancelButtonText: t('取消') },
		);
		await service.request({
			url: '/admin/geo/account/resetSession',
			method: 'POST',
			data: { id: row.id },
		});
		ElMessage.success(t('已重置，下次启动是全新设备'));
		Crud.value?.refresh();
	} catch (e: any) {
		if (e === 'cancel' || e === 'close') return;
		ElMessage.error(e?.message || t('重置失败'));
	}
}

async function deleteAccount(row: any) {
	try {
		await ElMessageBox.confirm(
			t('确定要删除账号「{name}」吗？登录态会丢失。', { name: row.name }),
			t('删除确认'),
			{ type: 'warning', confirmButtonText: t('删除'), cancelButtonText: t('取消') },
		);
		await service.request({
			url: '/admin/geo/account/deleteAccount',
			method: 'POST',
			data: { id: row.id },
		});
		ElMessage.success(t('删除成功'));
		Crud.value?.refresh();
	} catch (e: any) {
		if (e === 'cancel' || e === 'close') return;
		ElMessage.error(e?.message || t('删除失败'));
	}
}

// =================== 编辑 Dialog ===================
const editDialogVisible = ref(false);
const editSubmitting = ref(false);
const editFormRef = ref<FormInstance>();
const editForm = reactive<{
	id: number | null;
	name: string;
	platform: string;
	loginAccount: string;
	agentId: number | null;
	ipMode: 'local' | 'third_party';
	proxyId: number | null;
	sessionName: string;
}>({
	id: null,
	name: '',
	platform: '',
	loginAccount: '',
	agentId: null,
	ipMode: 'local',
	proxyId: null,
	sessionName: '',
});

const editFormRules: FormRules = {
	name: [{ required: true, message: t('请输入账号昵称'), trigger: 'blur' }],
	platform: [{ required: true, message: t('请选择平台'), trigger: 'change' }],
	proxyId: [
		{
			validator: (_r, v, cb) => {
				if (editForm.ipMode === 'third_party' && !v) cb(new Error(t('请选择 IP')));
				else cb();
			},
			trigger: 'change',
		},
	],
};

function openEditDialog(row: any) {
	Object.assign(editForm, {
		id: row.id,
		name: row.name || '',
		platform: row.platform || '',
		loginAccount: row.loginAccount || '',
		agentId: row.agentId || null,
		ipMode: row.proxyId ? 'third_party' : 'local',
		proxyId: row.proxyId || null,
		sessionName: row.sessionName || '',
	});
	(editForm as any).__originalProxyId = row.proxyId || null;
	editDialogVisible.value = true;
	loadAvailableIps(row.proxyId);  // 包含当前账号已绑定的 IP
}

async function submitEditForm() {
	if (!editFormRef.value || !editForm.id) return;
	await editFormRef.value.validate(async (valid) => {
		if (!valid) return;

		// 检测 IP 是否变更
		const newProxyId = editForm.ipMode === 'third_party' ? editForm.proxyId : null;
		const oldProxyId = (editForm as any).__originalProxyId ?? null;
		const ipChanged = (newProxyId ?? null) !== (oldProxyId ?? null);

		// IP 变了：要求确认（会清登录态）
		if (ipChanged) {
			try {
				await ElMessageBox.confirm(
					t('IP 变更会重置 sessionName + 清空 cookie + 关闭浏览器。这是养号必须的安全操作（同一账号变 IP 不变 cookie 会被风控判异常）。确认继续？'),
					t('IP 变更确认'),
					{ type: 'warning', confirmButtonText: t('确认变更'), cancelButtonText: t('取消') },
				);
			} catch {
				return; // 用户取消
			}
		}

		editSubmitting.value = true;
		try {
			// 1. 更新基础字段
			await service.geo.account.update({
				id: editForm.id,
				name: editForm.name,
				platform: editForm.platform,
				loginAccount: editForm.loginAccount || null,
				agentId: editForm.agentId || null,
			});
			// 2. 切换 IP 模式（IP 变了才调）
			if (ipChanged) {
				await service.request({
					url: '/admin/geo/account/setProxy',
					method: 'POST',
					data: { id: editForm.id, proxyId: newProxyId },
				});
				ElMessage.success(t('保存成功，IP 已更换，需要重新登录'));
			} else {
				ElMessage.success(t('保存成功'));
			}
			editDialogVisible.value = false;
			Crud.value?.refresh();
		} catch (e: any) {
			ElMessage.error(e?.message || t('保存失败'));
		} finally {
			editSubmitting.value = false;
		}
	});
}

const Table = useTable({
	contextMenu: ['refresh', 'edit', 'delete'],
	columns: [
		{ type: 'selection' },
		{ label: 'ID', prop: 'id', width: 60 },
		{ label: t('昵称'), prop: 'name', minWidth: 120, showOverflowTooltip: true },
		{
			label: t('平台'),
			prop: 'platform',
			minWidth: 90,
			formatter: (row) => PLATFORM_LABELS[row.platform] || row.platform || '-',
		},
		{ label: t('登录账号'), prop: 'loginAccount', minWidth: 130, showOverflowTooltip: true },
		{ label: 'SessionName', prop: 'sessionName', minWidth: 150, showOverflowTooltip: true },
		{
			label: t('登录状态'),
			prop: 'loginStatus',
			minWidth: 100,
			formatter(row) {
				const map: Record<string, string> = {
					never: '未登录',
					logged_in: '已登录',
					expired: '已过期',
					banned: '已封禁',
					deleted: '已删除',
				};
				return map[row.loginStatus] || row.loginStatus || '-';
			},
		},
		{ label: t('IP'), prop: 'proxyId', minWidth: 220, showOverflowTooltip: true, formatter: (row) => row.proxyId ? (ipNameMap.value[row.proxyId] || `#${row.proxyId}`) : t('本地') },
		{ label: 'Agent', prop: 'agentId', minWidth: 110, formatter: (row) => row.agentId ? (agentNameMap.value[row.agentId] || `#${row.agentId}`) : '-' },
		{ label: t('Cookie 过期'), prop: 'cookieExpiresAt', minWidth: 160, sortable: 'custom', formatter: formatCookieExpires },
		{
			type: 'op',
			width: 280,
			buttons: [
				{ label: t('启动登录'), type: 'primary', onClick: ({ scope }) => launchAccount(scope.row) },
				{ label: t('抓 Cookie'), type: 'success', onClick: ({ scope }) => captureCookies(scope.row) },
				{ label: t('编辑'), onClick: ({ scope }) => openEditDialog(scope.row) },
				{ label: t('关闭'), onClick: ({ scope }) => closeAccount(scope.row) },
				{ label: t('重置'), type: 'warning', onClick: ({ scope }) => resetAccount(scope.row) },
				{ label: t('删除'), type: 'danger', onClick: ({ scope }) => deleteAccount(scope.row) },
			],
		},
	],
});

const Crud = useCrud(
	{ service: service.geo.account },
	(app) => {
		app.refresh();
	}
);

// 进入页面时预加载 agent 列表 + IP 列表，用于表格显示名字
onMounted(() => {
	loadAgents();
	loadAllIps();
});
</script>

<style lang="scss" scoped>
.form-tip {
	font-size: 12px;
	color: #909399;
	line-height: 1.4;
	margin-top: 2px;
}
</style>
