import { readFileSync } from "node:fs";

import git from "@agentos-software/git";
import { describe, expect, it } from "vitest";

import {
  getExecutableGitSoftware,
  makeGitExecutablesRunnable,
} from "./agent-os-git-software";

const TAR_BLOCK_SIZE = 512;
const READ_ONLY_EXECUTABLE_MODE = Buffer.from([0xa4, 0x81, 0x00, 0x00]);
const RUNNABLE_EXECUTABLE_MODE = Buffer.from([0xed, 0x81, 0x00, 0x00]);

const readTarModes = (packageBytes: Buffer): Map<string, number> => {
  const tarOffset =
    16 + packageBytes.readUInt32LE(8) + packageBytes.readUInt32LE(12);
  const modes = new Map<string, number>();
  let offset = tarOffset;

  while (
    offset + TAR_BLOCK_SIZE <= packageBytes.length &&
    packageBytes
      .subarray(offset, offset + TAR_BLOCK_SIZE)
      .some((byte) => byte !== 0)
  ) {
    const [name = ""] = packageBytes
      .subarray(offset, offset + 100)
      .toString("utf-8")
      .split("\0");
    const mode = Number.parseInt(
      packageBytes
        .subarray(offset + 100, offset + 108)
        .toString("ascii")
        .replaceAll("\0", "")
        .trim(),
      8
    );
    const size = Number.parseInt(
      packageBytes
        .subarray(offset + 124, offset + 136)
        .toString("ascii")
        .replaceAll("\0", "")
        .trim() || "0",
      8
    );

    modes.set(name, mode);
    offset +=
      TAR_BLOCK_SIZE + Math.ceil(size / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;
  }

  return modes;
};

describe("AgentOS Git software", () => {
  it("marks the packaged Git commands executable", () => {
    const repaired = makeGitExecutablesRunnable(readFileSync(git.packagePath));
    const modes = readTarModes(repaired);

    expect(modes.get("./bin/git")).toBe(0o755);
    expect(modes.get("./bin/git-remote-http")).toBe(0o755);
    expect(modes.get("./bin/git-remote-https")).toBe(0o755);
    expect(repaired.includes(Buffer.from("0.3.0-zp.1", "ascii"))).toBe(true);

    const mountIndexOffset = 16 + repaired.readUInt32LE(8);
    const tarOffset = mountIndexOffset + repaired.readUInt32LE(12);
    const mountIndex = repaired.subarray(mountIndexOffset, tarOffset);
    expect(mountIndex.includes(READ_ONLY_EXECUTABLE_MODE)).toBe(false);
    expect(
      mountIndex.toString("hex").split(RUNNABLE_EXECUTABLE_MODE.toString("hex"))
        .length - 1
    ).toBe(3);
  });

  it("writes a stable repaired package for the AgentOS registry", () => {
    const first = getExecutableGitSoftware();
    const second = getExecutableGitSoftware();

    expect(second).toEqual(first);
    expect(readTarModes(readFileSync(first.packagePath)).get("./bin/git")).toBe(
      0o755
    );
  });
});
