#!/bin/sh
# Tests for scripts/install.sh
#
# Tests the detection and error-handling logic by overriding uname, command,
# and id via PATH shims. Does not require network access or root.
#
# Usage: ./tests/test_install.sh
set -eu

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
INSTALL_SCRIPT="$PROJECT_DIR/scripts/install.sh"

passed=0
failed=0

fail() {
    echo "FAIL: $1"
    failed=$((failed + 1))
}

pass() {
    echo "PASS: $1"
    passed=$((passed + 1))
}

# Create a temporary directory for test shims
setup_shims() {
    shim_dir="$(mktemp -d)"
    trap 'rm -rf "$shim_dir"' EXIT INT TERM
}

# Create a shim that overrides a command to output a fixed value
make_uname_shim() {
    sysname="$1"
    machine="$2"
    cat > "$shim_dir/uname" <<SHIM
#!/bin/sh
case "\$1" in
    -s) echo "$sysname" ;;
    -m) echo "$machine" ;;
    *)  echo "$sysname" ;;
esac
SHIM
    chmod +x "$shim_dir/uname"
}

# Create a shim that makes "command -v curl" fail
make_no_curl_shim() {
    cat > "$shim_dir/command" <<'SHIM'
#!/bin/sh
# Override command -v to hide curl
if [ "$1" = "-v" ] && [ "$2" = "curl" ]; then
    exit 1
fi
# Pass through everything else
/usr/bin/command "$@"
SHIM
    chmod +x "$shim_dir/command"
}

setup_shims

# --- Test: rejects macOS ---
test_rejects_macos() {
    make_uname_shim "Darwin" "arm64"
    output=$(PATH="$shim_dir:$PATH" sh "$INSTALL_SCRIPT" 2>&1) || true
    if echo "$output" | grep -q "unsupported OS: Darwin"; then
        pass "rejects macOS with correct message"
    else
        fail "rejects macOS — got: $output"
    fi
    if echo "$output" | grep -q "cargo install fafb-q"; then
        pass "macOS rejection suggests cargo install"
    else
        fail "macOS rejection missing cargo suggestion — got: $output"
    fi
}

# --- Test: rejects FreeBSD ---
test_rejects_freebsd() {
    make_uname_shim "FreeBSD" "amd64"
    output=$(PATH="$shim_dir:$PATH" sh "$INSTALL_SCRIPT" 2>&1) || true
    if echo "$output" | grep -q "unsupported OS: FreeBSD"; then
        pass "rejects FreeBSD"
    else
        fail "rejects FreeBSD — got: $output"
    fi
}

# --- Test: rejects unsupported architecture ---
test_rejects_unsupported_arch() {
    make_uname_shim "Linux" "s390x"
    output=$(PATH="$shim_dir:$PATH" sh "$INSTALL_SCRIPT" 2>&1) || true
    if echo "$output" | grep -q "unsupported architecture: s390x"; then
        pass "rejects unsupported arch s390x"
    else
        fail "rejects unsupported arch — got: $output"
    fi
}

# --- Test: detects x86_64 correctly ---
test_detects_x86_64() {
    make_uname_shim "Linux" "x86_64"
    # Script will fail at curl download, but we can check the detection output
    output=$(PATH="$shim_dir:$PATH" sh "$INSTALL_SCRIPT" 2>&1) || true
    if echo "$output" | grep -q "Detected: Linux x86_64"; then
        pass "detects x86_64"
    else
        fail "detects x86_64 — got: $output"
    fi
    if echo "$output" | grep -q "x86_64-unknown-linux-musl"; then
        pass "selects correct x86_64 target triple"
    else
        fail "selects correct x86_64 target triple — got: $output"
    fi
}

# --- Test: detects aarch64 correctly ---
test_detects_aarch64() {
    make_uname_shim "Linux" "aarch64"
    output=$(PATH="$shim_dir:$PATH" sh "$INSTALL_SCRIPT" 2>&1) || true
    if echo "$output" | grep -q "Detected: Linux aarch64"; then
        pass "detects aarch64"
    else
        fail "detects aarch64 — got: $output"
    fi
    if echo "$output" | grep -q "aarch64-unknown-linux-musl"; then
        pass "selects correct aarch64 target triple"
    else
        fail "selects correct aarch64 target triple — got: $output"
    fi
}

# --- Test: detects arm64 alias ---
test_detects_arm64_alias() {
    make_uname_shim "Linux" "arm64"
    output=$(PATH="$shim_dir:$PATH" sh "$INSTALL_SCRIPT" 2>&1) || true
    if echo "$output" | grep -q "Detected: Linux arm64"; then
        pass "detects arm64 alias"
    else
        fail "detects arm64 alias — got: $output"
    fi
    if echo "$output" | grep -q "aarch64-unknown-linux-musl"; then
        pass "arm64 maps to aarch64 target triple"
    else
        fail "arm64 maps to aarch64 target triple — got: $output"
    fi
}

# --- Test: exits non-zero on unsupported OS ---
test_exit_code_unsupported_os() {
    make_uname_shim "Darwin" "arm64"
    if PATH="$shim_dir:$PATH" sh "$INSTALL_SCRIPT" >/dev/null 2>&1; then
        fail "should exit non-zero on unsupported OS"
    else
        pass "exits non-zero on unsupported OS"
    fi
}

# --- Test: exits non-zero on unsupported arch ---
test_exit_code_unsupported_arch() {
    make_uname_shim "Linux" "ppc64le"
    if PATH="$shim_dir:$PATH" sh "$INSTALL_SCRIPT" >/dev/null 2>&1; then
        fail "should exit non-zero on unsupported arch"
    else
        pass "exits non-zero on unsupported arch"
    fi
}

# --- Test: script is POSIX sh (shebang check) ---
test_posix_shebang() {
    first_line=$(head -1 "$INSTALL_SCRIPT")
    if [ "$first_line" = "#!/bin/sh" ]; then
        pass "shebang is #!/bin/sh"
    else
        fail "shebang should be #!/bin/sh — got: $first_line"
    fi
}

# --- Test: script is executable ---
test_executable() {
    if [ -x "$INSTALL_SCRIPT" ]; then
        pass "install.sh is executable"
    else
        fail "install.sh is not executable"
    fi
}

# --- Run all tests ---
echo "Running install.sh tests..."
echo "---"

test_posix_shebang
test_executable
test_rejects_macos
test_rejects_freebsd
test_rejects_unsupported_arch
test_detects_x86_64
test_detects_aarch64
test_detects_arm64_alias
test_exit_code_unsupported_os
test_exit_code_unsupported_arch

echo "---"
echo "Results: $passed passed, $failed failed"

if [ "$failed" -gt 0 ]; then
    exit 1
fi
