/**
 * 加密工具函数
 * 提供密码加密、验证等安全相关功能
 */

const crypto = require('crypto');

// 配置参数
const SALT_LENGTH = 16; // salt 长度
const KEY_LENGTH = 64; // 密钥长度
const ITERATIONS = 100000; // 迭代次数
const DIGEST = 'sha256'; // 摘要算法

/**
 * 生成密码哈希
 * @param {string} password - 明文密码
 * @returns {Promise<string>} 加密后的密码字符串 (格式: salt$hash)
 */
async function hashPassword(password) {
  if (!password || typeof password !== 'string') {
    throw new Error('密码不能为空');
  }

  return new Promise((resolve, reject) => {
    // 生成随机 salt
    const salt = crypto.randomBytes(SALT_LENGTH).toString('hex');

    // 使用 pbkdf2 生成密钥
    crypto.pbkdf2(password, salt, ITERATIONS, KEY_LENGTH, DIGEST, (err, derivedKey) => {
      if (err) {
        reject(err);
      } else {
        const hash = derivedKey.toString('hex');
        // 返回格式: salt$hash
        resolve(`${salt}$${hash}`);
      }
    });
  });
}

/**
 * 验证密码
 * @param {string} password - 明文密码
 * @param {string} hashedPassword - 加密后的密码 (格式: salt$hash)
 * @returns {Promise<boolean>} 是否匹配
 */
async function verifyPassword(password, hashedPassword) {
  if (!password || !hashedPassword) {
    return false;
  }

  return new Promise((resolve, reject) => {
    try {
      // 解析 salt 和 hash
      const parts = hashedPassword.split('$');
      if (parts.length !== 2) {
        resolve(false);
        return;
      }

      const [salt, originalHash] = parts;

      // 使用相同的 salt 生成密钥
      crypto.pbkdf2(password, salt, ITERATIONS, KEY_LENGTH, DIGEST, (err, derivedKey) => {
        if (err) {
          reject(err);
        } else {
          const hash = derivedKey.toString('hex');
          // 使用恒定时间比较，防止时序攻击
          resolve(crypto.timingSafeEqual(Buffer.from(hash), Buffer.from(originalHash)));
        }
      });
    } catch (error) {
      reject(error);
    }
  });
}

/**
 * 生成安全的随机 token
 * @param {number} length - token 长度（字节数），默认 32
 * @returns {string} 十六进制字符串
 */
function generateToken(length = 32) {
  return crypto.randomBytes(length).toString('hex');
}

/**
 * 生成设备 ID
 * @param {string} prefix - 前缀，默认 'device'
 * @returns {string} 设备 ID
 */
function generateDeviceId(prefix = 'device') {
  const timestamp = Date.now();
  const random = crypto.randomBytes(8).toString('hex');
  return `${prefix}_${timestamp}_${random}`;
}

/**
 * 验证设备 ID 格式
 * @param {string} deviceId - 设备 ID
 * @returns {boolean} 是否有效
 */
function validateDeviceId(deviceId) {
  if (!deviceId || typeof deviceId !== 'string') {
    return false;
  }

  // 检查格式: prefix_timestamp_randomhex
  const pattern = /^[a-z]+_\d{13}_[a-f0-9]{16}$/i;
  return pattern.test(deviceId);
}

/**
 * 脱敏处理 - 手机号
 * @param {string} phone - 手机号
 * @returns {string} 脱敏后的手机号
 */
function maskPhone(phone) {
  if (!phone || typeof phone !== 'string') {
    return '';
  }
  if (phone.length < 11) {
    return phone;
  }
  return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
}

/**
 * 脱敏处理 - 邮箱
 * @param {string} email - 邮箱
 * @returns {string} 脱敏后的邮箱
 */
function maskEmail(email) {
  if (!email || typeof email !== 'string') {
    return '';
  }
  const parts = email.split('@');
  if (parts.length !== 2) {
    return email;
  }
  const [username, domain] = parts;
  if (username.length <= 2) {
    return `*@${domain}`;
  }
  const masked = username[0] + '***' + username[username.length - 1];
  return `${masked}@${domain}`;
}

/**
 * 脱敏处理 - 通用对象（用于日志）
 * @param {Object} obj - 要脱敏的对象
 * @param {Array<string>} sensitiveFields - 敏感字段列表
 * @returns {Object} 脱敏后的对象
 */
function maskSensitiveData(obj, sensitiveFields = ['password', 'pwd', 'token', 'secret', 'key']) {
  if (!obj || typeof obj !== 'object') {
    return obj;
  }

  const masked = { ...obj };

  for (const field of sensitiveFields) {
    if (masked[field]) {
      masked[field] = '***MASKED***';
    }
  }

  return masked;
}

module.exports = {
  hashPassword,
  verifyPassword,
  generateToken,
  generateDeviceId,
  validateDeviceId,
  maskPhone,
  maskEmail,
  maskSensitiveData
};
