import { mergeDistinctSenderIds } from "../../../../src/channels/pairing/preseed-allow-from.js";
import { beginAppRegistration, initAppRegistration, pollAppRegistration, printQrCode } from "../auth/app-registration.js";
import { confirm, input, select } from "@inquirer/prompts";
//#region extensions/feishu/src/adapters/onboard-cli.ts
/**
* Feishu interactive onboarding (CLI onboard) — {@link ChannelOnboardAdapter}.
*
* This configures the single-account layout under `channels.feishu.*`.
*/
function isFeishuConfigured(config) {
	const feishu = config.channels?.feishu;
	if (!feishu) return false;
	const appId = typeof feishu.appId === "string" ? feishu.appId.trim() : "";
	const appSecret = typeof feishu.appSecret === "string" ? feishu.appSecret.trim() : "";
	return feishu.enabled === true && Boolean(appId && appSecret);
}
function parseAllowlistRaw(raw) {
	if (!raw.trim()) return [];
	return raw.split(/[,\s\n]+/).map((s) => s.trim()).filter(Boolean).map((e) => {
		const num = parseInt(e, 10);
		return !isNaN(num) && String(num) === e ? num : e;
	});
}
async function configureFeishu(config) {
	console.log(`\n${"=".repeat(50)}`);
	console.log("📱 Feishu / Lark setup");
	console.log(`${"=".repeat(50)}\n`);
	const existing = config.channels?.feishu;
	const existingAppId = typeof existing?.appId === "string" ? existing.appId : "";
	const existingDomain = typeof existing?.domain === "string" ? existing.domain : "";
	if (existing?.enabled === true && existingAppId) {
		if (!await confirm({
			message: "A Feishu config already exists. Reconfigure it?",
			default: false
		})) return config;
	}
	const initialDomain = await select({
		message: "Feishu/Lark domain:",
		choices: [{
			value: "feishu",
			name: "feishu (open.feishu.cn)",
			description: "China / Feishu"
		}, {
			value: "lark",
			name: "lark (open.larksuite.com)",
			description: "International / Lark"
		}],
		default: existingDomain === "lark" ? "lark" : "feishu"
	});
	const useScanToCreate = await initAppRegistration(initialDomain) ? await confirm({
		message: "Create an app by scanning a QR code (recommended)?",
		default: true
	}) : false;
	let appId = "";
	let appSecret = "";
	let domain = initialDomain;
	let ownerOpenId;
	if (useScanToCreate) {
		console.log("\nScan this QR code with Feishu/Lark to create an app:\n");
		const begin = await beginAppRegistration(initialDomain);
		await printQrCode(begin.qrUrl);
		console.log("\nWaiting for confirmation...\n");
		const outcome = await pollAppRegistration({
			deviceCode: begin.deviceCode,
			intervalSec: begin.intervalSec,
			expireInSec: begin.expireInSec,
			initialDomain
		});
		if (outcome.status !== "success") console.log("Scan-to-create did not complete. Falling back to manual input.\n");
		else {
			appId = outcome.result.appId;
			appSecret = outcome.result.appSecret;
			domain = outcome.result.domain;
			ownerOpenId = outcome.result.openId;
			console.log(`✅ App created. Domain detected as "${domain}".\n`);
		}
	}
	if (!appId || !appSecret) {
		console.log("📝 Feishu app credentials (from Feishu Open Platform developer console):\n");
		appId = (await input({
			message: "App ID (cli_xxx):",
			default: existingAppId || void 0,
			validate: (v) => v.trim().length > 0 || "App ID cannot be empty"
		})).trim();
		appSecret = (await input({
			message: "App Secret:",
			validate: (v) => v.trim().length > 0 || "App Secret cannot be empty"
		})).trim();
		domain = initialDomain;
	}
	const connectionMode = await select({
		message: "Connection mode:",
		choices: [{
			value: "websocket",
			name: "websocket  [recommended]",
			description: "Socket Mode (persistent connection)"
		}, {
			value: "webhook",
			name: "webhook",
			description: "Local HTTP server receives events"
		}],
		default: "websocket"
	});
	let verificationToken;
	let encryptKey;
	let webhookHost;
	let webhookPort;
	let webhookPath;
	if (connectionMode === "webhook") {
		console.log("\n🪝 Webhook secrets (from Feishu event subscription settings):\n");
		verificationToken = (await input({
			message: "Verification Token:",
			validate: (v) => v.trim().length > 0 || "Verification Token cannot be empty"
		})).trim();
		encryptKey = (await input({
			message: "Encrypt Key:",
			validate: (v) => v.trim().length > 0 || "Encrypt Key cannot be empty"
		})).trim();
		webhookHost = (await input({
			message: "Webhook host:",
			default: typeof existing?.webhookHost === "string" ? existing.webhookHost : "127.0.0.1"
		})).trim();
		webhookPort = Number((await input({
			message: "Webhook port:",
			default: typeof existing?.webhookPort === "number" ? String(existing.webhookPort) : "3000"
		})).trim());
		webhookPath = (await input({
			message: "Webhook path:",
			default: typeof existing?.webhookPath === "string" ? existing.webhookPath : "/feishu/events"
		})).trim();
	}
	const dmPolicy = await select({
		message: "DM (private chat) policy:",
		choices: [
			{
				value: "open",
				name: "open  [default]",
				description: "Anyone can DM the bot after setup"
			},
			{
				value: "pairing",
				name: "pairing",
				description: "New users need `xopc channels pairing approve` (scanner pre-seeded after QR create)"
			},
			{
				value: "allowlist",
				name: "allowlist",
				description: "Only allowlisted users can DM"
			},
			{
				value: "disabled",
				name: "disabled",
				description: "Disable DMs"
			}
		],
		default: "open"
	});
	let allowFrom;
	if (dmPolicy === "allowlist") {
		const defaultAllow = ownerOpenId && (existing?.allowFrom == null || Array.isArray(existing.allowFrom) && existing.allowFrom.length === 0) ? ownerOpenId : "";
		allowFrom = parseAllowlistRaw(await input({
			message: "Allowed user open_id / union_id / numeric ids (comma-separated):",
			default: defaultAllow
		}) || defaultAllow);
	}
	const groupPolicy = await select({
		message: "Group chat policy:",
		choices: [
			{
				value: "allowlist",
				name: "allowlist  [recommended]",
				description: "Only allowlisted groups can use the bot"
			},
			{
				value: "open",
				name: "open",
				description: "All groups allowed"
			},
			{
				value: "disabled",
				name: "disabled",
				description: "Disable groups"
			}
		],
		default: "allowlist"
	});
	let groupAllowFrom;
	if (groupPolicy === "allowlist") groupAllowFrom = parseAllowlistRaw(await input({
		message: "Allowed group chat IDs (comma-separated, e.g. oc_xxx):",
		default: ""
	}));
	const requireMention = await confirm({
		message: "Require @mention in groups?",
		default: true
	});
	const renderMode = await select({
		message: "Default render mode:",
		choices: [
			{
				value: "auto",
				name: "auto",
				description: "Let xopc decide (default)"
			},
			{
				value: "raw",
				name: "raw",
				description: "Send plain text only"
			},
			{
				value: "card",
				name: "card",
				description: "Prefer interactive cards (CardKit streaming)"
			}
		],
		default: "auto"
	});
	const streaming = await confirm({
		message: "Enable streaming updates (Thinking… + incremental output)?",
		default: false
	});
	const reactionNotifications = await select({
		message: "Reaction notifications:",
		choices: [
			{
				value: "off",
				name: "off",
				description: "Disable reaction notifications"
			},
			{
				value: "own",
				name: "own  [recommended]",
				description: "Only notify reactions to bot messages"
			},
			{
				value: "all",
				name: "all",
				description: "Notify all reactions (noisy)"
			}
		],
		default: "own"
	});
	const enableFeishuTools = await select({
		message: "Enable Feishu tools (docs/wiki/drive/etc.)?",
		choices: [
			{
				value: "minimal",
				name: "minimal",
				description: "No extra tools (chat only)"
			},
			{
				value: "docs",
				name: "docs",
				description: "Enable doc/wiki/drive/scopes (common)"
			},
			{
				value: "full",
				name: "full",
				description: "Enable doc/wiki/drive/bitable/perm/scopes"
			}
		],
		default: "docs"
	});
	const tools = enableFeishuTools === "minimal" ? {
		doc: false,
		wiki: false,
		drive: false,
		perm: false,
		bitable: false,
		scopes: true
	} : enableFeishuTools === "docs" ? {
		doc: true,
		wiki: true,
		drive: true,
		perm: false,
		bitable: true,
		scopes: true
	} : {
		doc: true,
		wiki: true,
		drive: true,
		perm: true,
		bitable: true,
		scopes: true
	};
	const extras = ownerOpenId?.trim() && (dmPolicy === "pairing" || dmPolicy === "allowlist") ? [ownerOpenId.trim()] : [];
	const mergedAllowFrom = mergeDistinctSenderIds(allowFrom ?? existing?.allowFrom ?? [], extras);
	const nextFeishu = {
		...existing ?? {},
		enabled: true,
		appId,
		appSecret,
		domain,
		connectionMode,
		...connectionMode === "webhook" ? {
			verificationToken,
			encryptKey,
			webhookHost,
			webhookPort,
			webhookPath
		} : {},
		dmPolicy,
		groupPolicy,
		allowFrom: mergedAllowFrom,
		groupAllowFrom: groupAllowFrom ?? existing?.groupAllowFrom ?? [],
		requireMention,
		renderMode,
		streaming,
		reactionNotifications,
		actions: { reactions: true },
		tools,
		historyLimit: typeof existing?.historyLimit === "number" ? existing.historyLimit : 50,
		textChunkLimit: typeof existing?.textChunkLimit === "number" ? existing.textChunkLimit : 4e3
	};
	const newConfig = {
		...config,
		channels: {
			...config.channels,
			feishu: nextFeishu
		}
	};
	console.log("\n✅ Feishu configuration complete\n");
	return newConfig;
}
const feishuOnboardAdapter = {
	isConfigured: isFeishuConfigured,
	configure: configureFeishu
};
//#endregion
export { feishuOnboardAdapter };

//# sourceMappingURL=onboard-cli.js.map