import fs, { readdirSync } from 'fs';
import path from 'path';
import type { UserConfig, PluginOption } from 'vite';
import { themePreprocessorPlugin } from '@crami/vite-plugin-theme-preprocessor';
import { defaultsDeep } from 'lodash-es';
import colors from 'colors';

const ADDITIONALFILENAME = 'app.less';
const THEMEVARIABLESFILENAME = 'variables.less';
const PATHRESOLVETO = '../src/theme/';
const uuid = `.${new Date().getTime()}`;

type IThemeUserConfig = {
  env: IThemeEnvConfig;
  userConfig: UserConfig;
};

type IThemeConfig = {
  additionalDataName: string;
  themesName: string[];
  defaultThemeName: string;
  rootPath: string;
};

type IThemeLoadConfigOptions = {
  defaultThemeName: string;
};

type IThemeEnvConfig = {
  VITE_ENV_THEME_DEFAULT: string;
};

const loadConfig = (options: IThemeLoadConfigOptions) => {
  const dirname = __dirname;
  const { defaultThemeName } = options;
  const config: IThemeConfig = {
    additionalDataName: '',
    themesName: [],
    defaultThemeName: '',
    rootPath: '',
  };

  const themeRootPath = path.resolve(dirname, PATHRESOLVETO);
  let dir;
  try {
    dir = readdirSync(themeRootPath);
  } catch (e) {
    console.log(
      colors.red.underline('project file directory not exist the "src/theme/default" folder!'),
    );
    return null;
  }

  if (dir.includes(ADDITIONALFILENAME)) {
    config.additionalDataName = ADDITIONALFILENAME;
  }

  dir.forEach(name => {
    const themePath = path.resolve(themeRootPath, `./${name}`);
    const stats = fs.statSync(themePath);

    if (stats.isDirectory()) {
      const dir = readdirSync(themePath);
      if (dir.includes(THEMEVARIABLESFILENAME)) {
        config.themesName.push(name);
      }
    }
  });

  config.defaultThemeName = defaultThemeName || config.themesName[0] || 'default';
  config.rootPath = themeRootPath;

  return config;
};

const addCssAdditionalDataConfig = (themeConfig: IThemeConfig, userConfig: UserConfig) => {
  const _config: UserConfig = {
    css: {
      preprocessorOptions: {
        less: {
          additionalData: (content, filePath) => {
            const srcAppLess =
              path.resolve(themeConfig.rootPath, '..').replace(/\\/g, '/') + '/app.less';

            if (filePath === srcAppLess) {
              const _content = `${content} \n @import "./theme/app.less";`;
              return _content;
            }

            return content;
          },
          javascriptEnabled: true,
        },
      },
    },
  };
  defaultsDeep(userConfig, _config);
};

interface IUserConfig extends UserConfig {
  plugins: PluginOption[];
  optimizeDeps: {
    exclude: string[];
  };
}

const addThemePreprocessorPluginConfig = (themeConfig: IThemeConfig, userConfig: UserConfig) => {
  const pluginConfig: UserConfig = {
    plugins: [],
    optimizeDeps: {
      exclude: [],
    },
  };
  defaultsDeep(userConfig, pluginConfig);

  const config = userConfig as IUserConfig;

  config.plugins = [
    ...config.plugins,
    themePreprocessorPlugin({
      less: {
        // 是否启用任意主题色模式，这里不启用
        arbitraryMode: false,
        // 提供多组变量文件
        multipleScopeVars: themeConfig.themesName.map(name => {
          const _path = path.resolve(themeConfig.rootPath, `./${name}/${THEMEVARIABLESFILENAME}`);
          //console.log(_path);
          return {
            scopeName: name,
            path: _path,
          };
        }),
        defaultScopeName: themeConfig.defaultThemeName,
        // 在生产模式是否抽取独立的主题css文件，extract为true以下属性有效
        // !!!【注意】这里必须是true
        extract: true,
        customThemeCssFileName: scopeName => scopeName + uuid,
        removeCssScopeName: true,
      },
    }),
  ];

  config.optimizeDeps.exclude = [
    ...config.optimizeDeps.exclude,
    //【注意】 排除 import { toggleTheme } from "@crami/vite-plugin-theme-preprocessor/dist/browser-utils"; 在vite的缓存依赖
    // 否则会造成切换失效
    '@crami/vite-plugin-theme-preprocessor/dist/browser-utils',
  ];
};

const addThemeConfig = (options: IThemeUserConfig) => {
  const { env, userConfig } = options;
  const { VITE_ENV_THEME_DEFAULT: defaultThemeName } = env;
  const themeConfig = loadConfig({ defaultThemeName });
  if (!themeConfig) {
    return;
  }
  if (themeConfig.additionalDataName) {
    addCssAdditionalDataConfig(themeConfig, userConfig);
  }
  if (themeConfig.themesName && themeConfig.themesName.length > 0) {
    addThemePreprocessorPluginConfig(themeConfig, userConfig);
  }
};

export { addThemeConfig };
