const path = require("path");
const webpack = require("webpack");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const nodeExternals = require("webpack-node-externals");
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
const config = require("./config/config");

module.exports.getEnv = function getEnv() {
  const ENV = process.env.NODE_ENV == null ? "development" : process.env.NODE_ENV;
  return { ENV };
};

const DEFAULT_PARAMS = {
  localesPath: "./src/locales",
  modulesPath: [path.resolve("../../node_modules")],
  externalsModulesDir: "../../node_modules",
  outputPath: path.resolve(__dirname, "build"),
  watch: false,
};

/**
 *
 * @param {{
 *  configName: string;
 *  entry: string;
 *  tsConfig: string;
 *  outputPath?: string;
 *  mode?: string;
 *  env?: string;
 *  modulesPath?: string[];
 *  localesPath?: string;
 *  externalsModulesDir?: string;
 *  watch?: boolean;
 *  importAliases?: import("webpack").ResolveOptions["alias"];
 * }} params
 */
module.exports.buildConfig = function buildConfig(params) {
  params = { ...DEFAULT_PARAMS, ...params };
  const ENV = params.env || module.exports.getEnv().ENV;

  const envConfig = config.load(ENV);
  config.log(`Building CLI - ${params.configName} version`);
  config.log(envConfig);

  const moduleRules = [
    {
      test: /\.ts$/,
      use: "ts-loader",
      exclude: path.resolve(__dirname, "node_modules"),
    },
  ];

  const plugins = [
    new CopyWebpackPlugin({
      patterns: [{ from: params.localesPath, to: "locales" }],
    }),
    new webpack.DefinePlugin({
      "process.env.BWCLI_ENV": JSON.stringify(ENV),
    }),
    new webpack.BannerPlugin({
      banner: "#!/usr/bin/env node",
      raw: true,
    }),
    new webpack.IgnorePlugin({
      resourceRegExp: /^encoding$/,
      contextRegExp: /node-fetch/,
    }),
    new webpack.EnvironmentPlugin({
      ENV: ENV,
      BWCLI_ENV: ENV,
      FLAGS: envConfig.flags,
      DEV_FLAGS: envConfig.devFlags,
    }),
    new webpack.IgnorePlugin({
      resourceRegExp: /canvas/,
      contextRegExp: /jsdom$/,
    }),
  ];

  const webpackConfig = {
    mode: params.mode || ENV,
    target: "node",
    devtool: ENV === "development" ? "eval-source-map" : "source-map",
    node: {
      __dirname: false,
      __filename: false,
    },
    entry: {
      bw: params.entry,
    },
    optimization: {
      minimize: false,
    },
    resolve: {
      extensions: [".ts", ".js"],
      symlinks: false,
      modules: params.modulesPath,
      plugins: [new TsconfigPathsPlugin({ configFile: params.tsConfig })],
      alias: params.importAliases,
    },
    output: {
      filename: "[name].js",
      path: path.resolve(params.outputPath),
      clean: true,
    },
    module: { rules: moduleRules },
    plugins: plugins,
    externals: [
      nodeExternals({
        modulesDir: params.externalsModulesDir,
        allowlist: [/@bitwarden/, /^https-proxy-agent$/, /^agent-base$/],
      }),
    ],
    experiments: {
      asyncWebAssembly: true,
    },
  };
  if (params.watch) {
    webpackConfig.watch = true;
    webpackConfig.watchOptions = {
      ignored: /node_modules/,
      poll: 1000,
    };
  }
  return webpackConfig;
};
