const path = require('path');
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
const themeVars = require('./themeVars');
const getCSSModuleLocalIdent = require('./getCSSModuleLocalIdent');
const HappyPack = require('happypack');
const core = 4;
const happyThreadPool = HappyPack.ThreadPool({ size: core });

const TS_LOADER_ID = 'ts-loader';
module.exports = function (options) {
  const {
    context,
    entry,
    output,
    mode,
    watch,
    externals,
    resolveModules,
    htmlTemplatePath,
    definePlugin = {},
    devtool = false,
  } = options;

  const babelLoader = {
    loader: 'babel-loader',
    options: {
      compact: false,
      cacheDirectory: true,
      cwd: context,
      presets: [
        [
          '@babel/preset-env',
          {
            modules: false,
            targets: {
              // esmodules: true,
              browsers: ['defaults', 'iOS >= 10', 'safari >= 10', 'chrome >= 53'],
            },
          },
        ],
        '@babel/preset-react',
      ],
      plugins: [
        [
          'babel-plugin-import',
          {
            libraryName: '@govcloud/gsd-kbone-react',
            libraryDirectory: 'lib/components',
            camel2DashComponentName: false,
          },
        ],
        '@babel/plugin-proposal-class-properties',
        ['@babel/plugin-proposal-decorators', { legacy: true }],
        '@babel/plugin-proposal-export-default-from',
        '@babel/plugin-proposal-export-namespace-from',
        '@babel/plugin-proposal-optional-chaining',
        '@babel/plugin-proposal-partial-application',
        ['@babel/plugin-proposal-pipeline-operator', { proposal: 'minimal' }],
      ].filter(Boolean),
    },
  };
  const typescriptLoader = {
    loader: 'ts-loader',
    options: {
      compilerOptions: {
        target: 'ESNext',
        module: 'ESNext',
        esModuleInterop: true,
      },
      happyPackMode: true,
      transpileOnly: true,
    },
  };

  let plugins = [
    new HappyPack({
      id: TS_LOADER_ID,
      loaders: [babelLoader, typescriptLoader],
      threadPool: happyThreadPool,
    }),
    new HappyPack({
      id: 'babel',
      loaders: [babelLoader],
      threadPool: happyThreadPool,
    }),
    new HtmlWebpackPlugin({
      template: htmlTemplatePath,
      filename: 'index.html',
      cache: false,
    }),
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
      chunkFilename: '[id].[contenthash].css',
    }),
    new webpack.DefinePlugin(
      Object.assign(
        {
          'process.env.isMiniprogram': false, // 注入环境变量，用于业务代码判断
          'process.env.SSR': false,
          'process.env.compileTool': `'webpack'`,
        },
        definePlugin,
      ),
    ),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, '../assets'),
          to: '.',
          noErrorOnMissing: true,
        },
      ],
    }),
    new webpack.HashedModuleIdsPlugin({
      hashFunction: 'sha256',
      hashDigest: 'hex',
      hashDigestLength: 20,
    }),
    new webpack.EnvironmentPlugin({
      SSR: false,
      WEBPACK_ENV: 'production',
    }),
    new VueLoaderPlugin(),
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
  ];

  const commonCSSLoaders = [
    MiniCssExtractPlugin.loader,
    {
      loader: 'css-loader',
      options: {
        modules: {
          auto: true,
          getLocalIdent: getCSSModuleLocalIdent,
        },
        importLoaders: 2,
      },
    },
  ];

  return {
    context,
    entry,
    /**
     * 只要是构建都开启 production 以使用精简
     */
    mode: 'production',
    watch,
    output,
    externals,
    cache: {
      type: 'memory',
    },
    devtool: devtool,
    resolve: {
      extensions: ['.js', '.jsx', '.ts', '.tsx', '.json', '.mjs', '.scss', '.css'],
      modules: [...resolveModules],
      symlinks: false,
      cacheWithContext: false,
      alias: {
        '@': path.resolve(__dirname, '../src'),
      },
    },
    module: {
      rules: [
        {
          test: /\.vue$/,
          loader: require.resolve('vue-loader'),
        },
        {
          test: /\.tsx?$/,
          exclude: /node_modules\/(?!@cloudbase\/weda-ui)|gsd-kbone-react/,
          use: [`happypack/loader?id=${TS_LOADER_ID}`],
        },
        {
          test: /\.(js|jsx)$/,
          exclude:
            /node_modules\/(?!(@cloudbase\/weda-ui)|(@tcwd\/vuera)|(@tcwd\/weapps-core)|(@react-spring)|(@react-hookz))|gsd-kbone-react/,
          use: ['happypack/loader?id=babel'],
        },
        {
          test: /node_modules\/@loadable\/component\/.*\.mjs$/,
          include: /node_modules/,
          type: 'javascript/auto',
        },
        {
          test: /\.(scss|sass)$/,
          use: [
            ...commonCSSLoaders,
            {
              loader: 'sass-loader',
              options: {
                implementation: require('sass'),
              },
            },
          ],
        },
        {
          test: /\.css$/,
          use: [...commonCSSLoaders],
        },
        {
          test: /\.less$/,
          use: [
            ...commonCSSLoaders,
            {
              loader: 'less-loader',
              options: {
                lessOptions: {
                  modifyVars: themeVars,
                  javascriptEnabled: true,
                },
              },
            },
          ],
        },
        {
          test: /\.(jpe?g|png|gif|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
          loader: 'base64-inline-loader',
        },
      ],
    },
    plugins,
    optimization: {
      concatenateModules: true,
      noEmitOnErrors: true,
      splitChunks: {
        maxSize: 3000000,
        cacheGroups: {
          base: {
            test: /(react|react-dom|react-router|react-router-dom|mobx|mobx-react-lite|@cloudbase\/js-sdk)/,
            chunks: 'all',
            minSize: 500000,
            priority: 100, // 优先级
          },
          utils: {
            test: /(lodash|dayjs|axios|kbone-api)/,
            chunks: 'all',
            priority: 100, // 优先级
          },
          'async-commons': {
            chunks: 'async',
            minChunks: 2,
            priority: 20,
          },
          commons: {
            chunks: 'all',
            minChunks: 2,
            priority: 20,
          },
        },
      },
      minimizer: [
        new TerserPlugin({
          test: /\.js(\?.*)?$/i,
          cache: false,
          parallel: true,
          sourceMap: false,
          terserOptions: {
            safari10: true,
          },
        }),
      ],
    },
  };
};
