#!/usr/bin/env bash
set -euo pipefail

export LC_ALL=C
export TZ=UTC
export GIT_CONFIG_NOSYSTEM=1
export GIT_CONFIG_GLOBAL=/dev/null
export FLUXGIT_MCP_AUDIT_DISABLED=1
unset FLUXGIT_MCP_HANDSHAKE_ADDR FLUXGIT_GATEWAY_ADDR FLUXGIT_MCP_AGENT_POLICY

BENCH_ROOT="$(cd "$(dirname "$0")" && pwd)"
SOURCE_ROOT="$(cd "$BENCH_ROOT/../../../../.." && pwd)"
REPO="$BENCH_ROOT/repo"
CLI_OUT="$BENCH_ROOT/cli-outputs"
MCP_OUT="$BENCH_ROOT/mcp-outputs"
SIDECAR_BIN="${SIDECAR_BIN:-$SOURCE_ROOT/app/core/target/release/fluxgit-mcp-sidecar}"

if [[ "${SKIP_SIDECAR_BUILD:-0}" != "1" ]]; then
  cargo build --locked --release -p fluxgit-mcp-sidecar \
    --manifest-path "$SOURCE_ROOT/app/core/Cargo.toml"
fi
if [[ ! -x "$SIDECAR_BIN" ]]; then
  echo "Sidecar binary is not executable: $SIDECAR_BIN" >&2
  exit 1
fi

rm -rf "$CLI_OUT" "$MCP_OUT"
mkdir -p "$CLI_OUT" "$MCP_OUT"
"$BENCH_ROOT/make-repo.sh"

capture() {
  local destination="$1"
  shift
  local temporary="$destination.tmp"
  "$@" > "$temporary"
  python3 - "$temporary" "$destination" "$BENCH_ROOT" <<'PY'
import os
import sys

source, destination, bench_root = sys.argv[1:]
with open(source, "r", encoding="utf-8") as handle:
    text = handle.read()
for candidate in sorted({bench_root, os.path.realpath(bench_root)}, key=len, reverse=True):
    text = text.replace(candidate, "$BENCH_ROOT")
with open(destination, "w", encoding="utf-8", newline="") as handle:
    handle.write(text)
os.remove(source)
PY
}

capture "$CLI_OUT/01-status.txt" git -C "$REPO" status
capture "$CLI_OUT/02-log-oneline-30.txt" git -C "$REPO" log --oneline -30
capture "$CLI_OUT/03-branch-a-v.txt" git -C "$REPO" branch -a -v
capture "$CLI_OUT/04-diff-unstaged.txt" git -C "$REPO" diff
capture "$CLI_OUT/05-diff-cached.txt" git -C "$REPO" diff --cached
capture "$CLI_OUT/06-remote-v.txt" git -C "$REPO" remote -v
capture "$CLI_OUT/07-stash-list.txt" git -C "$REPO" stash list
capture "$CLI_OUT/08-tag.txt" git -C "$REPO" tag -n
capture "$CLI_OUT/09-ls-files.txt" git -C "$REPO" ls-files
capture "$CLI_OUT/10-submodule-status.txt" git -C "$REPO" submodule status
capture "$CLI_OUT/x-log-oneline-10.txt" git -C "$REPO" log --oneline -10
capture "$CLI_OUT/20-merge-base.txt" git -C "$REPO" merge-base feature/usage-metering main

merge_tree_tmp="$CLI_OUT/21-merge-tree.txt.tmp"
set +e
git -C "$REPO" merge-tree --write-tree feature/usage-metering main > "$merge_tree_tmp"
merge_tree_status=$?
set -e
if [[ "$merge_tree_status" -ne 1 ]]; then
  echo "Expected git merge-tree to report a conflict (exit 1), got $merge_tree_status" >&2
  exit 1
fi
python3 - "$merge_tree_tmp" "$CLI_OUT/21-merge-tree.txt" "$BENCH_ROOT" <<'PY'
import os
import sys

source, destination, bench_root = sys.argv[1:]
with open(source, "r", encoding="utf-8") as handle:
    text = handle.read()
for candidate in sorted({bench_root, os.path.realpath(bench_root)}, key=len, reverse=True):
    text = text.replace(candidate, "$BENCH_ROOT")
with open(destination, "w", encoding="utf-8", newline="") as handle:
    handle.write(text)
os.remove(source)
PY

python3 "$BENCH_ROOT/mcp-drive.py" "$SIDECAR_BIN" "$REPO" "$MCP_OUT"

(
  cd "$BENCH_ROOT"
  npm ci --ignore-scripts --no-audit --no-fund
  node count.mjs > results.json
)

python3 - "$BENCH_ROOT" "$SOURCE_ROOT" <<'PY'
import json
import os
import subprocess
import sys

bench_root, source_root = sys.argv[1:]
repo = os.path.join(bench_root, "repo")
with open(os.path.join(bench_root, "package-lock.json"), encoding="utf-8") as handle:
    package_lock = json.load(handle)

def git(*args):
    return subprocess.check_output(
        ["git", "-C", repo, *args], text=True, env={
            **os.environ,
            "GIT_CONFIG_NOSYSTEM": "1",
            "GIT_CONFIG_GLOBAL": "/dev/null",
        }
    ).strip()

directories = sorted({os.path.dirname(path) for path in git("ls-files").splitlines() if "/" in path})
conflict = json.loads(open(os.path.join(bench_root, "mcp-outputs", "conflict-preflight.json"), encoding="utf-8").read())
conflict_data = json.loads(conflict["result"]["content"][0]["text"])["data"]
tools = json.loads(open(os.path.join(bench_root, "mcp-outputs", "tools-list.json"), encoding="utf-8").read())["result"]["tools"]

manifest = {
    "formatVersion": 1,
    "normalization": {
        "absoluteBenchRoot": "$BENCH_ROOT",
        "appliedBeforeCounting": True,
    },
    "source": {
        "sidecarPackage": "fluxgit-mcp-sidecar",
        "sidecarVersion": "0.1.0",
        "repositoryCommit": subprocess.check_output(
            ["git", "-C", source_root, "rev-parse", "HEAD"], text=True
        ).strip(),
        "sidecarSourceTree": subprocess.check_output(
            ["git", "-C", source_root, "rev-parse", "HEAD:app/core/mcp-sidecar"], text=True
        ).strip(),
    },
    "environment": {
        "git": subprocess.check_output(["git", "--version"], text=True).strip(),
        "tokenizer": {
            "package": "gpt-tokenizer",
            "version": package_lock["packages"]["node_modules/gpt-tokenizer"]["version"],
            "encoding": "o200k_base",
        },
    },
    "repository": {
        "mainCommits": int(git("rev-list", "--count", "main")),
        "branchReachableCommits": int(git("rev-list", "--branches", "--count")),
        "trackedFiles": len(git("ls-files").splitlines()),
        "trackedFileDirectories": directories,
        "localBranches": git("for-each-ref", "--format=%(refname:short)", "refs/heads").splitlines(),
        "annotatedTags": git("tag").splitlines(),
        "stashes": len(git("stash", "list").splitlines()),
        "mainAheadOfOrigin": int(git("rev-list", "--count", "origin/main..main")),
    },
    "mcp": {
        "protocolVersion": "2024-11-05",
        "toolCount": len(tools),
        "readOnlyHintCount": sum(tool.get("annotations", {}).get("readOnlyHint") is True for tool in tools),
        "annotationsAvailable": any("annotations" in tool for tool in tools),
        "conflictStatus": conflict_data["status"],
        "conflictingPaths": conflict_data["conflictingPaths"],
        "workingTreeMutated": conflict_data["workingTreeMutated"],
    },
    "artifacts": {
        "cli": {
            "files": sorted(os.listdir(os.path.join(bench_root, "cli-outputs"))),
            "orientationCalls": 10,
            "conflictPreflightCalls": 2,
        },
        "mcp": {
            "files": sorted(os.listdir(os.path.join(bench_root, "mcp-outputs"))),
            "measuredTools": ["repo.brief", "repo.scope", "repo.conflictPreflight"],
        },
        "counts": "results.json",
    },
}

expected = {
    "mainCommits": 44,
    "branchReachableCommits": 48,
    "trackedFiles": 40,
    "directoryCount": 11,
    "localBranchCount": 4,
    "tagCount": 2,
    "stashes": 1,
    "mainAheadOfOrigin": 1,
}
actual = {
    "mainCommits": manifest["repository"]["mainCommits"],
    "branchReachableCommits": manifest["repository"]["branchReachableCommits"],
    "trackedFiles": manifest["repository"]["trackedFiles"],
    "directoryCount": len(directories),
    "localBranchCount": len(manifest["repository"]["localBranches"]),
    "tagCount": len(manifest["repository"]["annotatedTags"]),
    "stashes": manifest["repository"]["stashes"],
    "mainAheadOfOrigin": manifest["repository"]["mainAheadOfOrigin"],
}
if actual != expected:
    raise SystemExit(f"repository invariant mismatch: expected {expected}, got {actual}")
if manifest["mcp"]["conflictStatus"] != "conflicts":
    raise SystemExit(f"expected MCP conflict status, got {manifest['mcp']['conflictStatus']}")
if manifest["mcp"]["conflictingPaths"] != ["src/billing/subscription.ts"]:
    raise SystemExit(f"unexpected conflict paths: {manifest['mcp']['conflictingPaths']}")
if manifest["mcp"]["workingTreeMutated"] is not False:
    raise SystemExit("MCP conflict preflight mutated the working tree")

with open(os.path.join(bench_root, "manifest.json"), "w", encoding="utf-8", newline="") as handle:
    json.dump(manifest, handle, indent=2)
    handle.write("\n")
PY

(
  cd "$BENCH_ROOT"
  find cli-outputs mcp-outputs -type f -print | LC_ALL=C sort
  printf '%s\n' manifest.json results.json
) | while IFS= read -r artifact; do
  (cd "$BENCH_ROOT" && shasum -a 256 "$artifact")
done > "$BENCH_ROOT/SHA256SUMS"

for machine_path in "$BENCH_ROOT" "${HOME%/}/"; do
  if rg -F -n "$machine_path" \
    "$CLI_OUT" "$MCP_OUT" "$BENCH_ROOT/results.json" "$BENCH_ROOT/manifest.json"; then
    echo "Machine-specific path found in artifacts" >&2
    exit 1
  fi
done

(cd "$BENCH_ROOT" && shasum -a 256 -c SHA256SUMS)
echo "Benchmark complete: $BENCH_ROOT/results.json"
