/**
 * ali-oss模块
 * @date 2022-03
 * @author 何华东
 */

 import { logger } from 'mslib';
import { Stream } from 'stream';
 import { Singleton } from 'typescript-ioc';
 import { IocConfigProvider } from './Config';
 import { ConfigCenterConfigProvider } from './ConfigCenter';
 import Contants from './Contants';
 import { OssService } from './OssService';
 const OSS = require('ali-oss');
 
 /**
  * ali-oss客户端实例
  * 
  * 如已引用配置依赖[NsConfig](https://me.keytop.cn/service/config)将会自动创建该实例
  * 
  * ```
  * import { aliOss, aliOssClient } from "refs/nslib";
  * 
  * let res = await aliOssClient.put(`${filename}`, buffer);
  * aliOss.throwIfUrlIsEmpty(res);
  * let url = res.url;
  * ```
  * @see [ali-oss](https://www.npmjs.com/package/ali-oss)
  */
 export let aliOssClient = null;
 
 init();
 
 async function init() {
     try {
         //配置优先级: 1.本地配置 2.配置中心
         let config = IocConfigProvider.getAliOssConfig() || await ConfigCenterConfigProvider.getAliOssConfig();
         if (!config) return;
 
         //默认启用安全配置secure(使用https文件地址)
         config = Object.assign({ secure: true }, config);
         aliOssClient = new OSS(config);
 
         logger.info(`ali-oss客户端实例创建成功,region:${config.region}`);
     } catch (error) {
         logger.error('ali-oss客户端实例创建失败', error);
     }
 }
 
 /**
  * ali-oss响应类
  */
 type AliOssResponse = {
     name: string;
 
     /**
      * 文件地址
      */
     url: string;
 
     res: {
         status: number;
         statusCode: number;
         statusMessage: string;
     };
 }
 
 /**
  * 如果`ali-oss`接口返回的文件地址为空，则抛出异常
  * 
  * @throws {@link Error} if `!response?.url`
  */
 export function throwIfUrlIsEmpty(response: AliOssResponse) {
     if (!response?.url) {
         throw new Error(`ali-oss返回文件地址为空,返回值:${JSON.stringify(response)}`);
     }
 }
 
 /**
  * ali-oss服务
  * 
  * @see {@link OssService}
  */
 @Singleton
 export class AliOssService implements OssService {
     /**
      * 获取对象存放根目录
      */
     getRootPath() {
         return Contants.P_ID || IocConfigProvider.getBasicConfig()?.tapdId || 'non-standard';
     }
 
     /**
      * 上传对象到ali-oss
      * 
      * @returns 对象地址
      */
     async put(data: string | Buffer | Stream, name: string): Promise<string> {
         let fullname = `${this.getRootPath()}/${name}`;
         let res: AliOssResponse = await aliOssClient.put(fullname, data);
         throwIfUrlIsEmpty(res);
 
         logger.info(`ali-oss 上传对象成功,对象访问地址:${res.url}`);
 
         return res.url;
     }
 }