const path = require('path');
const fs = require('fs');
const glob = require('glob');
// const webpack = require('webpack');
const devServerPort = process.env.VUE_APP_DEV_SERVER_PORT || 8090;
const PAGE_PATH = path.resolve(__dirname, './src/pages');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const StaticEnvConfigPlugin = require('@wecity/static-env-config').default;
const TIconReplaceWebpackPlugin = require('@gtff/tdesign-gt-vue/icon/plugin');
const AutoRouterPlugin = require('@gtff/tdesign-gt-vue/plugins/auto-router');
const CSSSplitWebpackPlugin = require('css-split-webpack-plugin').default;
const TerserPlugin = require('terser-webpack-plugin');
const mock = require('./mock');
const packageName = require('./package.json').name;

const LOCAL_DEV = process.env.VUE_APP_MODEL === 'local';

// 本地开发配置代理
// const PROXY = LOCAL_DEV ? require('./proxy') : {};

// 根据启动的模式使用不同的template
const template = LOCAL_DEV ? 'public/local.html' : 'public/index.html';
const isExtract = process.env.NODE_ENV === 'production' || process.env.VUE_APP_CSS_EXTRACT === 'true';

/**
 * 获取页面入口集合 for devServer
 */
function getPagesEntities(pagePath) {
  const entities = {};
  glob.sync(pagePath).forEach((entity) => {
    const moduleName = entity.split('/').slice(-1);
    entities[moduleName] = entity;
  });
  // eg:
  // {
  //  apply_admin: './src/pages/admin_manage/index',
  //  test: './src/pages/test/index'
  // }
  return entities;
}

const pages = getPagesEntities(`${PAGE_PATH}/*`);

const multiPage = {};

Object.keys(pages).forEach((page) => {
  if (!Object.prototype.hasOwnProperty.call(pages, page)) {
    return;
  }
  const configFile = `${PAGE_PATH}/${page}/config.js`;
  const config = fs.existsSync(configFile) ? require(configFile) : {};
  multiPage[page] = {
    // page 的入口
    entry: `src/pages/${page}/main.js`,
    // 模板来源
    template,
    // 在 dist/index.html 的输出
    filename: page === 'index' ? `${page}.html` : `${page}/index.html`,
    // 当使用 title 选项时，
    // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
    title: process.env.VUE_APP_NAME || '智能申报',
    // 在这个页面中包含的块，默认情况下会包含
    // 提取出来的通用 chunk 和 vendor chunk。
    chunks: ['chunk-vendors', 'chunk-common', page],
    ...config,
  };
});

/**
 * 将对应环境的env的环境变量处理成常量，等待注入到static-env-config插件配置中去
 * 只注入VUE_APP_开头的环境变量
 */
const STATIC_ENV_CONFIG = {};
Object.keys(process.env).forEach((key) => {
  if (/^VUE_APP_/.test(key)) {
    Object.assign(STATIC_ENV_CONFIG, {
      [key]: process.env[key],
    });
  }
});

delete STATIC_ENV_CONFIG.VUE_APP_API_BASE_URL;
delete STATIC_ENV_CONFIG.VUE_APP_CDN_PATH;
delete STATIC_ENV_CONFIG.VUE_APP_ROUTER_BASE;

/**
 * 修复生产模式build出来的css background image url(~@)路径不符合预期的问题
 * @type {string[]}
 */
const styles = ['css', 'postcss', 'scss', 'sass', 'less', 'stylus'];
const modules = ['vue-modules', 'vue', 'normal-modules', 'normal'];

const configureWebpackPlugin = [];

/**
 * 本地开发启用hard-source-webpack-plugin
 */
if (LOCAL_DEV) {
  console.log('====>> 启动本地开发缓存');
  configureWebpackPlugin.push(
    new HardSourceWebpackPlugin({
      // 缓存目录，支持相对目录或绝对目录
      // 如果有设置VUE_APP_HARD_SOURCE_FOLDER目录则使用设置值
      // 一般在coding流水线编译使用，把缓存设置到`/data/npm/`中，不会丢失
      cacheDirectory: `${(process.env.VUE_APP_HARD_SOURCE_FOLDER && path.join(process.env.VUE_APP_HARD_SOURCE_FOLDER, '/')) ||
        path.join(process.cwd(), 'node_modules', '/')
        }.cache/hard-source/[confighash]`,
      // 基于package.json中的name来生成不同的hash串用于cacheDirectory的目录
      // @param webpackConfig
      configHash(webpackConfig) {
        return require('node-object-hash')({ sort: false }).hash({ packageName, ...webpackConfig });
      },
      // 根据目录中的lock文件来决定是否重设缓存，如果设置false则需要手动删除
      environmentHash: {
        root: process.cwd(),
        directories: [],
        files: ['package-lock.json', 'yarn.lock'],
      },
      info: {
        // 'none' or 'test'.
        mode: 'none',
        // 'debug', 'log', 'info', 'warn', or 'error'.
        level: 'debug',
      },
      // 自动清除过期、过大缓存
      cachePrune: {
        // 缓存时间：默认7天
        maxAge: 7 * 24 * 60 * 60 * 1000,
        // 超过该处设置的阈值（默认500MB），则自动删除缓存
        sizeThreshold: 500 * 1024 * 1024,
      },
    }),
    new HardSourceWebpackPlugin.ExcludeModulePlugin([
      {
        // HardSource works with mini-css-extract-plugin but due to how
        // mini-css emits assets, assets are not emitted on repeated builds with
        // mini-css and hard-source together. Ignoring the mini-css loader
        // modules, but not the other css loader modules, excludes the modules
        // that mini-css needs rebuilt to output assets every time.
        test: /mini-css-extract-plugin[\\/]dist[\\/]loader/,
      },
    ]),
  );
}

if (isExtract) {
  configureWebpackPlugin.push(
    new CSSSplitWebpackPlugin({
      size: 4000,
      preserve: true,
      filename: 'assets_res/css/[name]-[part].[ext]',
    }),
  );
}

if (process.env.VUE_APP_AUTO_ROUTER === 'true') {
  console.log('====>> 启动自动路由，若不需要请在.env.development文件把[VUE_APP_AUTO_ROUTER]变量删除或者设置为false');
  configureWebpackPlugin.push(new AutoRouterPlugin({ pages: './src/pages/*/views' }));
}
const transpileDependencies = ['tdesign-icons-vue', '@gt4/common-front'];
if (LOCAL_DEV && process.env.VUE_APP_IE === 'true') {
  transpileDependencies.push('sockjs-client');
}
module.exports = {
  lintOnSave: LOCAL_DEV,
  transpileDependencies,
  publicPath: process.env.NODE_ENV === 'production' ? '/' : process.env.VUE_APP_CDN_PATH,
  assetsDir: 'assets_res',
  // 生产模式生成sourcemap
  productionSourceMap: false,
  css: {
    sourceMap: false,
    // 在真实ie9下调试dev需要开始样式分离才能正常加载样式
    extract: isExtract,
  },
  chainWebpack: (config) => {
    // alias注册
    // eg:
    // config.resolve.alias.set('@src', path.resolve(process.cwd(), 'src'));

    /**
     * 修复生产模式build出来的css background-image: url(~@)路径不符合预期的问题
     *  eg: alias to pages/index => ~@/pages/index
     */
    if (process.env.NODE_ENV === 'production') {
      styles.forEach((s) => {
        modules.forEach((m) =>
          config.module
            .rule(s)
            .oneOf(m)
            .use('extract-css-loader')
            .tap((options) => {
              // Set whatever you want as publicPath
              // options.publicPath = process.env.VUE_APP_CDN_PATH;
              // Object.assign(options, {
              //   publicPath: './',
              // });
              return options;
            }),
        );
      });
    }

    config.plugin('static-env-config').use(
      new StaticEnvConfigPlugin({
        //        url: './env.config.js',
        url: '/view/kxtfwzx/env.config.js',
        headResourceTags: [
          {
            tagName: 'link',
            attributes: {
              href: '/favicon.ico',
              rel: 'icon',
            },
          },
        ],
        config: {
          // 这三个必须配置，默认从.env文件中来
          ROUTER_PREFIX: process.env.VUE_APP_ROUTER_BASE,
          API_PREFIX: process.env.VUE_APP_API_BASE_URL,
          RESOURCE_PREFIX: process.env.VUE_APP_CDN_PATH,
          // 把config里面的配置注入到最终的env.config.js中
          ...STATIC_ENV_CONFIG,
        },
      }),
    );

    // 移除prefetch插件
    config.plugins.delete('prefetch-index');
  },

  configureWebpack: {
    // 以下规则用于微前端
    // 让主应用能正确识别微应用暴露出来的一些信息
    output: {
      library: `${packageName}-[name]`,
      libraryTarget: 'umd',
      jsonpFunction: `webpackJsonp_${packageName}`,
    },
    optimization: {
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            compress: {
              warnings: false,
              drop_console: true,
              drop_debugger: true,
            },
          },
        }),
      ],
    },
    plugins: [
      ...configureWebpackPlugin,
      // t-icon替换插件
      new TIconReplaceWebpackPlugin({
        staticPath: 'static_res',
      }),
    ],
  },

  /**
   * 本地开发服务配置
   */
  devServer: {
    port: devServerPort,
    host: '0.0.0.0',
    contentBase: './dist',
    publicPath: process.env.VUE_APP_ROUTER_BASE,
    https: process.env.VUE_APP_PROTOCOL_HTTPS === 'true',
    compress: false,
    disableHostCheck: true,
    overlay: {
      warnings: false,
      errors: true,
    },
    headers: {
      'X-Custom-Foo': 'bar',
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
      'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
    },
    // proxy: {
    //   //   '/api': {
    //   //     // target: 'http://dzswj.mhnsrd.jcsj.tax.cn/sbzx/api/cxssb', // 云测试环境
    //   //     target: 'http://86.20.165.47:8082/dfts/api/sbf/',
    //   //     changeOrigin: true,
    //   //     // 用于将/api从请求路径中移除
    //   //     pathRewrite: {
    //   //       '^/api': '',
    //   //     },
    //   //   },
    //   [process.env.VUE_APP_API_BASE_URL]: {
    //     // target: 'http://dzswj.mhnsrd.jcsj.tax.cn/sbzx/api/cxssb', // 云测试环境
    //     target: 'http://127.0.0.1:48080/', // 苗梓誉职工&单位缴费证明开具
    //     changeOrigin: true,
    //     // 用于将/api从请求路径中移除
    //     pathRewrite: {
    //     //   '^/znsb/api': '',
    //     },
    //   },
    //   '/gs-api': {
    //     target: 'https://zr.jcsk100.com//', // 目标服务器地址  跳转到个税页面，跨域用的
    //     changeOrigin:  true,
    //     pathRewrite:  {
    //       '^/gs-api': ''
    //     }
    //   }
    // },
    before(app) {
      if (process.env.VUE_APP_MOCK === 'true') {
        // 是否开启MOCK，默认开启，检查项目根目录下是否存在.env.development文件 内容为VUE_APP_MOCK=true
        // 设置mock数据路由, 创建get或者post目录，该目录下的文件则为url请求地址
        // app对象、请求方法、url前缀
        // mock.setMock(app, 'get', process.env.VUE_APP_API_BASE_URL);
        // app对象、请求方法、url前缀 eg: user_bulk__delete.json => /api/user/bulk_delete
        // mock.setMock(app, 'post', process.env.VUE_APP_API_BASE_URL);
        // mock.mockSubDirs(app, ['post'], '/abc') // 增加子目录，mock/xxx/post 目录下的文件为url请求地址  eg: user_bulk__delete.json => /xxx/abc/user/bulk_delete
        // 设置mock数据路由, 对应目录下，创建get或者post目录，再请求目录下创建业务目录demo(没有层级层级的限制)，该目录下的文件则为url请求地址 eg: fail.json => /demo/fail
        // app对象、请求方法、url前缀
        mock.setMockByBasePath(app, 'get', process.env.VUE_APP_API_BASE_URL);
        mock.setMockByBasePath(app, 'post', process.env.VUE_APP_API_BASE_URL);
      }
    },
    // ...PROXY,
  },
  /**
   * 插件配置
   */
  pluginOptions: {
    // 添加了插件(@samhammer/vue-cli-plugin-stylelint), 所以需要配置
    lintStyleOnBuild: true,
    stylelint: {
      fix: true, // boolean (default: true)
      files: ['src/**/*.{vue,htm,html,css,sss,less,scss}'], // string | [string]
    },
    // 注入less全局变量
    'style-resources-loader': {
      preProcessor: 'less',
      patterns: [path.resolve(__dirname, './src/styles/variables/*.less')],
    },
  },
  /**
   * 多页应用配置
   */
  pages: multiPage,
};
