import { init_paths, resolveExtensionsDir } from "../config/paths.js";
import { getExtensionLockfileManager } from "./lockfile.js";
import { readFile, readdir } from "fs/promises";
import { join } from "path";
import { existsSync } from "fs";
//#region src/extensions/health.ts
init_paths();
var ExtensionHealthChecker = class {
	extensionsDir;
	constructor(extensionsDir) {
		this.extensionsDir = extensionsDir || resolveExtensionsDir();
	}
	/**
	* Check health of a single extension
	*/
	async checkExtension(extensionId) {
		const extDir = join(this.extensionsDir, extensionId);
		const issues = [];
		let status = "healthy";
		if (!existsSync(extDir)) return {
			extensionId,
			status: "error",
			issues: ["Extension directory not found"],
			checkedAt: (/* @__PURE__ */ new Date()).toISOString()
		};
		for (const file of ["package.json", "xopc.extension.json"]) if (!existsSync(join(extDir, file))) {
			issues.push(`Missing required file: ${file}`);
			status = "error";
		}
		if (!existsSync(join(extDir, "node_modules"))) {
			issues.push("node_modules not found (run npm install)");
			status = status === "error" ? "error" : "warning";
		}
		let version;
		try {
			const pkgContent = await readFile(join(extDir, "package.json"), "utf-8");
			const pkg = JSON.parse(pkgContent);
			version = pkg.version;
			if (!pkg.name) {
				issues.push("package.json missing name field");
				status = "error";
			}
			if (!pkg.version) {
				issues.push("package.json missing version field");
				status = "error";
			}
			if (!pkg.main && !pkg.exports) {
				issues.push("package.json missing main or exports field");
				status = "warning";
			}
		} catch {
			issues.push("Failed to parse package.json");
			status = "error";
		}
		try {
			const extConfigPath = join(extDir, "xopc.extension.json");
			if (existsSync(extConfigPath)) {
				const extContent = await readFile(extConfigPath, "utf-8");
				const extConfig = JSON.parse(extContent);
				if (!extConfig.id) {
					issues.push("xopc.extension.json missing id field");
					status = "error";
				}
				if (!extConfig.name) {
					issues.push("xopc.extension.json missing name field");
					status = "warning";
				}
				if (!extConfig.version) {
					issues.push("xopc.extension.json missing version field");
					status = "warning";
				}
			}
		} catch {
			issues.push("Failed to parse xopc.extension.json");
			status = status === "error" ? "error" : "warning";
		}
		const lockEntry = await getExtensionLockfileManager().get(extensionId);
		if (lockEntry) {
			if (version && version !== lockEntry.version) {
				issues.push(`Version mismatch: installed ${version}, expected ${lockEntry.version}`);
				status = "warning";
			}
		}
		return {
			extensionId,
			status,
			version,
			expectedVersion: lockEntry?.version,
			issues,
			checkedAt: (/* @__PURE__ */ new Date()).toISOString()
		};
	}
	/**
	* Check health of all extensions
	*/
	async checkAll() {
		const extensions = [];
		if (!existsSync(this.extensionsDir)) return {
			status: "healthy",
			extensions: [],
			summary: {
				total: 0,
				healthy: 0,
				warning: 0,
				error: 0
			},
			checkedAt: (/* @__PURE__ */ new Date()).toISOString()
		};
		const extensionDirs = (await readdir(this.extensionsDir, { withFileTypes: true })).filter((e) => e.isDirectory() && !e.name.startsWith("."));
		for (const dir of extensionDirs) {
			const health = await this.checkExtension(dir.name);
			extensions.push(health);
		}
		const summary = {
			total: extensions.length,
			healthy: extensions.filter((e) => e.status === "healthy").length,
			warning: extensions.filter((e) => e.status === "warning").length,
			error: extensions.filter((e) => e.status === "error").length
		};
		let status = "healthy";
		if (summary.error > 0) status = "error";
		else if (summary.warning > 0) status = "warning";
		return {
			status,
			extensions,
			summary,
			checkedAt: (/* @__PURE__ */ new Date()).toISOString()
		};
	}
	/**
	* Fix common issues automatically
	*/
	async fixIssues(extensionId) {
		const fixed = [];
		const failed = [];
		const health = await this.checkExtension(extensionId);
		const extDir = join(this.extensionsDir, extensionId);
		for (const issue of health.issues) if (issue.includes("node_modules not found")) try {
			const { spawn } = await import("child_process");
			const npm = process.platform === "win32" ? "npm.cmd" : "npm";
			await new Promise((resolve, reject) => {
				const proc = spawn(npm, ["install"], {
					cwd: extDir,
					stdio: "pipe"
				});
				proc.on("close", (code) => {
					if (code === 0) resolve();
					else reject(/* @__PURE__ */ new Error(`npm install exited with code ${code}`));
				});
				proc.on("error", reject);
			});
			fixed.push("Installed node_modules");
		} catch {
			failed.push("Failed to install node_modules");
		}
		return {
			fixed,
			failed
		};
	}
	/**
	* Check for orphaned extensions (not in lockfile)
	*/
	async findOrphaned() {
		if (!existsSync(this.extensionsDir)) return [];
		const extensionDirs = (await readdir(this.extensionsDir, { withFileTypes: true })).filter((e) => e.isDirectory() && !e.name.startsWith("."));
		const lockfileManager = getExtensionLockfileManager();
		const orphaned = [];
		for (const dir of extensionDirs) if (!await lockfileManager.has(dir.name)) orphaned.push(dir.name);
		return orphaned;
	}
	/**
	* Generate health report as string
	*/
	formatReport(report) {
		const lines = [];
		lines.push("Extension Health Report");
		lines.push("=".repeat(50));
		lines.push("");
		lines.push(`Status: ${report.status.toUpperCase()}`);
		lines.push(`Checked: ${new Date(report.checkedAt).toLocaleString()}`);
		lines.push("");
		lines.push("Summary:");
		lines.push(`  Total:     ${report.summary.total}`);
		lines.push(`  Healthy:   ${report.summary.healthy} ✓`);
		lines.push(`  Warning:   ${report.summary.warning} ⚠`);
		lines.push(`  Error:     ${report.summary.error} ✗`);
		lines.push("");
		if (report.extensions.length > 0) {
			lines.push("Details:");
			for (const ext of report.extensions) {
				const icon = ext.status === "healthy" ? "✓" : ext.status === "warning" ? "⚠" : "✗";
				lines.push(`  ${icon} ${ext.extensionId}`);
				if (ext.version) lines.push(`     Version: ${ext.version}`);
				for (const issue of ext.issues) lines.push(`     - ${issue}`);
			}
		}
		return lines.join("\n");
	}
};
let globalChecker;
function getExtensionHealthChecker(extensionsDir) {
	if (!globalChecker) globalChecker = new ExtensionHealthChecker(extensionsDir);
	return globalChecker;
}
function resetExtensionHealthChecker() {
	globalChecker = void 0;
}
async function checkExtensionHealth(extensionId) {
	return getExtensionHealthChecker().checkExtension(extensionId);
}
async function checkAllExtensionsHealth() {
	return getExtensionHealthChecker().checkAll();
}
//#endregion
export { ExtensionHealthChecker, checkAllExtensionsHealth, checkExtensionHealth, getExtensionHealthChecker, resetExtensionHealthChecker };

//# sourceMappingURL=health.js.map