import { t as writeFileAtomic } from "./atomic-write-8yjqqLtS.js";
import path from "path";
import fs from "fs";
import { OAuth2Client } from "google-auth-library";
//#region src/sync/oauth/token-store.ts
function tokensPath(dataDir) {
	return path.join(dataDir, ".agentic", "mailbox-tokens.json");
}
function keyOf(provider, user) {
	return `${provider}:${user.toLowerCase()}`;
}
function readAll(dataDir) {
	const file = tokensPath(dataDir);
	if (!fs.existsSync(file)) return {};
	try {
		return JSON.parse(fs.readFileSync(file, "utf-8"));
	} catch {
		return {};
	}
}
/** Persist (upsert) a mailbox OAuth token. */
function saveMailboxToken(dataDir, token) {
	const all = readAll(dataDir);
	all[keyOf(token.provider, token.user)] = token;
	const file = tokensPath(dataDir);
	fs.mkdirSync(path.dirname(file), { recursive: true });
	writeFileAtomic(file, JSON.stringify(all, null, 2));
}
/** Load a stored token for a provider+user, or undefined. */
function loadMailboxToken(dataDir, provider, user) {
	return readAll(dataDir)[keyOf(provider, user)];
}
/** True when the access token is missing or expires within `skewMs` (default 60s). */
function isTokenExpired(token, skewMs = 6e4, now = Date.now()) {
	return !token.accessToken || token.expiresAt <= now + skewMs;
}
//#endregion
//#region src/sync/oauth/google.ts
const GMAIL_IMAP_SCOPE = "https://mail.google.com/";
/** Loopback redirect for the desktop/installed-app flow. */
const DEFAULT_REDIRECT = "http://127.0.0.1";
/** Build a real Google OAuth2 client for an installed/desktop app. */
function createOAuthClient(clientId, clientSecret, redirectUri = DEFAULT_REDIRECT) {
	return new OAuth2Client(clientId, clientSecret, redirectUri);
}
/** The consent URL — offline access + forced consent so a refresh token is issued. */
function buildAuthUrl(client, redirectUri) {
	return client.generateAuthUrl({
		access_type: "offline",
		prompt: "consent",
		scope: GMAIL_IMAP_SCOPE,
		...redirectUri ? { redirect_uri: redirectUri } : {}
	});
}
/** Exchange an authorization code for tokens. */
async function exchangeCodeForTokens(client, code, now = Date.now) {
	const { tokens } = await client.getToken(code);
	if (!tokens.access_token) throw new Error("Google did not return an access token");
	return {
		accessToken: tokens.access_token,
		...tokens.refresh_token ? { refreshToken: tokens.refresh_token } : {},
		expiresAt: tokens.expiry_date ?? now() + 36e5
	};
}
/** Mint a fresh access token from a stored refresh token. */
async function refreshGoogleToken(clientId, clientSecret, refreshToken, clientFactory = createOAuthClient, now = Date.now) {
	const client = clientFactory(clientId, clientSecret);
	client.setCredentials({ refresh_token: refreshToken });
	const { credentials } = await client.refreshAccessToken();
	if (!credentials.access_token) throw new Error("Google refresh did not return an access token");
	return {
		accessToken: credentials.access_token,
		refreshToken,
		expiresAt: credentials.expiry_date ?? now() + 36e5
	};
}
//#endregion
//#region src/sync/oauth/microsoft.ts
const MS_IMAP_SCOPE = "offline_access https://outlook.office365.com/IMAP.AccessAsUser.All";
function endpoint(tenant, kind) {
	return `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/${kind}`;
}
/** Start the device-code flow; returns the user code + verification URL to show. */
async function requestDeviceCode(clientId, tenant = "common", fetchFn = fetch) {
	const res = await fetchFn(endpoint(tenant, "devicecode"), {
		method: "POST",
		headers: { "Content-Type": "application/x-www-form-urlencoded" },
		body: new URLSearchParams({
			client_id: clientId,
			scope: MS_IMAP_SCOPE
		}).toString()
	});
	if (!res.ok) throw new Error(`device code request failed: ${res.status} ${await res.text()}`);
	return await res.json();
}
/**
* Poll the token endpoint until the user authorizes (or the code expires).
* Honors `authorization_pending` (keep waiting) and `slow_down` (back off).
*/
async function pollForToken(opts) {
	const tenant = opts.tenant ?? "common";
	const fetchFn = opts.fetchFn ?? fetch;
	const sleepFn = opts.sleepFn ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
	const now = opts.now ?? Date.now;
	let intervalMs = (opts.interval ?? 5) * 1e3;
	const deadline = now() + (opts.expiresIn ?? 900) * 1e3;
	for (;;) {
		if (now() >= deadline) throw new Error("device code expired before authorization");
		await sleepFn(intervalMs);
		const res = await fetchFn(endpoint(tenant, "token"), {
			method: "POST",
			headers: { "Content-Type": "application/x-www-form-urlencoded" },
			body: new URLSearchParams({
				grant_type: "urn:ietf:params:oauth:grant-type:device_code",
				client_id: opts.clientId,
				device_code: opts.deviceCode
			}).toString()
		});
		const data = await res.json();
		if (res.ok && "access_token" in data) return tokensFromSuccess(data, now());
		const err = data.error;
		if (err === "authorization_pending") continue;
		if (err === "slow_down") {
			intervalMs += 5e3;
			continue;
		}
		throw new Error(`device flow failed: ${err}${describe(data)}`);
	}
}
/** Exchange a refresh token for a fresh access token. */
async function refreshMicrosoftToken(clientId, refreshToken, tenant = "common", fetchFn = fetch, now = Date.now) {
	const res = await fetchFn(endpoint(tenant, "token"), {
		method: "POST",
		headers: { "Content-Type": "application/x-www-form-urlencoded" },
		body: new URLSearchParams({
			grant_type: "refresh_token",
			client_id: clientId,
			refresh_token: refreshToken,
			scope: MS_IMAP_SCOPE
		}).toString()
	});
	const data = await res.json();
	if (!res.ok || !("access_token" in data)) throw new Error(`token refresh failed: ${data.error ?? res.status}`);
	return tokensFromSuccess(data, now());
}
function tokensFromSuccess(data, nowMs) {
	return {
		accessToken: data.access_token,
		...data.refresh_token ? { refreshToken: data.refresh_token } : {},
		expiresAt: nowMs + data.expires_in * 1e3
	};
}
function describe(e) {
	return e.error_description ? ` (${e.error_description.split("\n")[0]})` : "";
}
//#endregion
export { buildAuthUrl as a, refreshGoogleToken as c, saveMailboxToken as d, DEFAULT_REDIRECT as i, isTokenExpired as l, refreshMicrosoftToken as n, createOAuthClient as o, requestDeviceCode as r, exchangeCodeForTokens as s, pollForToken as t, loadMailboxToken as u };

//# sourceMappingURL=microsoft-DgbVlHdT.js.map