/**
 * 字节转换函数
 * 将字节大小转换为适当的单位（B, KB, MB, GB, TB等）
 *
 * @param bytes - 字节数
 * @param decimals - 小数位数，默认为2
 * @returns 格式化后的文件大小字符串
 */
export function formatBytes(bytes: number, decimals: number = 2): string {
  if (bytes === 0) return '0 B';

  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

/**
 * 字节转换函数（另一种实现方式）
 * 提供更精确的转换控制
 *
 * @param bytes - 字节数
 * @param options - 转换选项
 * @returns 格式化后的文件大小字符串
 */
export function convertBytes(
  bytes: number,
  options?: {
    decimals?: number;
    binary?: boolean; // 是否使用二进制单位（1024）而非十进制（1000）
  }
): string {
  const { decimals = 2, binary = true } = options || {};

  if (bytes === 0) return '0 B';

  const base = binary ? 1024 : 1000;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = binary
    ? ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
    : ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

  const i = Math.floor(Math.log(bytes) / Math.log(base));
  const value = bytes / Math.pow(base, i);

  return parseFloat(value.toFixed(dm)) + ' ' + sizes[i];
}

/**
 * 解析文件大小字符串为字节数
 *
 * @param sizeStr - 文件大小字符串，如 "1.5 MB", "2GB" 等
 * @returns 字节数，如果解析失败返回 NaN
 */
export function parseBytes(sizeStr: string): number {
  if (!sizeStr) return NaN;

  const match = sizeStr.match(/^(\d+(?:\.\d+)?)\s*(B|KB|MB|GB|TB|PB|EB|ZB|YB|KIB|MIB|GIB|TIB|PIB|EIB|ZIB|YIB)$/i);
  if (!match) return NaN;

  const value = parseFloat(match[1]);
  const unit = match[2].toUpperCase();

  const binaryUnits: Record<string, number> = {
    'B': 1,
    'KIB': Math.pow(1024, 1),
    'MIB': Math.pow(1024, 2),
    'GIB': Math.pow(1024, 3),
    'TIB': Math.pow(1024, 4),
    'PIB': Math.pow(1024, 5),
    'EIB': Math.pow(1024, 6),
    'ZIB': Math.pow(1024, 7),
    'YIB': Math.pow(1024, 8)
  };

  const decimalUnits: Record<string, number> = {
    'B': 1,
    'KB': Math.pow(1000, 1),
    'MB': Math.pow(1000, 2),
    'GB': Math.pow(1000, 3),
    'TB': Math.pow(1000, 4),
    'PB': Math.pow(1000, 5),
    'EB': Math.pow(1000, 6),
    'ZB': Math.pow(1000, 7),
    'YB': Math.pow(1000, 8)
  };

  // 优先使用二进制单位
  if (binaryUnits[unit]) {
    return value * binaryUnits[unit];
  }

  if (decimalUnits[unit]) {
    return value * decimalUnits[unit];
  }

  return NaN;
}
