/**
 * 接口加解密策略管理
 *
 * 加密条件：
 * 1. 加密开关开启（接口级 > 全局）
 * 2. 请求方法是 POST 或 PUT
 * 3. 请求路径不在白名单内
 * 4. Content-Type 包含 application/json
 * 5. 请求数据存在且不是特殊类型（FormData/Blob等）
 *
 * 解密条件：
 * 1. 加密开关开启（接口级 > 全局）
 * 2. 响应 Content-Type 包含 application/json
 * 3. 响应数据符合 Base64 密文特征
 */

// ==================== 配置 ====================

/** 加密白名单：这些路径的请求不加密 */
export const ENCRYPT_WHITE_LIST = [
  "/doc.html",
  "/swagger-ui/**",
  "/v2/api-docs",
  "/swagger-resources/**",
  "/webjars/**",
  "/actuator/**",
  "/favicon.ico",
  "/error",
  "/test/**",
  "/xxl-job-admin/**",
  "/payment/notify",
  "/lawyer/img/upload",
  "/file/upload/**",
  "/file/**",
  "/video/moderation/submit",
  "/video/moderation/processTask",
  "/template/download/**",
  "/store/img/upload",
  "/ai/upload",
  "/store/platform/login",
  "/license/upload",
  "/base/data/export",
  "/sys/login",
  "/sys/logout"
];

/** 支持加密的请求方法 */
const ENCRYPT_METHODS = ["POST", "PUT"];

// ==================== 工具函数 ====================

/**
 * 判断是否启用加密（接口级配置优先于全局配置）
 */
function isEncryptEnabled(config: any): boolean {
  if (config?.encrypt !== undefined) {
    return !!config.encrypt;
  }
  return import.meta.env.VITE_API_ENCRYPTION_ENABLED === "true";
}

/**
 * 获取请求头中的 Content-Type
 */
function getContentType(headers: any): string {
  if (!headers) return "";
  // 兼容 AxiosHeaders 和普通对象
  if (typeof headers.get === "function") {
    return headers.get("Content-Type") || headers.get("content-type") || "";
  }
  return headers["Content-Type"] || headers["content-type"] || "";
}

/**
 * 规范化路径（去除域名、查询参数等）
 */
function normalizePath(url: string): string {
  if (!url) return "";
  let path = url;
  // 去除协议和域名
  if (path.includes("://")) {
    path = "/" + path.split("://")[1].split("/").slice(1).join("/");
  }
  // 去除查询参数
  path = path.split("?")[0];
  // 确保以 / 开头
  if (!path.startsWith("/")) {
    path = "/" + path;
  }
  return path;
}

/**
 * 检查路径是否匹配白名单
 */
function isPathInWhiteList(url: string): boolean {
  const path = normalizePath(url);
  return ENCRYPT_WHITE_LIST.some(pattern => {
    const normalizedPattern = pattern.startsWith("/") ? pattern : "/" + pattern;
    // 通配符匹配：/path/** 匹配 /path 下所有子路径
    if (normalizedPattern.endsWith("/**")) {
      return path.startsWith(normalizedPattern.slice(0, -3));
    }
    return path === normalizedPattern;
  });
}

/**
 * 检查数据是否是特殊类型（不应加密的类型）
 */
function isSpecialDataType(data: any): boolean {
  if (!data) return false;
  return (
    (typeof FormData !== "undefined" && data instanceof FormData) ||
    (typeof URLSearchParams !== "undefined" && data instanceof URLSearchParams) ||
    (typeof Blob !== "undefined" && data instanceof Blob) ||
    (typeof File !== "undefined" && data instanceof File) ||
    (typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer)
  );
}

/**
 * 检查字符串是否符合 Base64 密文特征
 */
function isBase64CipherText(data: any): boolean {
  if (typeof data !== "string" || data.length < 16) return false;
  // Base64: 长度是4的倍数，只包含合法字符
  return data.length % 4 === 0 && /^[A-Za-z0-9+/=]+$/.test(data);
}

// ==================== 核心策略 ====================

export const cryptoStrategy = {
  /**
   * 判断请求是否应该加密
   */
  shouldEncrypt(config: any): boolean {
    // 1. 检查加密开关
    if (!isEncryptEnabled(config)) {
      return false;
    }

    // 2. 检查请求方法
    const method = (config.method || "").toUpperCase();
    if (!ENCRYPT_METHODS.includes(method)) {
      return false;
    }

    // 3. 检查白名单
    if (isPathInWhiteList(config.url || "")) {
      return false;
    }

    // 4. 检查 Content-Type 必须包含 application/json
    const contentType = getContentType(config.headers);
    if (!contentType.toLowerCase().includes("application/json")) {
      return false;
    }

    // 5. 检查数据类型
    if (isSpecialDataType(config.data)) {
      return false;
    }

    return true;
  },

  /**
   * 判断响应是否应该解密
   * @param config 请求配置（用于判断加密开关）
   * @param responseHeaders 响应头（用于判断 Content-Type）
   * @param data 响应数据
   */
  shouldDecrypt(config: any, responseHeaders: any, data: any): boolean {
    // 1. 检查加密开关
    if (!isEncryptEnabled(config)) {
      return false;
    }

    // 2. 检查响应 Content-Type 必须包含 application/json
    const contentType = getContentType(responseHeaders);
    if (!contentType.toLowerCase().includes("application/json")) {
      return false;
    }

    // 3. 检查数据是否是 Base64 密文
    if (!isBase64CipherText(data)) {
      return false;
    }

    return true;
  }
};
