#!/usr/bin/env node
const { spawnSync } = require("node:child_process");
const { existsSync, readdirSync, statSync } = require("node:fs");
const { join, resolve } = require("node:path");

const root = resolve(__dirname, "..");
const srcResources = join(root, "src", "resources");
const distResources = join(root, "dist", "resources");
const stampPath = join(distResources, ".sf-resource-build-stamp");
const copyResourcesScript = join(root, "scripts", "copy-resources.cjs");

function latestMtimeMs(path) {
	let latest = 0;
	const stack = [path];

	while (stack.length > 0) {
		const current = stack.pop();
		if (!current) continue;

		let entries;
		try {
			entries = readdirSync(current, { withFileTypes: true });
		} catch {
			continue;
		}

		for (const entry of entries) {
			const entryPath = join(current, entry.name);
			let stat;
			try {
				stat = statSync(entryPath);
			} catch {
				continue;
			}
			latest = Math.max(latest, stat.mtimeMs);
			if (entry.isDirectory()) {
				stack.push(entryPath);
			}
		}
	}

	return latest;
}

function sourceInputsMtimeMs() {
	return Math.max(
		latestMtimeMs(srcResources),
		existsSync(copyResourcesScript) ? statSync(copyResourcesScript).mtimeMs : 0,
		existsSync(join(root, "tsconfig.resources.json"))
			? statSync(join(root, "tsconfig.resources.json")).mtimeMs
			: 0,
	);
}

function hasCompleteResourceBuild() {
	return (
		existsSync(stampPath) &&
		existsSync(join(distResources, "SF-WORKFLOW.md")) &&
		existsSync(join(distResources, "agents")) &&
		existsSync(join(distResources, "extensions"))
	);
}

function shouldRebuild() {
	if (process.env.SF_DEV_CLI_SKIP_RESOURCE_BUILD === "1") return false;
	if (process.env.SF_SKIP_SOURCE_RESOURCE_BUILD === "1") return false;
	if (!hasCompleteResourceBuild()) return true;

	let stampMtime = 0;
	try {
		stampMtime = statSync(stampPath).mtimeMs;
	} catch {
		return true;
	}

	return sourceInputsMtimeMs() > stampMtime;
}

if (shouldRebuild()) {
	console.error(
		"[forge] Source resources changed; rebuilding dist/resources before launch...",
	);
	const result = spawnSync(process.execPath, [copyResourcesScript], {
		cwd: root,
		stdio: "inherit",
		env: process.env,
	});

	if (result.status !== 0) {
		process.exit(result.status ?? 1);
	}
}
