/** @format */

import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
import { basename, resolve } from 'path';
import dayjs from 'dayjs';
import pkg from '../package.json';
import vueJsx from '@vitejs/plugin-vue-jsx';
import legacy from '@vitejs/plugin-legacy';
import { generateModifyVars } from './less';
import { theme } from './theme';
import { visualizer } from 'rollup-plugin-visualizer';
import duration from 'dayjs/plugin/duration';
import path from 'path';
import { splitVendorChunkPlugin } from 'vite';
import { configMockPlugin } from './plugin/mock/mock';

dayjs.extend(duration);

interface Statistics {
  buildStartTime: number;
  outputOptionsTime: number[];
  closeBundleTime: number;
}

function buildTimePlugin() {
  const statistics: Statistics = {
    buildStartTime: 0,
    outputOptionsTime: [],
    closeBundleTime: 0,
  };
  return {
    name: 'build-time',

    buildStart() {
      statistics.buildStartTime = Date.now();
      console.log('开始打包');
    },

    outputOptions() {
      statistics.outputOptionsTime.push(Date.now());
      if (statistics.outputOptionsTime.length === 1) {
        console.log(
          `分析耗时: ${dayjs
            .duration(
              statistics.outputOptionsTime[statistics.outputOptionsTime.length - 1] -
                statistics.buildStartTime,
            )
            .format('m:s')}`,
        );
      } else {
        console.log(
          `上一步耗时: ${dayjs
            .duration(
              statistics.outputOptionsTime[statistics.outputOptionsTime.length - 1] -
                statistics.outputOptionsTime[statistics.outputOptionsTime.length - 2],
            )
            .format('m:s')}`,
        );
      }
    },

    closeBundle() {
      statistics.closeBundleTime = Date.now();
      if (statistics.outputOptionsTime.length === 1) {
        console.log(
          `分包耗时 ${dayjs
            .duration(statistics.closeBundleTime - statistics.outputOptionsTime[0])
            .format('m:s')}`,
        );
      }

      console.log(
        `总耗时 ${dayjs
          .duration(statistics.closeBundleTime - statistics.buildStartTime)
          .format('m:s')}`,
      );
    },
  };
}
const { dependencies, devDependencies, name, version } = pkg;

export default function nsDefineConfig(params: {
  serviceMode?: 'saas' | 'paas';
  dirname: string;
  baseDir?: string;
  proxy?: object;
  manualChunks?: boolean;
  mock?: boolean;
  mockPath?: string;
}) {
  const {
    serviceMode = 'saas',
    dirname,
    baseDir = '../',
    manualChunks = false,
    mock = false,
    mockPath = `${basename(dirname)}/mock`,
  } = params;

  function pathResolve(dir: string): string {
    return resolve(dirname, '.', dir);
  }

  console.log('mockPath', mockPath);
  // @ts-ignore
  return defineConfig(({ mode, command }) => {
    //运行信息
    const __APP_INFO__ = {
      platform: process.env.PLATFORM,
      pkg: { dependencies, devDependencies, name, version },
      buildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      serviceMode,
    };
    const env = loadEnv(mode, dirname);
    const { VITE_PORT, VITE_PROXY = '{}', VITE_LEGACY, VITE_PUBLIC_PATH } = env;
    const port = Number(VITE_PORT);
    const proxy = params.proxy ? params.proxy : JSON.parse(VITE_PROXY);
    const isBuild = command === 'build';
    const server = {
      host: true,
      port,
      proxy,
      fs: {
        allow: ['..'],
      },
    };
    const config: any = {
      base: VITE_PUBLIC_PATH,
      cacheDir: `${baseDir}node_modules/.vite-${basename(dirname)}`,
      build: {
        assetsDir: 'asset',
        brotliSize: false,
        target: 'es2015',
        rollupOptions: {
          output: {
            manualChunks: (id: string) => {
              const root = basename(dirname);
              const fileName = path
                .normalize(path.relative(root, id))
                .split(path.sep)
                .join(path.posix.sep);

              if (fileName.includes('lib/')) {
                return 'nerv-lib';
              } else if (fileName.includes('src/view/')) {
                return id.toString().split('src/view/')[1].split('/')[0].toString();
              }
            },
          },
        },
      },
      resolve: {
        alias: [
          {
            find: 'vue-i18n',
            replacement: 'vue-i18n/dist/vue-i18n.cjs.js',
          },
          {
            find: /\/@\//,
            replacement: pathResolve('src') + '/',
          },
          {
            find: /\/nerv-lib\//,
            replacement: pathResolve('../lib') + '/',
          },
          {
            find: /\/nerv-base\//,
            replacement: pathResolve(`../lib/${serviceMode}`) + '/',
          },
          {
            find: '@antv/x6',
            replacement: '@antv/x6/dist/x6.js',
          },
          {
            find: 'flv.js',
            replacement: 'flv.js/dist/flv.min.js',
          },
        ],
      },
      server,
      define: {
        __APP_INFO__: JSON.stringify(__APP_INFO__),
      },
      css: {
        preprocessorOptions: {
          less: {
            modifyVars: {
              ...generateModifyVars({
                dark: false,
                paths: [
                  pathResolve(`${baseDir}lib/${serviceMode}/theme/variable.less`),
                  pathResolve('./src/theme/variable.less'),
                ],
              }),
            },
            javascriptEnabled: true,
          },
        },
      },
      plugins: [
        vue(),
        vueJsx(),
        theme({ isProd: mode !== 'development' }),
        VITE_LEGACY &&
          isBuild &&
          legacy({
            targets: ['defaults', 'not IE 11'],
          }),
        createSvgIconsPlugin({
          // 指定需要缓存的图标文件夹
          iconDirs: [
            pathResolve('src/icon'),
            pathResolve(`${baseDir}lib/${serviceMode}/asset/icon`),
          ],
          svgoOptions: isBuild,
          symbolId: 'icon-[dir]-[name]',
        }),
        configMockPlugin({ enable: mock, mockPath }),
        visualizer(),
        isBuild && buildTimePlugin(),
        splitVendorChunkPlugin(),
      ],
    };
    return config;
  });
}