import { Ct as resolveStateDir } from "./entry.js";
import { r as loadOrCreateDeviceIdentity } from "./device-identity-ZHUQ6a8N.js";
import path from "node:path";
import fs from "node:fs/promises";

//#region src/federation/access-token.ts
function resolveFederationTokenPath(env = process.env) {
	const explicitPath = env.FASED_FEDERATION_TOKEN_PATH?.trim();
	if (explicitPath) return explicitPath;
	return path.join(resolveStateDir(env), "federation", "access-token.json");
}
async function loadPersistedFederationToken(env = process.env) {
	const tokenPath = resolveFederationTokenPath(env);
	try {
		const raw = await fs.readFile(tokenPath, "utf-8");
		const parsed = JSON.parse(raw);
		if (!parsed || typeof parsed !== "object") return null;
		const token = parsed;
		if (typeof token.tokenId !== "string" || typeof token.nodeId !== "string" || typeof token.handle !== "string" || typeof token.issuedAt !== "string" || typeof token.expiresAt !== "string" || !Array.isArray(token.scopes) || typeof token.signature !== "string") return null;
		return {
			tokenId: token.tokenId,
			nodeId: token.nodeId,
			handle: token.handle,
			issuedAt: token.issuedAt,
			expiresAt: token.expiresAt,
			scopes: token.scopes.filter((scope) => typeof scope === "string"),
			signature: token.signature,
			trustState: token.trustState === "pending" || token.trustState === "verified" || token.trustState === "revoked" || token.trustState === "blocked" ? token.trustState : void 0,
			hostedState: token.hostedState === "disabled" || token.hostedState === "pending" || token.hostedState === "ready" || token.hostedState === "missing" ? token.hostedState : void 0,
			agentSlug: typeof token.agentSlug === "string" ? token.agentSlug : void 0,
			publicUrl: typeof token.publicUrl === "string" ? token.publicUrl : void 0,
			zrokToken: typeof token.zrokToken === "string" ? token.zrokToken : void 0,
			zrokTokenPresent: typeof token.zrokTokenPresent === "boolean" ? token.zrokTokenPresent : void 0,
			lastAttestOrRenewAt: typeof token.lastAttestOrRenewAt === "string" ? token.lastAttestOrRenewAt : void 0,
			paidFlowEligible: typeof token.paidFlowEligible === "boolean" ? token.paidFlowEligible : void 0,
			bondId: typeof token.bondId === "string" ? token.bondId : void 0,
			bondWallet: token.bondWallet && typeof token.bondWallet === "object" && typeof token.bondWallet.chain === "string" && typeof token.bondWallet.address === "string" ? {
				chain: token.bondWallet.chain,
				address: token.bondWallet.address
			} : void 0,
			bondStatus: token.bondStatus === "missing" || token.bondStatus === "active" || token.bondStatus === "unlocking" || token.bondStatus === "unlocked" ? token.bondStatus : void 0,
			bondTier: token.bondTier === "none" || token.bondTier === "basic-bond" || token.bondTier === "operator-bond" ? token.bondTier : void 0,
			bondAmountRaw: typeof token.bondAmountRaw === "string" ? token.bondAmountRaw : void 0,
			bondUnlockAvailableAt: typeof token.bondUnlockAvailableAt === "string" ? token.bondUnlockAvailableAt : void 0,
			bondQuotaBand: token.bondQuotaBand === "standard" || token.bondQuotaBand === "boosted" || token.bondQuotaBand === "operator" ? token.bondQuotaBand : void 0,
			bondDerivedScopes: Array.isArray(token.bondDerivedScopes) ? token.bondDerivedScopes.filter((scope) => typeof scope === "string") : void 0
		};
	} catch {
		return null;
	}
}
function mergePersistedFederationTokenMetadata(params) {
	const previous = params.previous;
	if (!previous) return params.next;
	return {
		...params.next,
		hostedState: params.next.hostedState ?? previous.hostedState,
		agentSlug: params.next.agentSlug ?? previous.agentSlug,
		publicUrl: params.next.publicUrl ?? previous.publicUrl,
		zrokToken: params.next.zrokToken ?? previous.zrokToken,
		zrokTokenPresent: params.next.zrokTokenPresent ?? previous.zrokTokenPresent
	};
}
async function persistFederationAccessToken(token, env = process.env) {
	const tokenPath = resolveFederationTokenPath(env);
	const next = mergePersistedFederationTokenMetadata({
		next: token,
		previous: await loadPersistedFederationToken(env)
	});
	await fs.mkdir(path.dirname(tokenPath), {
		recursive: true,
		mode: 448
	});
	const tmpPath = `${tokenPath}.tmp`;
	await fs.writeFile(tmpPath, `${JSON.stringify(next, null, 2)}\n`, { mode: 384 });
	await fs.rename(tmpPath, tokenPath);
	return next;
}
async function loadFederationBearerToken(env = process.env) {
	const token = await loadPersistedFederationToken(env);
	if (!token?.tokenId) return "";
	const expiresAtMs = Date.parse(token.expiresAt);
	if (!Number.isFinite(expiresAtMs) || expiresAtMs <= Date.now()) return "";
	return token.tokenId;
}

//#endregion
//#region src/federation/runtime.ts
const DEFAULT_FEDERATION_BASE_URL = "https://ff1.fased.app";
function normalizeUrl(raw) {
	const value = new URL(raw).toString();
	return value.endsWith("/") ? value.slice(0, -1) : value;
}
function sanitizeName(raw) {
	return raw.trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "fased-agent";
}
function normalizeHandle(raw, domain) {
	const trimmed = raw.trim();
	if (!trimmed) return "";
	if (trimmed.startsWith("@") && trimmed.includes("@", 1)) return trimmed;
	const base = trimmed.startsWith("@") ? trimmed.slice(1) : trimmed;
	if (base.includes("@")) return `@${base}`;
	return `@${base}@${domain}`;
}
function resolveFederationBaseUrl(env = process.env) {
	const raw = env.FASED_FEDERATION_BASE_URL?.trim() || env.FASED_FEDERATION_URL?.trim() || DEFAULT_FEDERATION_BASE_URL;
	try {
		return normalizeUrl(raw);
	} catch {
		return "";
	}
}
function resolveAgentPublicOrigin(env = process.env) {
	const explicit = env.FASED_A2A_ORIGIN?.trim() || env.FASED_FEDIFY_ORIGIN?.trim() || "";
	if (explicit) try {
		return normalizeUrl(explicit);
	} catch {}
	const port = Number(env.FASED_GATEWAY_PORT ?? "18789");
	return `http://127.0.0.1:${Number.isFinite(port) && port > 0 ? Math.floor(port) : 18789}`;
}
function resolveFederationHandle(params) {
	const env = params?.env ?? process.env;
	const fallbackDomain = params?.fallbackDomain ?? "localhost";
	const explicit = env.FASED_A2A_HANDLE?.trim() || env.FASED_FEDERATION_HANDLE?.trim() || "";
	if (explicit) return normalizeHandle(explicit, fallbackDomain);
	const federationBaseUrl = resolveFederationBaseUrl(env);
	const federationDomain = federationBaseUrl ? new URL(federationBaseUrl).hostname : fallbackDomain;
	const nodeId = params?.nodeId ?? loadOrCreateDeviceIdentity(path.join(resolveStateDir(env), "identity", "device.json")).deviceId;
	return `@${sanitizeName(env.FASED_A2A_NAME?.trim() || "fased-agent")}-${nodeId.slice(0, 12)}@${federationDomain}`;
}
function resolveFederationBondWalletId(params) {
	const env = params?.env ?? process.env;
	const cfg = params?.cfg;
	const envExplicit = env.FASED_FEDERATION_BOND_WALLET_ID?.trim() || env.FASED_BOND_WALLET_ID?.trim() || "";
	if (envExplicit) return envExplicit;
	const configExplicit = cfg?.federation?.bond?.walletId?.trim() || "";
	if (configExplicit) return configExplicit;
	return "";
}

//#endregion
export { resolveFederationBondWalletId as a, loadPersistedFederationToken as c, resolveFederationBaseUrl as i, persistFederationAccessToken as l, normalizeHandle as n, resolveFederationHandle as o, resolveAgentPublicOrigin as r, loadFederationBearerToken as s, DEFAULT_FEDERATION_BASE_URL as t, resolveFederationTokenPath as u };