// ============================================================
// 日志脱敏工具 — 主进程 + 渲染进程共用
//
// 设计：在 createEntry 阶段统一对 context 字段脱敏，调用方无感知
//
// 脱敏策略（按字段名模式匹配，大小写不敏感）：
//   *token* / *secret* / *password* / *pwd* → [REDACTED]
//   *email*                               → 保留首字符 + 域名（t***@qq.com）
//   *phone* / *mobile* / *tel*            → 保留首 3 尾 4（138****5678）
//   *id / *_id / userId / user_id         → SHA256 前 8 位（可追溯但不可读）
//   *name / username / display_name       → 保留首字符 + ***
//   *balance* / *money* / *amount*        → 数值替换为 [FILTERED]
//   其他字段                                → 原样保留
// ============================================================

import type { LogEntry } from '@shared/types';

// ---------- 脱敏函数 ----------

/** 通过哈希缩短（用于 ID 类字段，可追溯不可读） */
export function hashShort(value: string): string {
   // 简易哈希（避免引入 crypto 模块，双端兼容）
   let h = 0;
   for (let i = 0; i < value.length; i++) {
      h = (Math.imul(31, h) + value.charCodeAt(i)) | 0;
   }
   // 转 hex 前缀，补零到 8 位
   const hex = (h >>> 0).toString(16).padStart(8, '0');
   return `#${hex}`;
}

/** 邮箱脱敏：首字符 + ***@域名 */
export function sanitizeEmail(value: string): string {
   const atIndex = value.indexOf('@');
   if (atIndex <= 0) return `${value[0]}***`;
   return `${value[0]}***@${value.slice(atIndex + 1)}`;
}

/** 手机号脱敏：保留前 3 后 4 */
export function sanitizePhone(value: string): string {
   const digits = value.replace(/\D/g, '');
   if (digits.length < 7) return `${digits.slice(0, 3)}****`;
   return `${digits.slice(0, 3)}****${digits.slice(-4)}`;
}

/** 名称脱敏：保留首字符 + *** */
export function sanitizeName(value: string): string {
   if (!value || value.length <= 1) return '***';
   return `${value[0]}***`;
}

/** 判断字段名是否匹配某个模式 */
function matchKey(key: string, patterns: string[]): boolean {
   const lower = key.toLowerCase();
   return patterns.some((p) => {
      if (p.startsWith('*') && p.endsWith('*')) return lower.includes(p.slice(1, -1));
      if (p.endsWith('*')) return lower.startsWith(p.slice(0, -1));
      if (p.startsWith('*')) return lower.endsWith(p.slice(1));
      return lower === p;
   });
}

/** 对单个值脱敏（递归处理嵌套对象） */
function sanitizeValue(key: string, value: unknown): unknown {
   if (value === null || value === undefined) return value;

   // 完全隐藏
   if (matchKey(key, ['*token*', '*secret*', '*password*', '*pwd*', 'authorization'])) {
      return '[REDACTED]';
   }

   // 邮箱
   if (
      matchKey(key, ['*email*']) &&
      typeof value === 'string' &&
      value.includes('@')
   ) {
      return sanitizeEmail(value);
   }

   // 手机号
   if (matchKey(key, ['*phone*', '*mobile*', '*tel*']) && typeof value === 'string') {
      return sanitizePhone(value);
   }

   // ID 类字段（数字或字符串）
   if (
      matchKey(key, ['*id', '*_id', 'userId', 'user_id', 'company_id']) &&
      (typeof value === 'string' || typeof value === 'number')
   ) {
      return hashShort(String(value));
   }

   // 名称
   if (
      matchKey(key, ['*name', 'username', 'display_name', 'real_name']) &&
      typeof value === 'string'
   ) {
      return sanitizeName(value);
   }

   // 金额 / 余额
   if (matchKey(key, ['*balance*', '*money*', '*amount*', '*cent*', '*fee*'])) {
      return '[FILTERED]';
   }

   // 递归处理嵌套对象
   if (typeof value === 'object' && !Array.isArray(value)) {
      return sanitizeRecord(value as Record<string, unknown>);
   }

   // 数组：逐个脱敏
   if (Array.isArray(value)) {
      return value.map((v) => sanitizeValue(key, v));
   }

   return value;
}

/** 脱敏整个 Record */
function sanitizeRecord(record: Record<string, unknown>): Record<string, unknown> {
   const result: Record<string, unknown> = {};
   for (const [key, value] of Object.entries(record)) {
      result[key] = sanitizeValue(key, value);
   }
   return result;
}

// ---------- 对外 API ----------

/**
 * 脱敏任意对象（返回新对象，不修改原对象）
 *
 * 用法：
 *   import { sanitize } from '@shared/utils/sanitize';
 *   const safe = sanitize({ userId: 42, email: 'test@qq.com', phone: '13812345678' });
 *   // → { userId: "#a1b2c3d4", email: "t***@qq.com", phone: "138****5678" }
 */
export function sanitize(record: Record<string, unknown>): Record<string, unknown> {
   return sanitizeRecord(record);
}

/**
 * 对 LogEntry 脱敏（原地不修改，返回新对象）
 * 内部也调用了 sanitizeRecord
 */
export function sanitizeLogEntry(entry: LogEntry): LogEntry {
   const sanitized = { ...entry };

   // 脱敏 context
   if (sanitized.context && Object.keys(sanitized.context).length > 0) {
      sanitized.context = sanitizeRecord(sanitized.context);
   }

   // 脱敏 error 中的 message（可能含用户信息，如 "User xxx not found"）
   if (sanitized.error) {
      sanitized.error = { ...sanitized.error };
      // 对 error message 做基础脱敏（邮箱/手机号）
      if (sanitized.error.message) {
         sanitized.error.message = sanitizeInlineText(sanitized.error.message);
      }
   }

   // 脱敏 message 字段本身
   sanitized.message = sanitizeInlineText(sanitized.message);

   return sanitized;
}

/**
 * 对任意文本中的敏感信息做内联脱敏
 * 使用正则匹配邮箱和手机号模式
 */
export function sanitizeInlineText(text: string): string {
   // 邮箱（简单模式）
   let result = text.replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, (match) =>
      sanitizeEmail(match),
   );
   // 手机号（中国大陆 11 位）
   result = result.replace(/\b1[3-9]\d{9}\b/g, (match) => sanitizePhone(match));
   return result;
}
