const path = require('path');
const fs = require('fs');
const WebpackBar = require('webpackbar');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
// const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const {
  when,
  whenDev,
  whenProd,
  whenTest,
  ESLINT_MODES,
  POSTCSS_MODES,
} = require('@craco/craco');

const rewireEntries = [
  {
    name: 'shareChart',
    entry: path.resolve(__dirname, './src/shareChart.entry.ts'),
    outPath: 'shareChart.html',
  },
  {
    name: 'shareDashboard',
    entry: path.resolve(__dirname, './src/shareDashboard.entry.ts'),
    outPath: 'shareDashboard.html',
  },
  {
    name: 'shareStoryPlayer',
    entry: path.resolve(__dirname, './src/shareStoryPlayer.entry.ts'),
    outPath: 'shareStoryPlayer.html',
  },
];

const defaultEntryName = 'main';

const appIndexes = ['js', 'tsx', 'ts', 'jsx'].map(ext =>
  path.resolve(__dirname, `src/index.${ext}`),
);

module.exports = {
  babel: {
    plugins: ['babel-plugin-styled-components'],
  },
  webpack: {
    alias: {},
    plugins: [
      new WebpackBar(),
      new MonacoWebpackPlugin({ languages: [''] }),
      // new BundleAnalyzerPlugin(),
    ],
    configure: (webpackConfig, { env, paths }) => {
      // paths.appPath='public'
      // paths.appBuild = 'dist'; // 配合输出打包修改文件目录
      // webpackConfig中可以解构出你想要的参数比如mode、devtool、entry等等，更多信息请查看webpackConfig.json文件
      /**
       * 修改 output
       */
      webpackConfig.output = {
        ...webpackConfig.output,
        ...{
          filename: whenDev(() => 'static/js/bundle.js', 'static/js/[name].js'),
          chunkFilename: 'static/js/[name].[contenthash:8].js',
        },
        // path: path.resolve(__dirname, 'dist'), // 修改输出文件目录
        publicPath: `${process.env.PUBLIC_URL || ''}/`,
      };
      /**
       * webpack split chunks
       */
      webpackConfig.optimization.splitChunks = {
        ...webpackConfig.optimization.splitChunks,
        ...{
          chunks: 'all',
          name: true,
          cacheGroups: {
            chartGraph: {
              name: 'ChartGraph',
              test: /[\\/]app[\\/]components[\\/]ChartGraph[\\/]/,
              priority: 100,
              enforce: true,
            },
            antdDesign: {
              name: 'antdDesign',
              test: /[\\/]node_modules[\\/](@ant-design|antd)[\\/]/,
              priority: 100,
              enforce: true,
            },
            videoReact: {
              name: 'videoReact',
              test: /[\\/]node_modules[\\/](video-react)[\\/]/,
              priority: 100,
              enforce: true,
            },
            reactGridLayout: {
              name: 'reactGridLayout',
              test: /[\\/]node_modules[\\/]react-grid-layout[\\/]/,
              priority: 100,
              enforce: true,
            },
            rc: {
              name: 'rc',
              test: /[\\/]node_modules[\\/](rc-tree|react-color|rc-menu|rc-slider|rc-table|rc-util|rc-picker|rc-select|rc-field-form|rc-motion|@babel|@emotion|react-i18next|redux|react-draggable|lodash-es|dnd-core|rc-virtual-list|rc-tabs|rc-trigger|react-dnd|echarts-wordcloud|tinycolor|rc-pagination|rc-drawer|react-quill|rc-input-number|gl-matrix|react-resizable|redux-undo|rc-cascader|rc-image|rc-upload|resize-obserer-polyfill|d3-color|rc-dialog|rc-textarea|rc-overflow)[\\/]/,
              priority: 100,
              enforce: true,
            },
            echarts: {
              name: 'echarts',
              test: /[\\/]node_modules[\\/](echarts|zrender)[\\/]/,
              priority: 100,
              enforce: true,
            },
            quill: {
              name: 'quill',
              test: /[\\/]node_modules[\\/]quill[\\/]/,
              priority: 100,
              enforce: true,
            },
            lodash: {
              name: 'lodash',
              test: /[\\/]node_modules[\\/](lodash|lodash-es)[\\/]/,
              priority: 100,
              enforce: true,
            },
            reactdnd: {
              name: 'react',
              test: /[\\/]node_modules[\\/](react-beautiful-dnd|react-dnd)[\\/]/,
              priority: 100,
              enforce: true,
            },
            version: {
              name: 'version',
              test: /[\\/]node_modules[\\/](moment|react-dom|core-js|i18next|rc-field-form|buffer|axios|react-redux)[\\/]/,
              priority: 100,
              enforce: true,
            },
          },
        },
      };

      const instanceOfMiniCssExtractPlugin = webpackConfig.plugins.filter(
        plugin => plugin.constructor.name === 'MiniCssExtractPlugin',
      )[0];
      if (instanceOfMiniCssExtractPlugin) {
        instanceOfMiniCssExtractPlugin.options.ignoreOrder = true;
      }

      const defaultEntryHTMLPlugin = webpackConfig.plugins.filter(plugin => {
        return plugin.constructor.name === 'HtmlWebpackPlugin';
      })[0];
      defaultEntryHTMLPlugin.options.chunks = [defaultEntryName];

      // config.entry is not an array in Create React App 4
      if (!Array.isArray(webpackConfig.entry)) {
        webpackConfig.entry = [webpackConfig.entry];
      }

      // If there is only one entry file then it should not be necessary for the rest of the entries
      const necessaryEntry =
        webpackConfig.entry.length === 1
          ? []
          : webpackConfig.entry.filter(file => !appIndexes.includes(file));
      const multipleEntry = {};
      multipleEntry[defaultEntryName] = webpackConfig.entry;

      rewireEntries.forEach(entry => {
        multipleEntry[entry.name] = necessaryEntry.concat(entry.entry);
        // Multiple Entry HTML Plugin
        webpackConfig.plugins.unshift(
          new defaultEntryHTMLPlugin.constructor(
            Object.assign({}, defaultEntryHTMLPlugin.options, {
              filename: entry.outPath,
              // template: entry.template,
              chunks: [entry.name],
            }),
          ),
        );
      });
      webpackConfig.entry = multipleEntry;

      // Multiple Entry Output File
      let names = webpackConfig.output.filename.split('/').reverse();

      if (names[0].indexOf('[name]') === -1) {
        names[0] = '[name].' + names[0];
        webpackConfig.output.filename = names.reverse().join('/');
      }

      // 返回重写后的新配置
      return webpackConfig;
    },
  },
  jest: {
    configure: (jestConfig, { env, paths, resolve, rootDir }) => {
      return Object.assign(jestConfig, {
        setupFiles: ['jest-canvas-mock'],
      });
    },
    modulePaths: ['../'],
  },
  devServer: {
    before: function (app, server, compiler) {
      app.get('/api/v1/plugins/custom/charts', function (req, res) {
        const pluginPath = 'custom-chart-plugins';
        const dir = fs.readdirSync(`./public/${pluginPath}`);
        res.json({
          data: (dir || [])
            .filter(file => path.extname(file) === '.js')
            .map(file => `${pluginPath}/${file}`),
          errCode: 0,
          success: true,
        });
      });
    },
    hot: true,
    port: 8081,
    proxy: {
      '/api/v1': {
        changeOrigin: true,
        target: 'http://116.153.88.3:18081/',
        // target: 'http://localhost:8080/',
      },
      '/resources': {
        changeOrigin: true,
        target: 'http://192.168.3.114:8080/',
      },
      '/login/oauth2': {
        changeOrigin: true,
        target: 'http://192.168.3.114:8080/',
      },
      '/oauth2': {
        changeOrigin: true,
        target: 'http://192.168.3.114:8080/',
      },
    },
    historyApiFallback: {
      rewrites: [
        { from: /^\/$/, to: '/index.html' },
        { from: /^\/shareChart\/\w/, to: '/shareChart.html' },
        { from: /^\/shareDashboard\/\w/, to: '/shareDashboard.html' },
        { from: /^\/shareStoryPlayer\/\w/, to: '/shareStoryPlayer.html' },
      ],
    },
  },
};
