import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
import { join } from "node:path";
//#region extensions/crypto/src/services/policy-types.ts
/**
* Maps category names to the write tools they contain.
* Every tool in WRITE_TOOL_NAMES should be in exactly one category.
*/
const TOOL_CATEGORIES = {
	defi: [
		"defi_swap",
		"defi_lend",
		"defi_stake",
		"liquidity",
		"yield",
		"bridge",
		"permit2",
		"approvals",
		"wayfinder",
		"molten"
	],
	transfer: ["transfer"],
	fiat: ["fiat_payment"],
	bankr: [
		"bankr_launch",
		"bankr_automate",
		"bankr_polymarket",
		"bankr_leverage"
	],
	social: ["clawnx", "farcaster"],
	nft: ["nft", "airdrop"],
	governance: ["governance", "safe"],
	platform: [
		"clawnch_launch",
		"clawnch_fees",
		"clawnch_info",
		"hummingbot"
	],
	orchestration: [
		"manage_orders",
		"compound_action",
		"crypto_workflow"
	],
	privacy: ["privacy"],
	browser: ["browser"],
	wallet: ["clawnchconnect"]
};
/** Human-readable category labels. */
const CATEGORY_LABELS = {
	defi: "DeFi (swap, lend, stake, bridge, LP, yield, approvals)",
	transfer: "Transfers (send ETH/tokens)",
	fiat: "Fiat (on-ramp, off-ramp)",
	bankr: "Bankr (launch, automate, polymarket, leverage)",
	social: "Social (X/Twitter, Farcaster)",
	nft: "NFT & Airdrops",
	governance: "Governance & Safe multisig",
	platform: "Platform (launch, fees, hummingbot)",
	orchestration: "Orchestration (orders, compound actions, workflows)",
	privacy: "Privacy tools",
	browser: "Web3 browser",
	wallet: "Wallet connection"
};
/** Reverse lookup: tool name → category. */
const TOOL_TO_CATEGORY = {};
for (const [category, tools] of Object.entries(TOOL_CATEGORIES)) for (const tool of tools) TOOL_TO_CATEGORY[tool] = category;
const PERIOD_MS = {
	hourly: 3600 * 1e3,
	daily: 1440 * 60 * 1e3,
	weekly: 10080 * 60 * 1e3,
	monthly: 720 * 60 * 60 * 1e3
};
/** Convert a named period to milliseconds. Throws on unknown periods. */
function periodToMs(period) {
	const ms = PERIOD_MS[period];
	if (ms == null) throw new Error(`Unknown period: "${period}". Valid: ${Object.keys(PERIOD_MS).join(", ")}.`);
	return ms;
}
/** Render a single rule as unambiguous plain English. */
function describeRule(rule) {
	switch (rule.type) {
		case "spending_limit": return `Spending limit: max $${rule.maxAmountUsd} USD per ${rule.period} period`;
		case "rate_limit": {
			const hours = Math.round(rule.periodMs / 36e5);
			const label = hours >= 24 ? `${Math.round(hours / 24)} day(s)` : `${hours} hour(s)`;
			return `Rate limit: max ${rule.maxCalls} calls per ${label}`;
		}
		case "allowlist": return `Allowlist (${rule.field}): only ${rule.values.join(", ")}`;
		case "blocklist": return `Blocklist (${rule.field}): never ${rule.values.join(", ")}`;
		case "time_window": {
			const parts = [];
			if (rule.allowedHours) parts.push(`hours ${rule.allowedHours.start}:00–${rule.allowedHours.end}:00`);
			if (rule.allowedDays) {
				const dayNames = [
					"Sun",
					"Mon",
					"Tue",
					"Wed",
					"Thu",
					"Fri",
					"Sat"
				];
				parts.push(rule.allowedDays.map((d) => dayNames[d] ?? d).join(", "));
			}
			const tz = rule.timezone ?? "UTC";
			return `Time window: allowed during ${parts.join(" on ")} (${tz})`;
		}
		case "approval_threshold": return `Require confirmation: for any action above $${rule.amountUsd} USD`;
		case "max_amount": return `Hard limit: block any single action above $${rule.maxAmountUsd} USD`;
		case "erc20_limit": {
			const symbol = {
				"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913": "USDC",
				"0xfde4c96c8593536e31f229ea8f37b2ada2699bb2": "USDT",
				"0x50c5725949a6f0c72e6c4a641f24049a917db0cb": "DAI",
				"0x4200000000000000000000000000000000000006": "WETH",
				"0xa1f72459dfa10bad200ac160ecd78c6b77a747be": "CLAWNCH"
			}[rule.token.toLowerCase()] ?? `${rule.token.slice(0, 10)}...`;
			return `ERC-20 limit: max ${rule.maxAmount} ${symbol}`;
		}
	}
}
/** Render a scope as plain English. */
function describeScope(scope) {
	switch (scope.type) {
		case "all_write": return "All write operations (any tool that sends transactions or modifies state)";
		case "tools": return `Specific tools: ${(scope.tools ?? []).join(", ")}`;
		case "categories": return `Categories: ${(scope.categories ?? []).map((c) => CATEGORY_LABELS[c] ?? c).join("; ")}`;
	}
}
const POLICY_MODE_HOME = join(process.env.HOME ?? "/home/openclawnch", ".openclawnch");
const POLICY_MODE_FILE = join(POLICY_MODE_HOME, "policy-mode.json");
/** Default mode — delegation is the default for new installs. */
const DEFAULT_MODE = "delegation";
/** In-memory cache. */
let _cachedMode = null;
/** Get the current policy enforcement mode. */
function getPolicyMode() {
	if (_cachedMode) return _cachedMode;
	try {
		if (existsSync(POLICY_MODE_FILE)) {
			const data = JSON.parse(readFileSync(POLICY_MODE_FILE, "utf8"));
			if (data.mode === "delegation" || data.mode === "simple") {
				_cachedMode = data.mode;
				return data.mode;
			}
		}
	} catch {}
	_cachedMode = DEFAULT_MODE;
	return _cachedMode;
}
/** Set the policy enforcement mode. Persists to disk. */
function setPolicyMode(mode) {
	_cachedMode = mode;
	if (!existsSync(POLICY_MODE_HOME)) mkdirSync(POLICY_MODE_HOME, { recursive: true });
	const tmpPath = POLICY_MODE_FILE + ".tmp." + Date.now();
	writeFileSync(tmpPath, JSON.stringify({ mode }, null, 2), { mode: 384 });
	renameSync(tmpPath, POLICY_MODE_FILE);
}
/** Check if delegation features are enabled (mode === 'delegation'). */
function isDelegationMode() {
	return getPolicyMode() === "delegation";
}
/** Reset cached mode (for testing). */
function resetPolicyMode() {
	_cachedMode = null;
}
//#endregion
export { CATEGORY_LABELS, TOOL_CATEGORIES, TOOL_TO_CATEGORY, describeRule, describeScope, getPolicyMode, isDelegationMode, periodToMs, resetPolicyMode, setPolicyMode };

//# sourceMappingURL=policy-types.mjs.map