#!/usr/bin/env node
//
// Write the expected-output fixtures for a roster added to
// src/transforms/__fixtures__/.
//
//   node scripts/update-fixtures.mjs            # only writes what is missing
//   node scripts/update-fixtures.mjs --force    # re-baselines everything
//
// Drop a new `<name>.ros` in that directory and run this to generate the four
// `<name>.{merge,strip,convert,all}.ros` files the test suite compares against.
// Read the diff before committing: this records whatever the transforms do
// today, so it cannot tell a fix from a regression.
//
// Existing fixtures are left alone unless --force is given, and that guard is
// the point rather than a convenience. The fixtures that came with this repo
// were produced by a separate Python implementation and verified by printing
// the cards; the test suite is worth something because it checks the transforms
// against that independent output. Re-baselining a fixture from the JS replaces
// it with the very thing under test, and the comparison becomes a tautology
// that passes no matter what the code does.

import { readFileSync, readdirSync, existsSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { JSDOM } from "jsdom";

import {
	convertChoiceAbilities,
	defaultConfig,
	mergeDuplicateUnits,
	removeLeaderAbilities,
} from "../src/transforms/index.js";

const FIXTURES = join(
	dirname(fileURLToPath(import.meta.url)),
	"..",
	"src",
	"transforms",
	"__fixtures__",
);

const STEPS = {
	merge: (doc) => mergeDuplicateUnits(doc, defaultConfig),
	strip: (doc) => removeLeaderAbilities(doc, defaultConfig),
	convert: (doc) => convertChoiceAbilities(doc, defaultConfig),
};

// Chained, in the order the app runs them; see src/transforms/index.js.
const PIPELINE = ["merge", "strip", "convert"];

const force = process.argv.includes("--force");
const { window } = new JSDOM();

const inputs = readdirSync(FIXTURES)
	.filter((name) => name.endsWith(".ros") && name.split(".").length === 2)
	.map((name) => name.replace(/\.ros$/, ""));

let written = 0;
let kept = 0;

for (const input of inputs) {
	const xml = readFileSync(join(FIXTURES, `${input}.ros`), "utf8");

	const outputs = { ...STEPS, all: null };
	for (const label of Object.keys(outputs)) {
		const path = join(FIXTURES, `${input}.${label}.ros`);
		if (existsSync(path) && !force) {
			kept++;
			continue;
		}

		const doc = new window.DOMParser().parseFromString(xml, "text/xml");
		if (label === "all") {
			for (const step of PIPELINE) STEPS[step](doc);
		} else {
			STEPS[label](doc);
		}

		writeFileSync(path, new window.XMLSerializer().serializeToString(doc), "utf8");
		console.log(`wrote ${input}.${label}.ros`);
		written++;
	}
}

console.log(`\n${written} written, ${kept} left alone.`);
if (kept > 0 && !force) {
	console.log("Pass --force to re-baseline the rest, but read the header first.");
}
