import { InternalAxiosRequestConfig, AxiosResponse, FormData } from '@ohos/axios';
import { Signature } from '../constants/AppConstants';
import { Logger } from '../utils/Logger';
import { RandomUtil, MD5, JSONUtil, StrUtil } from '@pura/harmony-utils';
import systemDateTime from '@ohos.systemDateTime';

export interface EncryptConfig extends InternalAxiosRequestConfig {
  startTime?: number;
  params?: Record<string, string | number | boolean | null | undefined>;
}

export class RequestInterceptor {
  static readonly TAG: string = "RabbitLog_Request";

  static async onPrepare(config: EncryptConfig): Promise<EncryptConfig> {
    config.startTime = Date.now();

    // 1. 获取请求方法
    const method = (config.method ?? "get").toLowerCase();

    // 2. 准备基础参数 (Query Params)
    config.params = config.params || {};
    config.params.nonce = RandomUtil.generateUUID36()
    config.params.timestamp = Math.trunc(systemDateTime.getTime() / 1000)

    // 3. 对 Query 参数进行字典排序并拼接
    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))

    // 4. 准备签名盐值
    let signature = MD5.digestSync(sortQueryString + '&' + MD5.digestSync(Signature));

    // 5. 【核心判断】识别是否为文件上传
    const contentType = String(config.headers?.['Content-Type'] || "");
    const isFormData = config.data instanceof FormData || contentType.includes('multipart/form-data');

    // 6. 根据请求类型和内容计算签名
    if ((method === 'post' || method === 'put') && config.data) {
      if(!isFormData){
        let dataStr = JSON.stringify(config.data);
        if (StrUtil.isNotEmpty(dataStr)) {
          signature = MD5.digestSync(sortQueryString + '&' + dataStr + "&" + MD5.digestSync(Signature));
        }
      }
    }

    // 7. 回填带签名的参数
    config.params.signature = signature;

    // 8. 打印请求日志
    RequestInterceptor.logRequest(config, isFormData);

    return config;
  }

  static onResponse(response: AxiosResponse): AxiosResponse {
    const config = response.config as EncryptConfig;
    const startTime: number = config.startTime ?? Date.now();
    RequestInterceptor.logResponse(response, startTime);
    return response;
  }

  private static logRequest(config: EncryptConfig, isFormData: boolean): void {
    let logString = `\n┌─── 📤 Request [ ${config.method?.toUpperCase()} ] ───\n`;
    logString += `│ Url: ${config.baseURL}${config.url}\n`;
    logString += `│ Final Params: ${JSON.stringify(config.params)}\n`;

    if (isFormData) {
      logString += `│ Body: [ Multipart/FormData - File Upload ]\n`;
    } else {
      logString += `│ Body: ${JSON.stringify(config.data)}\n`;
    }
    logString += `└─────────────────────────────────────\n`;
    Logger.info(RequestInterceptor.TAG, logString);
  }

  private static logResponse(response: AxiosResponse, startTime: number): void {
    const duration: number = Date.now() - startTime;
    const config = response.config as EncryptConfig;

    // 0. 完整的请求地址（包含参数拼接）
    let fullUrl = `${config.baseURL ?? ""}${config.url ?? ""}`;
    const params = config.params;
    let queryStr = "";
    if (params !== undefined && params !== null) {
      const keys = Object.keys(params);
      if (keys.length > 0) {
        const queryParts: string[] = [];
        for (const key of keys) {
          const value = params[key];
          if (value !== undefined && value !== null) {
            queryParts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
          }
        }
        queryStr = queryParts.join('&');
        const separator = fullUrl.includes('?') ? '&' : '?';
        fullUrl += `${separator}${queryStr}`;
      }
    }

    // 1. 获取完整的 Data 字符串
    const dataStr: string = JSON.stringify(response.data);

    // 2. 构造基础信息
    let header ='';
    header =`\n┌─── 📥 响应开始🔜Response [ ${response.status} ] [ ${duration}ms ] ───\n`;
    header += `│ Full URL: ${fullUrl}\n`;
    header += `│ Data Content: `;

    // 3. 拼接完整报文
    const fullLog = header + dataStr + `\n└────────────────────响应结束🔚─────────────────`;

    // 4. 执行分段连贯打印
    RequestInterceptor.printInChunks(fullLog);
  }

  /**
   * 分段打印并确保数据完全打印
   */
  private static printInChunks(message: string): void {
    const CHUNK_SIZE = 3000;
    let start = 0;

    while (start < message.length) {
      let end = Math.min(start + CHUNK_SIZE, message.length);
      let chunk = message.substring(start, end);
      Logger.info(RequestInterceptor.TAG, chunk);

      start = end;
    }
  }



  /*
  private static logResponse(response: AxiosResponse, startTime: number): void {
    const duration: number = Date.now() - startTime;
    const config = response.config as EncryptConfig; // 显式类型转换

    // 1. 安全地获取 BaseURL 和 URL
    const baseUrl: string = config.baseURL ?? "";
    let urlPath: string = config.url ?? "";
    let fullUrl: string = `${baseUrl}${urlPath}`;

    // 2. 强类型处理 Query Params (对应 Android 的 request.url().toString())
    const params = config.params;
    if (params !== undefined && params !== null) {
      const keys: string[] = Object.keys(params);
      if (keys.length > 0) {
        const queryParts: string[] = [];
        for (const key of keys) {
          const value = params[key];
          if (value !== undefined && value !== null) {
            queryParts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
          }
        }
        const queryString: string = queryParts.join('&');
        const separator: string = fullUrl.includes('?') ? '&' : '?';
        fullUrl += `${separator}${queryString}`;
      }
    }

    // 3. 构造日志字符串
    let logString =''
    logString =`\n┌─── 📥 Response [ ${String(response.status)} ] ───\n`;
    logString += `│ Time: ${String(duration)}ms\n`;
    logString += `│ Full Request URL: ${fullUrl}\n`;

    // 4. 处理 Response Data (禁止使用 any，需转换为 string)
    const dataObj = response.data as object; // 假设返回的是对象
    const dataStr: string = JSON.stringify(dataObj);
    const displayData: string = dataStr.length > 1000
      ? `${dataStr.substring(0, 1000)}... [Truncated]`
      : dataStr;

    logString += `│ Data: ${displayData}\n`;
    logString += `└─────────────────────────────────────\n`;

    Logger.info(RequestInterceptor.TAG, logString);
  }
  */
}

/**
 * 时间同步工具
 */
export class TimeSync {
  static timeOffset: number = 0; // 服务器时间 - 本地时间

  static async sync(serverTimeStr: string) {
    const serverTime = parseInt(serverTimeStr, 10);
    const localTime = Math.trunc(Date.now() / 1000);
    TimeSync.timeOffset = serverTime - localTime;
    console.info(`[TimeSync] Offset calculated: ${TimeSync.timeOffset}s`);
  }

  static getCorrectedTime(): number {
    // return Math.trunc(Date.now() / 1000) + TimeSync.timeOffset;
    return Math.trunc(systemDateTime.getTime() / 1000);
  }
}
