const { defineConfig } = require('@vue/cli-service');
const webpack = require('webpack');
const path = require('path');
const config = require('./config');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
const AutoImport = require('unplugin-auto-import/webpack');
const Components = require('unplugin-vue-components/webpack');
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers');

const IS_PRODUCTION = process.env.NODE_ENV === 'production';
// 当前场景
const SCENE = process.env.SCENE;

if (SCENE != null) {
  console.log('当前场景:', SCENE);
}

const ENV = getEnv();

module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,

  pages: {
    scene: {
      template: 'public/index.html',
      entry: 'src/main.ts',
      filename: IS_PRODUCTION ? `${SCENE || 'index'}.html` : 'index.html',
      title: process.env.TITLE,
    },
    hotspot: {
      template: 'hotspot/hotspot.html',
      entry: 'hotspot/main.ts',
      filename: IS_PRODUCTION ? `${SCENE ? SCENE + '-hotspot' : 'hotspot'}.html` : 'hotspot.html',
      title: process.env.TITLE,
    },
  },

  outputDir: IS_PRODUCTION && !!SCENE ? `build/${SCENE}` : 'build',
  // 根据场景隔离
  assetsDir: path.posix.join(config.assetsDir, SCENE || ''),

  productionSourceMap: process.env.SOURCE_MAP === 'true' || false,

  css: {
    loaderOptions: {
      sass: {
        additionalData: ENV.sass,
      },
    },
  },

  /**
   * 开发服务器配置
   */
  devServer: {
    compress: true,
    host: '0.0.0.0',
    port: process.env.PORT || 80,
    historyApiFallback: true,
    allowedHosts: 'all',
  },

  configureWebpack: {
    devtool: 'source-map',
    resolve: {
      symlinks: false,
      alias: {
        '@': path.join(__dirname, 'src'),
        '@hotspot': path.join(__dirname, 'hotspot'),
      },
    },
    plugins: [
      new NodePolyfillPlugin(),

      // 扩展 process.env
      new webpack.DefinePlugin(ENV.define),

      AutoImport({
        resolvers: [ElementPlusResolver()],
      }),
      Components({
        resolvers: [ElementPlusResolver()],
      }),
    ],
  },

  chainWebpack: (webpackConfig) => {
    if (SCENE != null) {
      const extensions = webpackConfig.resolve.extensions.values();
      for (let i = extensions.length - 1; i >= 0; i--) {
        webpackConfig.resolve.extensions.prepend(`.${SCENE}${extensions[i]}`);
      }
    }

    webpackConfig.module
      .rule('json')
      .test(/(.*)\.tr$/)
      .use('json-loader')
      .loader('json-loader')
      .end();

    if (IS_PRODUCTION) {
      webpackConfig.plugin('loadshReplace').use(new LodashModuleReplacementPlugin());

      // 主包分割
      webpackConfig.optimization.splitChunks({
        cacheGroups: {
          common: {
            name: 'chunk-common',
            chunks: 'initial',
            minChunks: 2,
            // 一个入口最大的并行请求数
            maxInitialRequests: 4,
            // 形成一个新代码块最小的体积
            minSize: 5000,
            // 缓存组打包的先后优先级
            priority: 1,
            // 如果当前的 chunk 已被从 split 出来，那么将会直接复用这个 chunk 而不是重新创建一个
            reuseExistingChunk: true,
          },
          vendors: {
            name: 'chunk-vendors',
            test: /[\\/]node_modules[\\/]/,
            chunks: 'initial',
            priority: 2,
            reuseExistingChunk: true,
            // 总是为这个缓存组创建 chunks
            enforce: true,
          },
          elementIcons: {
            name: 'element-icons',
            test: /[\\/]node_modules[\\/]@element-plus[\\/]/,
            chunks: 'initial',
            priority: 3,
            reuseExistingChunk: true,
            enforce: true,
          },
          elementPlus: {
            name: 'element-plus',
            test: /[\\/]node_modules[\\/]element-plus[\\/]/,
            chunks: 'initial',
            priority: 3,
            reuseExistingChunk: true,
            enforce: true,
          },
          swiper: {
            name: 'swiper',
            test: /[\\/]node_modules[\\/]swiper[\\/]/,
            chunks: 'initial',
            priority: 3,
            reuseExistingChunk: true,
            enforce: true,
          },
        },
      });
    }
  },
});

/**
 * 初始化环境变量
 */
function getEnv() {
  const constants = config.constants;

  // 扩展内置变量
  for (const key in constants) {
    process.env[`VUE_APP_${key}`] = constants[key];
  }

  // 内置变量
  const vueVariables = ['NODE_ENV', 'BASE_URL'];
  const variableNames = [...vueVariables, 'SCENE', 'HOT_DOMAIN'];
  const variables = [];

  for (const key in process.env) {
    if (key.startsWith('VUE_APP_')) {
      variableNames.push(key);
    }
  }

  variableNames.forEach((name) => {
    variables.push(`${name}: "${process.env[name]}"`);
  });

  return {
    sass: variables.map((d) => `$` + d + ';\n').join(''),
    variableNames,
    variables,
    // 用于 definePlugin
    define: variableNames
      .filter((name) => {
        return !name.startsWith('VUE_APP_') && !vueVariables.includes(name);
      })
      .reduce((prev, cur) => {
        prev[`process.env.${cur}`] = JSON.stringify(process.env[cur]);
        return prev;
      }, {}),
  };
}
