import { ICodeResource, EResourceType, ECodeType, PostcssRpx2Calc } from '@cloudbase/cals';
import { CALC_RPX_ROOT_VAL_NAME } from '../../index';

const remConfig = {
  rootValue: 28,
  propList: ['*'],
  unitPrecision: 5,
  selectorBlackList: [],
  replace: true,
  mediaQuery: false,
  minPixelValue: 0,
};

async function generateStyleModule(
  modules: ICodeResource[] = [],
  cssContextWrapper?: string,
  optsions?: { processCssUnit?: string },
): Promise<{ code: string }[]> {
  const codeModules = modules.filter((item) => item.type === EResourceType.CODE);
  const themeModuels = codeModules.filter((item) => item.codeType === ECodeType.THEME);
  const styleModuels = codeModules.filter((item) => item.codeType === ECodeType.STYLE);
  const { processCssUnit = 'rem' } = optsions || {};
  let processedModules = await Promise.all(
    styleModuels.map(async (module) => {
      try {
        let cssCode = module.code;
        if (cssContextWrapper) {
          cssCode = `${cssContextWrapper} { ${module.code} }`;
        } else if (themeModuels[0]?.code) {
          cssCode = `${themeModuels[0]?.code || ''}\n${cssCode || ''}`;
        }
        const { default: less } = await import(/* webpackChunkName: "extra-package" */ 'less');
        const { default: postcss } = await import(/* webpackChunkName: "extra-package" */ 'postcss');
        const { default: pxToRem } = await import(/* webpackChunkName: "extra-package" */ 'postcss-pxtorem');

        let { css: processedCss } = await less.render(cssCode, { compress: true });
        if (processCssUnit === 'rem') {
          processedCss = await postcss([pxToRem(remConfig)]).process(processedCss).css;
        }
        const { css } = await postcss([PostcssRpx2Calc({ root: `var(${CALC_RPX_ROOT_VAL_NAME})` })]).process(
          processedCss,
        );
        return css ? { ...module, code: css } : null;
      } catch (e) {
        console.error(module.name, 'applyLessCodeStyle error', e);
      }
    }),
  );
  return processedModules.filter((item) => !!item);
}

export async function generateStyleModuleMap(moduleMap: {
  [key: string]: {
    resources: ICodeResource[];
    cssContextWrapper?: string;
    processCssUnit?: 'rem' | 'rpx' | 'px';
  };
}): Promise<{
  [key: string]: ICodeResource & {
    code: string;
  };
}> {
  let resultMap = {};
  let promises = [];
  const { global } = moduleMap;
  const themeModuels = global?.resources?.filter?.((item) => item.codeType === ECodeType.THEME) || [];
  for (const key in moduleMap) {
    promises.push(
      generateStyleModule(
        moduleMap[key].resources?.concat?.(key === 'global' ? [] : themeModuels) || [],
        moduleMap[key].cssContextWrapper,
        { processCssUnit: moduleMap[key].processCssUnit },
      ).then((res) => {
        if (res) {
          resultMap[key] = res;
        }
      }),
    );
  }
  await Promise.all(promises);
  return resultMap;
}
