import { readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { parse } from "jsonc-parser";
import { format } from "prettier";
import { printWarningToConsole } from "../output.js";
import { StandardUpgrader } from "./lib.js";
export class FailedToParseTSConfigJson extends Error {
    constructor() {
        super("Invalid tsconfig.json: Failed to parse the tsconfig.json file.");
        Object.setPrototypeOf(this, FailedToParseTSConfigJson.prototype);
    }
}
const tsConfig = {
    include: ["modules/**/*", ".zuplo/**/*", "tests/**/*"],
    exclude: ["./node_modules", "./dist"],
    compilerOptions: {
        module: "ESNext",
        target: "ES2022",
        moduleResolution: "Bundler",
        lib: ["ESNext", "WebWorker", "Webworker.Iterable"],
        preserveConstEnums: true,
        useUnknownInCatchVariables: false,
        forceConsistentCasingInFileNames: true,
        importHelpers: true,
        removeComments: true,
        esModuleInterop: true,
        strictNullChecks: true,
        noEmit: true,
    },
};
export class InvalidTSConfigJson extends Error {
    constructor(message) {
        super(message);
        Object.setPrototypeOf(this, InvalidTSConfigJson.prototype);
    }
}
export class TSConfigUpgrader extends StandardUpgrader {
    async isApplicable() {
        return { ok: true };
    }
    async needsUpgrade() {
        try {
            const tsFilePath = join(this.normalizedDir, "tsconfig.json");
            const tsConfigRaw = await readFile(tsFilePath, "utf-8");
            const tsConfigJson = parse(tsConfigRaw);
            if (!(tsConfigJson &&
                typeof tsConfigJson === "object" &&
                "compilerOptions" in tsConfigJson)) {
                return true;
            }
            const libValue = ["ESNext", "WebWorker", "Webworker.Iterable"];
            const includesAllLibs = (userLibs) => {
                const a = libValue.map((item) => item.toLowerCase());
                const b = userLibs.map((item) => item.toLowerCase());
                return a.every((item) => b.includes(item));
            };
            if (tsConfigJson.extends) {
                printWarningToConsole("This project uses an advanced tsconfig.json setup. You will need to manually upgrade this file.");
                return false;
            }
            else {
                const options = tsConfigJson.compilerOptions;
                return (options.module?.toLowerCase() !==
                    tsConfig.compilerOptions.module.toLowerCase() ||
                    options.target?.toLowerCase() !==
                        tsConfig.compilerOptions.target.toLowerCase() ||
                    options.moduleResolution?.toLowerCase() !==
                        tsConfig.compilerOptions.moduleResolution.toLowerCase() ||
                    !options.lib ||
                    options.baseUrl !== undefined ||
                    !includesAllLibs(tsConfigJson.compilerOptions.lib ?? []));
            }
        }
        catch {
            return true;
        }
    }
    async upgrade() {
        if (!(await this.needsUpgrade())) {
            return;
        }
        const tsFilePath = join(this.normalizedDir, "tsconfig.json");
        const formatted = await format(JSON.stringify(tsConfig), {
            parser: "json",
        });
        await writeFile(tsFilePath, formatted);
    }
}
//# sourceMappingURL=tsconfig-upgrader.js.map