//#region extensions/feishu/src/auth/app-registration.ts
const FEISHU_ACCOUNTS_URL = "https://accounts.feishu.cn";
const LARK_ACCOUNTS_URL = "https://accounts.larksuite.com";
const REGISTRATION_PATH = "/oauth/v1/app/registration";
const REQUEST_TIMEOUT_MS = 1e4;
function accountsBaseUrl(domain) {
	return domain === "lark" ? LARK_ACCOUNTS_URL : FEISHU_ACCOUNTS_URL;
}
async function postRegistration(baseUrl, body) {
	return await (await fetch(`${baseUrl}${REGISTRATION_PATH}`, {
		method: "POST",
		headers: { "Content-Type": "application/x-www-form-urlencoded" },
		body: new URLSearchParams(body).toString(),
		signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
	})).json();
}
/**
* Check if the Feishu/Lark app registration endpoint supports scan-to-create.
*/
async function initAppRegistration(domain) {
	try {
		const result = await postRegistration(accountsBaseUrl(domain), { action: "init" });
		return Boolean(result.supported_auth_methods?.includes("client_secret"));
	} catch {
		return false;
	}
}
/**
* Start the device-code flow and return a QR URL for the user to scan.
*/
async function beginAppRegistration(domain) {
	const result = await postRegistration(accountsBaseUrl(domain), {
		action: "begin",
		archetype: "PersonalAgent",
		auth_method: "client_secret",
		request_user_info: "open_id"
	});
	const qrUrl = new URL(result.verification_uri_complete);
	qrUrl.searchParams.set("from", "xopc_onboard");
	qrUrl.searchParams.set("tp", "ob_cli_app");
	return {
		deviceCode: result.device_code,
		qrUrl: qrUrl.toString(),
		intervalSec: result.interval || 5,
		expireInSec: result.expire_in || 600
	};
}
/**
* Poll the registration endpoint until the user scans and confirms.
*/
async function pollAppRegistration(params) {
	let domain = params.initialDomain;
	let intervalSec = params.intervalSec;
	let domainSwitched = false;
	const deadline = Date.now() + params.expireInSec * 1e3;
	while (Date.now() < deadline) {
		let pollResponse;
		try {
			pollResponse = await postRegistration(accountsBaseUrl(domain), {
				action: "poll",
				device_code: params.deviceCode,
				tp: "ob_cli_app"
			});
		} catch {
			await sleep(intervalSec * 1e3);
			continue;
		}
		if (pollResponse.user_info?.tenant_brand) {
			const isLark = pollResponse.user_info.tenant_brand === "lark";
			if (!domainSwitched && isLark) {
				domain = "lark";
				domainSwitched = true;
				continue;
			}
		}
		if (pollResponse.client_id && pollResponse.client_secret) return {
			status: "success",
			result: {
				appId: pollResponse.client_id,
				appSecret: pollResponse.client_secret,
				domain,
				openId: pollResponse.user_info?.open_id
			}
		};
		if (pollResponse.error) if (pollResponse.error === "authorization_pending") {} else if (pollResponse.error === "slow_down") intervalSec += 5;
		else if (pollResponse.error === "access_denied") return { status: "access_denied" };
		else if (pollResponse.error === "expired_token") return { status: "expired" };
		else return {
			status: "error",
			message: `${pollResponse.error}: ${pollResponse.error_description ?? "unknown"}`
		};
		await sleep(intervalSec * 1e3);
	}
	return { status: "timeout" };
}
/**
* Print a QR code to the terminal (falls back to URL if qrcode-terminal is unavailable).
*/
async function printQrCode(url) {
	try {
		const qrcodeTerminal = await import(
			/* @vite-ignore */
			"qrcode-terminal"
);
		await new Promise((resolve) => {
			qrcodeTerminal.default.generate(url, { small: true }, (qr) => {
				process.stdout.write(qr.endsWith("\n") ? qr : `${qr}\n`);
				resolve();
			});
		});
	} catch {
		console.log("Open this URL in a browser to scan:\n");
		console.log(url);
	}
}
function sleep(ms) {
	return new Promise((resolve) => setTimeout(resolve, ms));
}
//#endregion
export { beginAppRegistration, initAppRegistration, pollAppRegistration, printQrCode };

//# sourceMappingURL=app-registration.js.map