const FUTU_SIGN = 'ft-v1.0';
let nextSession = 1;

// 全局 TextEncoder/Decoder（浏览器和 Node.js 都支持）
const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();

export const encodeBuffer = (cmd: number, protobuf: Uint8Array) => {
  const session = nextSession++;
  const signBytes = textEncoder.encode(FUTU_SIGN); // "ft-v1.0" → Uint8Array

  // 总长度 = 8 (sign) + 4 (cmd) + 8 (session) + protobuf.length
  const totalLength = 8 + 4 + 8 + protobuf.byteLength;
  const buffer = new ArrayBuffer(totalLength);
  const view = new Uint8Array(buffer);
  const dv = new DataView(buffer);

  // 1. 写入签名（最多 8 字节，不足补 0）
  view.set(signBytes, 0);
  for (let i = signBytes.length; i < 8; i++) {
    view[i] = 0;
  }

  // 2. 写入 cmd (uint32, big-endian)
  dv.setUint32(8, cmd, false); // false = big-endian

  // 3. 写入 session (uint64, big-endian)
  // 注意：JavaScript number 是 double，但 session 是整数且 <= Number.MAX_SAFE_INTEGER
  // 如果 session 可能 > 2^53-1，请改用 BigInt 并分高低位写入
  dv.setBigUint64(12, BigInt(session), false);

  // 4. 写入 protobuf
  view.set(protobuf, 20); // 8+4+8 = 20

  return { message: buffer, session };
};

export const decodeBuffer = (arrayBuffer: ArrayBuffer) => {
  const dv = new DataView(arrayBuffer);
  const view = new Uint8Array(arrayBuffer);

  const cmd = dv.getUint32(8, false);
  // 1. 读取 session (uint64 @ offset 12)
  const session = Number(dv.getBigUint64(12, false));

  // 2. 读取 errorCode (int32 @ offset 20)
  const errorCode = dv.getInt32(20, false);

  // 3. 读取 errorMessage (20 bytes from offset 24)
  const errorMessageBytes = view.subarray(24, 44);
  // 移除末尾的 \0（找到第一个 0 或取全部）
  const nullIndex = errorMessageBytes.indexOf(0);
  const cleanBytes = nullIndex === -1 ? errorMessageBytes : errorMessageBytes.subarray(0, nullIndex);
  const errorMessage = cleanBytes.length > 0 ? textDecoder.decode(cleanBytes) : '';

  // 4. 读取 protobuf (from offset 44 to end)
  const protobuf = view.subarray(44).slice(); // slice() 创建新副本（可选）

  return { session, cmd, message: { errorCode, errorMessage, protobuf } };
};
