const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const LicenseWebpackPlugin = require("license-webpack-plugin").LicenseWebpackPlugin;
// Note: Changes to this list requires approval from legal
const PackageInformation = require("./packageInformation").PackageInformation;
const allowedLicenses = require("./allowedLicenseTypes");
const path = require("path");
const { codeFrameColumns } = require("@babel/code-frame");
const fs = require("fs");
const os = require("os");

const setupCommonProd = env => {
    const plugins = [];

    // ForkTsCheckerWebpackPlugin requires "sync" mode when used with webpack-dev-server, too slow for development.
    // In async mode, webpack-dev-server doesn't report errors.
    // The IDE should still report any errors in open files and the production build checks everything.
    if (process.env.FAST_BUILD !== "1" || process.env.OUTPUT_BB_STATS) {
        const forkTsCheckerConfig = {
            typescript: {
                configFile: "tsconfig.base.json",
                diagnosticOptions: {
                    syntactic: true,
                },
                memoryLimit: 8192,
            },
        };

        if (process.env.OUTPUT_BB_STATS) {
            forkTsCheckerConfig.formatter = issue => {
                const file = issue.file;
                const source = file && fs.existsSync(file) && fs.readFileSync(file, "utf-8");
                let frame = "";

                if (source && issue?.location && issue?.location?.start && issue?.location?.end) {
                    frame = codeFrameColumns(source, issue.location, {
                        highlightCode: false,
                    });
                    frame = frame
                        .split("\n")
                        .map(line => `${line}`)
                        .join(os.EOL);
                }
                issue.snippet = frame;
                return JSON.stringify(issue);
            };
        }

        plugins.push(new ForkTsCheckerWebpackPlugin(forkTsCheckerConfig));

        const blueprint = process.env.BLUEPRINT_NAME ?? (env && env.BLUEPRINT) ?? "content-library";

        if (blueprint === "content-library") {
            // only validate licenses used in base, not blueprints
            // we no longer use the output file, so license validation should be moved elsewhere in the future
            plugins.push(
                new LicenseWebpackPlugin({
                    perChunkOutput: false,
                    // to stop all the missing license text warnings....
                    licenseTemplateDir: path.resolve(__dirname, "./default-license-texts"),
                    outputFilename: "licenses.json",
                    licenseTypeOverrides: {
                        // domutils license is not recognized correctly, override here. Hopefully it never changes.
                        domutils: "BSD-2-Clause",
                        "@adyen/adyen-web-auto": "MIT",
                    },
                    unacceptableLicenseTest: licenseType => !allowedLicenses.includes(licenseType),
                    modulesDirectories: [path.resolve(__dirname, "../../node_modules")],
                    renderLicenses: modules => {
                        console.log(`Licenses discovered: ${modules.length}`);
                        const mapped = modules
                            .sort((left, right) => {
                                return left.name < right.name ? -1 : 1;
                            })
                            .map(module => new PackageInformation(module));

                        return JSON.stringify(mapped);
                    },
                }),
            );
        }
    }

    return {
        mode: "production",
        plugins,
        devtool: "source-map",
    };
};

module.exports = setupCommonProd;
