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

import { logger } from 'mslib';
import path = require('path');
import { Singleton } from 'typescript-ioc';
import { IocConfigProvider, Config } from './Config';
import { ConfigCenterConfigProvider } from './ConfigCenter';
import Contants from './Contants';
import { OssService } from './OssService';
import { uuid } from './Utils';
const OSS = require('ali-oss');

/**
 * ali-oss客户端实例
 * 
 * 如果项目已添加配置依赖[NsConfig](https://me.keytop.cn/service/config)，
 * 那么模块被加载时，从`@Value`获取`ali-oss`配置({@link ConfigCenterConfigProvider})并自动创建该实例，否则为空
 * 
 * ```ts
 * import { aliOss, aliOssClient } from "refs/nslib";
 * 
 * //非标/上传base64图片到ali-oss
 * let res = await aliOss.putBase64Image('data:image/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAA...');
 * throwIfUrlIsEmpty(res);
 * let imgUrl = res.url;
 * 
 * //直接使用插件原生方法上传文件
 * let res = await aliOssClient.put(`${filename}`, buffer);
 * throwIfUrlIsEmpty(res);
 * let url = res.url;
 * ```
 * @see [ali-oss](https://www.npmjs.com/package/ali-oss)
 */
export let aliOssClient;

init();

async function init() {
    try {
        let config = IocConfigProvider.getAliOssConfig();
        if (!config) config = await ConfigCenterConfigProvider.getAliOssConfig();
        if (!config) return;

        //默认启用安全配置secure(使用https文件地址)
        config = Object.assign({ secure: true }, config);
        aliOssClient = new OSS(config);

        logger.info(`ali-oss客户端实例创建成功`);
    } catch (error) {
        logger.error('ali-oss客户端实例创建失败', error);
    }
}

/**
 * ali-oss响应类
 */
type AliOssResponse = {
    name: string;

    /**
     * 文件地址
     */
    url: string;

    res: {
        status: number;
        statusCode: number;
        statusMessage: string;
    };
}

/**
 * 如果`ali-oss`接口返回的文件地址为空，则抛出异常
 */
export function throwIfUrlIsEmpty(response: AliOssResponse) {
    if (!response?.url) {
        throw new Error(`ali-oss返回文件地址为空,返回值:${JSON.stringify(response)}`);
    }
}

@Singleton
export class AliOssService implements OssService {
    getRootPath() {
        return Contants.P_ID || IocConfigProvider.getBasicConfig()?.tapdId || 'tapdId';
    }

    /**
     * 上传对象到ali-oss
     */
    async put(data: string | Buffer, 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;
    }
}