/**
 * 
 * @date 2023-02-16 16:29:18
 * @author 鲜伟坚
 */

import axios, { AxiosInstance, AxiosResponse, AxiosRequestConfig } from 'axios';
const querystring = require('querystring');
const moment = require('moment')
const path = require('path')
import * as FormData from 'form-data';
import { Config } from './Config'
import { CryptoUtils } from './CryptoUtils'
import { logger } from "mslib"
import { Helper } from './Helper'

/**
 * 基于Axios框架实现的Http工具
 * @author wufl2019@qq.com
 * @date 2020-06-23
 */
class HttpClient {

    private readonly axios: AxiosInstance;

    private readonly tyAxios: AxiosInstance;

    constructor(_timeout: number = 1000 * 30) {
        this.axios = axios.create({
            timeout: _timeout
        });

        this.axios.interceptors.response.use(res => res.data);

        this.tyAxios = axios.create({
            baseURL: Config.getTYApiConfig().url,
            timeout: _timeout
        })

        this.tyAxios.interceptors.request.use(config => {

            config.headers = Object.assign(config.headers, {
                'Content-Type': 'application/json;charset=utf-8',
                'version': config.headers.version || '1.0.0',
            })

            const data = Object.assign({
                appId: Config.getTYApiConfig().appId,
                appsecret: Config.getTYApiConfig().appsecret,
                reqId: `${Config.getTYApiConfig().appId}-${Helper.uuid()}`,
                ts: `${moment().valueOf()}`,
            }, config.data)

            config.data = Object.assign(data, { key: CryptoUtils.getTYApiSing(data) })

            delete config.data.appsecret

            logger.info('统一平台Request:', `${path.join(config.baseURL, config.url)}`, config?.method?.toUpperCase(), JSON.stringify(config.data))

            return config
        })

        this.tyAxios.interceptors.response.use(res => {
            logger.info('统一平台Response:', JSON.stringify(res.data))
            return res.data
        }, error => {
            logger.error('统一平台Error:', error.message, error?.response?.data)
            return { resCode: '500', resMsg: error.message, data: error?.response?.data }
        })
    }

    tyRequest(conf: AxiosRequestConfig): Promise<any> {
        return this.tyAxios.request(conf)
    }

    /**
     * @desc get请求
     * @param {String} path 请求api路径
     * @param {any} data 参数对象
     * @param {any} config 局部配置 {headers: {'X-Custom-Header': 'foobar'}}
     */
    async get(url: string, data: any = {}, config: any = {}): Promise<any> {
        return await this.axios.get(url, {
            params: data,
            ...config
        })
    }
    async getImg(url: string, data: any = {}, config: any = {}): Promise<any> {
        return await this.axios.get(url, {
            responseType: 'file',
            params: data,
            ...config
        })
    }

    async getImageToBase64(url: string, config: AxiosRequestConfig = {}): Promise<any> {
        const buf: Buffer = await this.axios.get(url, { responseType: 'arraybuffer', ...config })
        return buf.toString('base64')
    }

    /**
     * @desc post表单请求
     * @param {String} path 请求api路径
     * @param {any} data 参数对象
     * @param {any} config 局部配置 {headers: {'X-Custom-Header': 'foobar'}}
     */
    async postForm(url: string, data: any = {}, config: any = {}): Promise<any> {
        if (!config['headers']) {
            config['headers'] = {}
        }
        config['headers']['content-type'] = 'application/x-www-form-urlencoded;charset=utf-8';
        return await this.axios.post(url, querystring.encode(data), config);
    }
    /**
     * @desc post表单请求
     * @param {String} path 请求api路径
     * @param {any} data 参数对象
     * @param {any} config 局部配置 {headers: {'X-Custom-Header': 'foobar'}}
     */
    async postFile(url: string, data: FormData): Promise<any> {
        const formHeaders = data.getHeaders();
        return await this.axios.post(url, data.getBuffer(), {
            headers: {
                ...formHeaders
            }
        });
    }
    /**
     * @desc post JSON
     * @param {String} path 请求api路径
     * @param {any} data 参数对象
     * @param {any} config 局部配置 {headers: {'X-Custom-Header': 'foobar'}}
     */
    async postJson(url: string, params: any = {}, bodyObj: any = {}, config: any = {}): Promise<any> {
        let requestUrl = url
        if (!config['headers']) {
            config['headers'] = {}
        }
        config['headers']['content-type'] = 'application/json;charset=utf-8';
        if (params && Object.keys(params).length) {
            requestUrl = requestUrl + '?' + querystring.encode(params)
        }
        return await this.axios.post(requestUrl, bodyObj, config);
    }

    /**
     * @desc post 
     * @param {String} path 请求api路径
     * @param {any} data 参数对象
     * @param {any} config 局部配置 {headers: {'X-Custom-Header': 'foobar'}}
     */
    async post(url: string, data: any = {}, config: any = {}): Promise<any> {
        return await this.axios.post(url, data, config);
    }

    async tyPost(url: string, data: any = {}, config: any = {}): Promise<any> {
        return await this.tyAxios.post(url, data, config);
    }


    /**
     * @desc request 
     * @param {any} config AxiosRequestConfig
     */
    async request(config: AxiosRequestConfig = {}): Promise<any> {
        return await this.axios.request(config);
    }


    async postFormData(url: string, data: FormData): Promise<any> {
        const formHeaders = data.getHeaders();
        return await this.axios.post(url, data, {
            headers: {
                ...formHeaders
            }
        });
    }

}


// export default new HttpClient();
export { HttpClient }