import axios, { AxiosError, AxiosRequestConfig, AxiosResponse,
  FormData,
  InternalAxiosRequestConfig } from '@ohos/axios';
import BuildProfile from 'BuildProfile';
import { Constants } from '../common/Constants';
import deviceInfo from '@ohos.deviceInfo';
import { AppUtil, DeviceUtil, JSONUtil, MD5, RandomUtil, StrUtil } from '@pura/harmony-utils';
import systemDateTime from '@ohos.systemDateTime';
import { JSON } from '@kit.ArkTS';
import { AESpkcs7paddingUtil } from '../utils/AESpkcs7paddingUtil';
import { HttpResult } from './HttpResult';
import { plainToInstance } from 'class-transformer';
import { LoginManager } from '../manager/LoginGlobalManager';
import { router } from '@kit.ArkUI';
import { RouterUrls } from '../common/RouterUrls';
import { EventConstants } from '../common/EventConstants';

const instance = axios.create({
  baseURL: BuildProfile.DEBUG ? Constants.TEST_URL : Constants.BASE_URL,
  timeout: 20000
});

// 请求头拦截器
instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
  config.headers.set('x-token', LoginManager.getToken())
  config.headers.set('x-app-id', Constants.APP_ID)
  config.headers.set('x-device-id', DeviceUtil.getDeviceId())
  config.headers.set('x-version', BuildProfile.VERSION_NAME)
  config.headers.set('x-mobile-brand', deviceInfo.brand)
  config.headers.set('x-mobile-model', deviceInfo.productModel)
  config.headers.set('x-base-version', BuildProfile.VERSION_NAME)
  config.headers.set('x-package', 'com.yuan.scmf')
  config.headers.set('x-platform', 'android')
  config.headers.set('x-channel', 'scmf_hmos')
  return config;
}, (error: AxiosError) => {
  return Promise.reject(error);
});

// 请求内容拦截器
instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
  let url = config.url;
  if (!url?.includes("user/upload")) {
    let method = config.method?.toLowerCase();
    if (method === "post" || method === "put") {
      config.headers.set("Content-Type", "application/json; charset=utf-8");
    } else if (method === 'delete') {
      config.headers.set("Content-Type", "application/x-www-form-urlencoded");
    }
  }
  return config;
}, (error: AxiosError) => {
  return Promise.reject(error);
});

// 请求内容加密拦截器
instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
  if (config.baseURL === Constants.BASE_URL) {
    config.params = config.params || {};
    config.params.nonce = RandomUtil.generateUUID36()
    config.params.timestamp = Math.trunc(systemDateTime.getTime() / 1000)
    let paramsMap = JSONUtil.jsonToMap(JSON.stringify(config.params));
    let arrayMap = Array.from(paramsMap);
    arrayMap.sort((a, b) => {
      return a[0].localeCompare(b[0])
    })
    paramsMap = new Map(arrayMap)
    let sortQueryString = "";
    paramsMap.forEach((value, key) => {
      sortQueryString += key + "=" + value + "&"
    })
    sortQueryString = encodeURI(sortQueryString.substring(0, sortQueryString.length - 1))
    let signature = MD5.digestSync(sortQueryString + '&' + MD5.digestSync(Constants.SIGNATURE));
    let method = config.method?.toLowerCase();
    if (method === "post" || method === "put") {
      if (config.data) {
        let dataStr = JSON.stringify(config.data);
        if (StrUtil.isNotEmpty(dataStr)) {
          signature = MD5.digestSync(sortQueryString + '&' + dataStr + "&" + MD5.digestSync(Constants.SIGNATURE));
        }
      }
    }
    config.params.signature = signature;
  }
  return config;
}, (error: AxiosError) => {
  return Promise.reject(error);
});

// 响应拦截器
instance.interceptors.response.use((response: AxiosResponse) => {
  if (response.config.baseURL === (BuildProfile.DEBUG ? Constants.TEST_URL : Constants.BASE_URL)) {
    try {
      let contentType = response.headers['content-type'] as string;
      let dataString: string = '';
      if (StrUtil.isNotEmpty(contentType) && contentType?.includes("application/json")) {
        if (response.data !== null) {
          let isEncrypt = response.data['encrypt'] as boolean
          dataString = response.data['data'] as string;
          if (isEncrypt) {
            dataString = AESpkcs7paddingUtil.decryptNormal(dataString, Constants.ENCRYPT);
            let decData = JSON.parse(dataString) as Record<string, Object>;
            let decCode = decData['code'] as number;
            switch (decCode) {
              case 11018: {
                // 刷新首页
                AppUtil.getContext().eventHub.emit(EventConstants.HomeRefreshEvent);
                AppUtil.getContext().eventHub.emit(EventConstants.MineRefreshEvent);
                break;
              }
              case 19000: {
                // 跳转Vip页面
                router.push({url: RouterUrls.VIP_PAGE, params: { origin: response.config.url }})
                break;
              }
              case 1001003: {
              }
              case 1001004: {

              }
              case 1001005: {
                // 跳转登录
                LoginManager.logout()
                router.push({url: RouterUrls.LOGIN_PAGE})
                break;
              }
            }
          } else {
            let newResponse: Record<string, Object> = {
              'code': 0,
              'data': dataString
            }
            dataString = JSON.stringify(newResponse)
          }
        }
      }
      response.data = JSON.parse(dataString);
      console.error('AxiosResponse：' + JSON.stringify(response.data))
      return plainToInstance(HttpResult, JSON.parse(dataString));
    } catch (e) {
      console.log(e);
      return new HttpResult(-1, e);
    }
  }
  return response.data;
}, (error: AxiosError) => {
  // 响应失败
  return Promise.reject(error);
});

export class AxiosRequest {
  // 万能请求
  static request<T>(config: AxiosRequestConfig): Promise<T> {
    return instance.request<null, T>(config)
  }

  // get请求
  static get<T>(url: string, params?: object): Promise<T> {
    return instance.get<null, T>(url, { params });
  }

  // post请求
  static post<T>(url: string, data?: object): Promise<T> {
    return instance.post<null, T>(url, data);
  }

  // put请求
  static put<T>(url: string, data?: object): Promise<T> {
    return instance.put<null, T>(url, data);
  }

  // delete请求
  static delete<T>(url: string, params?: object): Promise<T> {
    return instance.delete<null, T>(url, { params });
  }
}