const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const webpack = require("webpack");
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");

const dotenv = require("dotenv");

const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;

const TerserPlugin = require("terser-webpack-plugin");

module.exports = () => {
  let envPath = ".env";
  if (process.env.ENV_FILE !== "") {
    envPath = process.env.ENV_FILE;
  }
  console.log(`using envfile from path ${envPath}`);

  let env = dotenv.config({ path: envPath }).parsed;
  console.log(env);
  if (!env) {
    env = process.env;
  }

  const envKeys = Object.keys(env).reduce((prev, next) => {
    const varName = `process.env.${next}`;
    if (typeof env[next] !== "string") return prev;

    if (env[next].toLowerCase() === "true") {
      prev[varName] = true;
    } else if (env[next].toLowerCase() === "false") {
      prev[varName] = false;
    } else {
      prev[varName] = JSON.stringify(env[next]);
    }

    return prev;
  }, {});

  // Check first the env file and if it's empty, check out the node env of the process.
  let isDevelopment = env.NODE_ENV !== "production";
  if (process.env.NODE_ENV !== env.NODE_ENV) {
    isDevelopment = process.env.NODE_ENV !== "production";
  }

  let htmlPluginOpts = {
    template: path.resolve(__dirname, "src", "index.html"),
  };

  if (env.IS_HOSTED) {
    htmlPluginOpts = {
      template: path.resolve(__dirname, "src", "hosted.index.html"),
      intercomAppId: `${env.INTERCOM_APP_ID}`,
      hotjarId: `${env.HOTJAR_ID}`,
      intercomSrc: `${process.env.INTERCOM_SRC}`,
      segmentWriteKey: `${process.env.SEGMENT_WRITE_KEY}`,
      segmentKey: `${process.env.SEGMENT_PUBLIC_KEY}`,
    };
  }

  /**
   * @type {webpack.Configuration}
   */
  const config = {
    entry: [
      "core-js/modules/es.promise",
      "core-js/modules/es.array.iterator",
      "./src/index.tsx",
    ],
    target: "web",
    mode: isDevelopment ? "development" : "production",
    devtool: "source-map",
    module: {
      rules: [
        {
          test: /\.(ts|tsx|mjs|js|jsx)$/,
          exclude: /node_modules/,
          use: [
            {
              loader: require.resolve("babel-loader"),
              options: {
                plugins: [
                  isDevelopment && require.resolve("react-refresh/babel"),
                ].filter(Boolean),
              },
            },
          ],
        },
        {
          enforce: "pre",
          test: /\.js$/,
          loader: "source-map-loader",
        },
        {
          test: /\.(png|svg|jpg|gif|mp3)$/,
          use: ["file-loader"],
        },
        // {
        //   test: /\.css$/i,
        //   loader: "css-loader",
        //   options: {
        //     import: true,
        //   },
        // },
        {
          test: /\.css$/i,
          use: [
            { loader: "style-loader", options: { injectType: "linkTag" } },
            { loader: "file-loader" },
          ],
        },
        {
          test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
          use: [
            {
              loader: "file-loader",
              options: {
                name: "[name].[ext]",
                outputPath: "fonts/",
              },
            },
          ],
        },
      ],
    },
    resolve: {
      modules: [path.resolve(__dirname, "src"), "node_modules"],
      extensions: ["*", ".tsx", ".ts", ".js", ".jsx", ".json"],
    },
    output: {
      filename: "bundle.js",
      path: path.resolve(__dirname, "build"),
      publicPath: "/",
    },
    devServer: {
      historyApiFallback: true,
      disableHostCheck: true,
      host: "0.0.0.0",
      port: env.DEV_SERVER_PORT || 8080,
      hot: true,
    },
    plugins: [
      new HtmlWebpackPlugin(htmlPluginOpts),
      new webpack.DefinePlugin(envKeys),
      isDevelopment && new ReactRefreshWebpackPlugin(),
    ].filter(Boolean),
  };

  if (!isDevelopment) {
    config.optimization = {
      minimize: true,
      minimizer: [
        new TerserPlugin({
          test: /\.(ts|tsx|mjs|js|jsx)$/,
          terserOptions: {
            parse: {
              // We want terser to parse ecma 8 code. However, we don't want it
              // to apply minification steps that turns valid ecma 5 code
              // into invalid ecma 5 code. This is why the `compress` and `output`
              ecma: 8,
            },
            compress: {
              ecma: 5,
              warnings: false,
              inline: 2,
            },
            mangle: {
              // Find work around for Safari 10+
              safari10: true,
            },
            output: {
              ecma: 5,
              comments: false,
              ascii_only: true,
            },
          },

          // Use multi-process parallel running to improve the build speed
          parallel: true,
        }),
      ],
    };
  }

  if (env.ENABLE_ANALYZER) {
    config.plugins.push(new BundleAnalyzerPlugin());
  }
  if (env.ENABLE_PROXY) {
    if (!env.API_SERVER) {
      throw new Error(
        "API_SERVER is not present on .env! Please setup the api server url if you want the proxy to work! API_SERVER example: http://localhost:8080"
      );
    }
    config.devServer.proxy = {
      "/api": {
        logLevel: "debug",
        target: env.API_SERVER, // target host
        changeOrigin: true, // needed for virtual hosted sites
        ws: true, // proxy websockets
      },
    };
  }

  return config;
};
