import { isArray } from 'lodash-es';
import compressPlugin from 'vite-plugin-compression';

import type { Plugin } from 'vite';

export const configCompressPlugin = (compress: BuildCompression): Plugin | Plugin[] | null => {
    if (compress === 'none') return null;

    // framework 模式下 Vite 分 client / ssr 两个环境构建；ssr:false 时 react-router 会删除 dist/server，
    // 压缩插件若在 server 环境的 closeBundle 阶段扫描已被删的目录会报 ENOENT。故只对 client 环境启用压缩
    //（server 产物本就不部署，无需压缩）。
    const onlyClient = (plugin: Plugin): Plugin => ({
        ...plugin,
        applyToEnvironment: (environment) => environment.name === 'client',
    });

    const gz = {
        // 生成的压缩包后缀
        ext: '.gz',
        // 体积大于threshold才会被压缩
        threshold: 0,
        // 默认压缩.js|mjs|json|css|html后缀文件，设置成true，压缩全部文件
        filter: () => true,
        // 压缩后是否删除原始文件
        deleteOriginFile: false,
        // 是否打印详细信息
        verbose: false,
    };
    const br = {
        ext: '.br',
        algorithm: 'brotliCompress',
        threshold: 0,
        filter: () => true,
        deleteOriginFile: false,
        verbose: false,
    };

    const codeList = [
        { k: 'gzip', v: gz },
        { k: 'brotli', v: br },
        { k: 'both', v: [gz, br] },
    ];

    const plugins: Plugin[] = [];

    codeList.forEach((item) => {
        if (compress.includes(item.k)) {
            if (compress.includes('clear')) {
                if (isArray(item.v)) {
                    item.v.forEach((vItem) => {
                        plugins.push(
                            onlyClient(
                                compressPlugin(Object.assign(vItem, { deleteOriginFile: true }))
                            )
                        );
                    });
                } else {
                    plugins.push(
                        onlyClient(
                            compressPlugin(Object.assign(item.v, { deleteOriginFile: true }))
                        )
                    );
                }
            } else {
                if (isArray(item.v)) {
                    item.v.forEach((vItem) => {
                        plugins.push(onlyClient(compressPlugin(vItem)));
                    });
                } else {
                    plugins.push(onlyClient(compressPlugin(item.v)));
                }
            }
        }
    });

    return plugins;
};
