import {
  deserializeValue,
  IPlatformApp,
  PropBindType,
  deserializeDynamicMap,
} from '@cloudbase/cals';
import { isEmptyObj } from '../common';
import { generateDataBindForDataset } from './generate';
/**
 * 将对象的key的首字母转换为小写
 * { UserName: 'xxx', Id: 'xxxx'} => { userName: 'xxx', id: 'xxx' }
 * 默认只处理最外层, 若 deep 为 true, 则递归处理
 */
function lowercaseKey(obj: any, deep?: boolean): any {
  if (!obj || typeof obj !== 'object') return obj;
  if (Array.isArray(obj)) return obj.map((item) => lowercaseKey(item, deep));
  const result: Record<string, any> = {};
  return Object.keys(obj).reduce((acc, key) => {
    const smallCase = key.charAt(0).toLowerCase() + key.slice(1);
    const val = obj[key];
    acc[smallCase] = deep ? lowercaseKey(val, deep) : val;
    return acc;
  }, result);
}

/**
 * 标准化从云API获取的数据源结构
 *  1. 将大写转换为小写
 *  2. 将 methods 和 methods 从字符串转换为对象
 */
function standardizeDataSource(ds: any) {
  const transformed = lowercaseKey(ds, false);
  try {
    const { schema } = ds;
    if (typeof transformed.schema === 'string') {
      transformed.schema = JSON.parse(transformed.schema);
    }
    if (!transformed.schema || typeof transformed.schema !== 'object') {
      // console.warn(
      //   '[standardizeDataSource]invalid schema',
      //   schema,
      //   'in datasource',
      //   transformed
      // );
      transformed.schema = {};
    }
  } catch (error) {
    // console.warn(
    //   '[standardizeDataSource] unable to transform schema',
    //   transformed.schema
    // );
    transformed.schema = {};
  }
  try {
    const { methods } = ds;
    if (typeof transformed.methods === 'string') {
      transformed.methods = JSON.parse(transformed.methods);
    }
    if (!Array.isArray(transformed.methods)) {
      // console.warn(
      //   '[standardizeDataSource]invalid methods',
      //   methods,
      //   'in datasource',
      //   transformed
      // );
      transformed.methods = [];
    }
  } catch (error) {
    // console.warn(
    //   '[standardizeDataSource]unable to transform methods',
    //   transformed.methods
    // );
    transformed.methods = [];
  }
  return transformed;
}

/**
 * 简化数据源描述信息数组, 以供低码运行时使用
 * @param datasources 完整的数据源描述信息数组
 */
export function getDatasourceProfiles(datasources) {
  return (
    datasources?.map((item) => {
      const ds = standardizeDataSource(item);
      return {
        id: ds.id,
        title: ds.title,
        name: ds.name,
        type: ds.type,
        childDataSourceNames: ds.childDataSourceNames,
        schema: ds.schema,
        methods:
          ds.methods &&
          ds.methods.map((method) => {
            return {
              name: method.name,
              type: method.type,
            };
          }),
      };
    }) || []
  );
}

function _generateDynamicDataset(ctx, dataset) {
  const { looseError = false } = ctx;
  // 这里的动作实际上是一个有副作用的动作，所以这里进行一个简单的深拷贝
  let result = JSON.parse(JSON.stringify(dataset));
  let { state } = result;
  if (state) {
    for (let key in state) {
      let config = state[key];
      if (config.varType === 'datasource' && config.initMethod?.params) {
        let params = deserializeDynamicMap(ctx, config.initMethod.params || {});
        if (params && !isEmptyObj(params)) {
          let processed = {};
          for (let paramKey in params) {
            let bind = params[paramKey];
            try {
              processed[paramKey] = generateDataBindForDataset({
                propertyPath: paramKey,
                bindDataPath: bind.value,
                type: bind.type as any,
              });
            } catch (e) {
              if (!looseError) {
                throw e;
              } else {
                console.warn(
                  `generate dataset ${key}'s param: ${paramKey} error:`,
                  e
                );
              }
            }
          }
          config.initMethod.params = processed;
        }
      }
    }
  }
  return result;
}

export function getDatasetProfiles(
  cals: IPlatformApp,
  apps?: IPlatformApp[],
  options?: {
    looseError?: boolean;
  }
) {
  const result = {};
  if (cals.dataset) {
    result['$global'] = _generateDynamicDataset(
      { app: cals, looseError: options.looseError },
      cals.dataset
    );
  }
  (apps || []).forEach((app) => {
    app.items?.forEach((page) => {
      if (page.dataset) {
        result[
          app.extra?.rootPath ? `${app.extra.rootPath}/${page.id}` : page.id
        ] = _generateDynamicDataset(
          { app: cals, page: page, looseError: options.looseError },
          page.dataset
        );
      }
    });
  });
  return result;
}

export function getConfig(
  cals,
  options?: {
    deployOptions?: {
      mode: 'production' | 'preview';
    };
    looseError?: boolean;
  }
) {
  return {
    /** 当前是否处于正式发布模式 */
    isProd: false || options?.deployOptions?.mode === 'production',
    /** 低码应用ID */
    appID: (cals as any).id || (cals as any).appId || '',
    /** 云开发环境ID */
    envID: cals.extra?.envId || cals.envId,
    /** 应用端ID */
    tcbClientId: cals.extra?.clientId,
    /** 数据源描述对象数组 */
    dataSourceProfiles: getDatasourceProfiles(cals.dataSources || []),
    /**
     * 新的dataset变量配置对象
     *  key 为页面ID(全局为$global), val 为变量配置数组
     */
    datasetProfiles: getDatasetProfiles(cals, [cals], {
      looseError: options?.looseError,
    }),
  };
}
