import { ConfigRequire } from '../models/ConfigRequire';
import { ConfigLoader } from './ConfigLoader';
import HttpUtil from '../utils/HttpUtil';
import { logger } from 'mslib';

import * as fs from 'fs';
import * as util from 'util';

export class ConfigLoaderNet extends ConfigLoader {
  /**
   * 加载配置
   * @param configData 配置内容
   */
  async load(
    configData: Map<string, any>,
    configRequires: Array<ConfigRequire>
  ) {
    if (!configRequires || configRequires.length == 0) {
      return;
    }
    for (const configRequire of configRequires) {
      await this.pullConfigFile(configData, configRequire);
    }
  }

  /**
   * 从远程配置中心拉取配置内容
   * @param configData 配置中心加载的配置内容
   * @param configRequire 依赖配置版本，配置代码
   * @param retry 重试次数
   */
  private async pullConfigFile(
    configData: Map<string, any>,
    configRequire: ConfigRequire,
    retry: number = 1
  ) {
    if (retry > 1) {
      return; //超过3就不重试了
    }
    const params = {} as any;
    params['meEnv'] = this.meEnv;
    params['meEnvKey'] = this.meEnvKey;
    params['configCode'] = configRequire.configCode;
    params['version'] = configRequire.version;
    logger.debug(
      '准备加载配置文件--->ENV:%s ,configCode:%s,version：%s ,configServer: %s',
      this.meEnv,
      configRequire.configCode,
      configRequire.version,
      this.configServerUrl!!
    );
    const response = await HttpUtil.get(this.configServerUrl!!, params).catch(
      error => {
        logger.error(
          '加载配置中心配置异常--->ENV:%s ,configCode:%s,version：%s, error :%j',
          this.meEnv,
          configRequire.configCode,
          configRequire.version,
          error
        );
      }
    );
    logger.debug(
      '加载配置文件完成--->ENV:%s ,configCode:%s,version：%s ',
      this.meEnv,
      configRequire.configCode,
      configRequire.version
    );
    let isSuccess = false;
    if (response && response.status === 200) {
      const opResult = response.data;
      if (opResult.code !== 2000) {
        throw new Error('加载配置错误' + opResult.message);
      }
      const config = opResult.data;
      isSuccess = true;
      logger.debug(
        '加载配置中心配置成功--->ENV:%s ,configCode:%s,version：%s ',
        this.meEnv,
        configRequire.configCode,
        configRequire.version
      );
      if (config) {
        const keys = Object.keys(config);
        keys.forEach(key => {
          configData.set(key, config[key]);
        });
        await this.saveToFile(configRequire, config);
      }
    } else {
      logger.error(
        '加载配置中心配置失败--->ENV:%s ,configCode:%s,version：%s, response :%j',
        this.meEnv,
        configRequire.configCode,
        configRequire.version,
        response
      );
    }

    if (!isSuccess) {
      await this.pullConfigFile(configData, configRequire, ++retry);
    }
  }

  /**
   * 配置文件保存到本地
   * @param configRequire
   * @param config
   */
  async saveToFile(configRequire: ConfigRequire, config: any) {
    if (!this.configLocalPath || this.configLocalPath.length == 0) {
      return;
    }
    const fs_writeFile = util.promisify(fs.writeFile);
    const path = this.assembleFilePath(configRequire);
    await fs_writeFile(path, JSON.stringify(config));
  }
}
