import { readFile } from "node:fs/promises";
import makeAbsolute from "./make-absolute.mjs";

/**
 * @import { IViolation } from "../../types/violations.mjs"
 * @import { DependencyType } from "../../types/shared-types.mjs"
 *
 * @typedef {IViolation & {cycle: Array<{name: string, dependencyTypes: Array<DependencyType>}>} | {cycle: Array<DependencyType>}} IMaybeOldFormatViolation
 */

/**
 * cycles went from Array<string> to Array<{name: string, dependencyTypes: Array<DependencyType>}>
 * in version 16.0.0. Known violations would typically be still in the old
 * format. To prevent customers from bumping into error messages and having
 * to update or regenerate their known violations, we'll make the old format
 * forward compatible with this.
 *
 * @param {IMaybeOldFormatViolation} pKnownViolation
 * @returns {IViolation}
 */
function makeForwardCompatible(pKnownViolation) {
	let lReturnValue = pKnownViolation;
	if (pKnownViolation.cycle) {
		lReturnValue = {
			...pKnownViolation,
			cycle: pKnownViolation.cycle.map((pModule) => {
				if (pModule.name) {
					return pModule;
				}
				return {
					name: pModule,
					dependencyTypes: [],
				};
			}),
		};
	}
	if (pKnownViolation.via) {
		lReturnValue = {
			...pKnownViolation,
			via: pKnownViolation.via.map((pModule) => {
				if (pModule.name) {
					return pModule;
				}
				return {
					name: pModule,
					dependencyTypes: [],
				};
			}),
		};
	}
	return lReturnValue;
}

export default async function extractKnownViolations(pKnownViolationsFileName) {
	const { default: json5 } = await import("json5");

	try {
		const lFileContents = await readFile(
			makeAbsolute(pKnownViolationsFileName),
			"utf8",
		);
		const lKnownViolations = json5.parse(lFileContents);
		const lForwardCompatible = lKnownViolations.map(makeForwardCompatible);

		return lForwardCompatible;
	} catch (pError) {
		if (pError instanceof SyntaxError) {
			throw new SyntaxError(
				`'${pKnownViolationsFileName}' should be valid json\n          ${pError}`,
			);
		}
		throw pError;
	}

	// TODO: validate the json against the schema? (might be more clear to do it here,
	// even if (in context of the cli) it's done again when validating the whole
	// config
}
