import { execFileSync } from "node:child_process";
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = dirname(fileURLToPath(import.meta.url));
const fontsDir = join(__dirname, "..", "public", "fonts");
const outputWoff2 = join(fontsDir, "lxgwwenkaimono-medium.woff2");
const sourceTtf = join(__dirname, "..", "assets", "fonts", "LXGWWenKaiMono-Medium.ttf");

/** Full CJK font woff2 is typically 7–10 MB; reject obvious subset/corrupt output. */
const MIN_WOFF2_BYTES = 5_000_000;

if (!existsSync(sourceTtf)) {
	console.warn(`[prepare-font] source not found: ${sourceTtf}`);
	process.exit(0);
}

mkdirSync(fontsDir, { recursive: true });

function removePublicTtfCopies() {
	for (const name of readdirSync(fontsDir)) {
		if (name.toLowerCase().endsWith(".ttf")) {
			const path = join(fontsDir, name);
			unlinkSync(path);
			console.log(`[prepare-font] removed public TTF copy (woff2 only): ${path}`);
		}
	}
}

function woff2LooksValid() {
	if (!existsSync(outputWoff2)) return false;
	return readFileSync(outputWoff2).length >= MIN_WOFF2_BYTES;
}

function verifyGlyphCount() {
	const py = [
		"from fontTools.ttLib import TTFont",
		"import sys",
		"src, out = sys.argv[1], sys.argv[2]",
		"source_glyphs = len(TTFont(src).getGlyphOrder())",
		"output_glyphs = len(TTFont(out).getGlyphOrder())",
		"if source_glyphs != output_glyphs:",
		"\traise SystemExit(f'glyph count mismatch: source={source_glyphs}, output={output_glyphs}')",
		"print(output_glyphs)",
	].join("\n");
	const count = execFileSync("python", ["-c", py, sourceTtf, outputWoff2], {
		encoding: "utf8",
	}).trim();
	console.log(`[prepare-font] verified full glyph set (${count} glyphs)`);
}

removePublicTtfCopies();

if (woff2LooksValid()) {
	const sourceMtime = statSync(sourceTtf).mtimeMs;
	const outputMtime = statSync(outputWoff2).mtimeMs;
	if (outputMtime >= sourceMtime) {
		const sizeMb = (readFileSync(outputWoff2).length / (1024 * 1024)).toFixed(2);
		console.log(`[prepare-font] up to date ${outputWoff2} (${sizeMb} MB, woff2 only)`);
		process.exit(0);
	}
}

if (existsSync(outputWoff2) && !woff2LooksValid()) {
	console.warn("[prepare-font] removing invalid woff2 (< 5 MB, likely subset or corrupt)");
	unlinkSync(outputWoff2);
}

console.log(
	"[prepare-font] converting full font to woff2 (no glyph subsetting, glyf/loca/hmtx transforms)...",
);

const py = [
	"from fontTools.ttLib.woff2 import compress",
	"import sys",
	"compress(sys.argv[1], sys.argv[2], transform_tables={'glyf', 'loca', 'hmtx'})",
].join("\n");

execFileSync("python", ["-c", py, sourceTtf, outputWoff2], { stdio: "inherit" });

const sizeBytes = readFileSync(outputWoff2).length;
if (sizeBytes < MIN_WOFF2_BYTES) {
	throw new Error(
		`[prepare-font] woff2 output too small (${sizeBytes} bytes); conversion likely failed`,
	);
}

verifyGlyphCount();
removePublicTtfCopies();

const sizeMb = (sizeBytes / (1024 * 1024)).toFixed(2);
console.log(`[prepare-font] wrote ${outputWoff2} (${sizeMb} MB, full glyph set, woff2 only)`);
