#!/usr/bin/env bash

# Create system "tools" that always fail and push them to the front of PATH
cat >"$HOME/bin/fail" <<'EOF'
#!/usr/bin/env bash
echo "CALL TO SYSTEM $(basename $0)! args: $*" >&2
exit 1
EOF
chmod +x "$HOME"/bin/fail
ln -s fail "$HOME/bin/go"
export PATH="$HOME/bin:$PATH"

# Just to be sure...
assert_fail go

cat >>.mise.toml <<EOF
[tools]
go = "prefix:1.24"
"go:github.com/jdx/go-example" = "v0.1.0"
"go:github.com/jdx/go-example/deep/cmd/tool/v2[tags=postgres]" = "latest"
[settings]
experimental = true
# go-example's untagged deep module resolves to a pseudo-version minted on every
# commit; the default 24h minimum_release_age would hide a fresh one.
minimum_release_age = "0s"
EOF

mise install go
GOPROXY=direct mise install

eval "$(mise activate bash --shims)"

assert "go-example" "hello world"
assert "tool" "deep v2 postgres"

# A published go.mod can miss a requirement its packages need. `go install
# -mod=readonly` rejects that with "updates to go.mod needed", so mise uses
# -mod=mod, which still keeps a project's GOFLAGS=-mod=vendor out (#7052).
# A local GOPROXY serves such a module: untidy imports dep without requiring it.
python3 - "$PWD/goproxy" <<'PY'
import json, pathlib, sys, zipfile

proxy = pathlib.Path(sys.argv[1])
modules = {
    ("example.com/dep", "v1.0.0"): {
        "go.mod": "module example.com/dep\n\ngo 1.22\n",
        "dep.go": 'package dep\n\nfunc Msg() string { return "untidy ok" }\n',
    },
    ("example.com/untidy", "v0.1.0"): {
        "go.mod": "module example.com/untidy\n\ngo 1.22\n",
        "cmd/untidy/main.go": 'package main\n\nimport (\n\t"fmt"\n\n\t"example.com/dep"\n)\n\nfunc main() { fmt.Println(dep.Msg()) }\n',
    },
}
for (module, version), files in modules.items():
    d = proxy / module / "@v"
    d.mkdir(parents=True)
    (d / "list").write_text(version + "\n")
    (d / f"{version}.info").write_text(json.dumps({"Version": version, "Time": "2026-01-01T00:00:00Z"}))
    (d / f"{version}.mod").write_text(files["go.mod"])
    with zipfile.ZipFile(d / f"{version}.zip", "w") as zf:
        for name, body in files.items():
            zf.writestr(f"{module}@{version}/{name}", body)
PY
assert \
  "GOPROXY=file://$PWD/goproxy GOSUMDB=off GOFLAGS=-mod=vendor mise x go:example.com/untidy/cmd/untidy@v0.1.0 -- untidy" \
  "untidy ok"

# Remote-version caches for the same module must be isolated by Go's routing
# configuration. Without that isolation, the GOPROXY=off lookup reuses the
# public proxy's cached list.
assert_contains \
  "GOPROXY=https://proxy.golang.org mise ls-remote go:github.com/jdx/go-example" \
  "0.1.0"
assert_not_contains \
  "GOPROXY=off mise ls-remote go:github.com/jdx/go-example 2>&1" \
  "0.1.0"

# See https://github.com/jdx/mise/discussions/6737
assert "mise x go:github.com/jdx/go-example@e16a340 -- go-example" "hello world"

# Deep sub-module with no tagged versions; direct mode resolves a pseudo-version via @latest.
assert_matches \
  "GOPROXY=direct mise install --dry-run 'go:github.com/jdx/go-example/deep/cmd/tool/v2@latest' 2>&1" \
  'go:github.com/jdx/go-example/deep/cmd/tool/v2@2\.0\.0-[0-9]{14}-[0-9a-f]+'

# The parent-path walk below misses before it hits, and `go list` complains to stderr on
# every miss. That belongs behind --verbose rather than in the default output.
# See https://github.com/jdx/mise/discussions/5189
# Runs before the assertion below because a warm version cache would skip `go` entirely.
assert_not_contains \
  "GOPROXY=direct mise install --dry-run 'go:github.com/noperator/sol/cmd/sol@latest' 2>&1" \
  "go: module"

# Package in a subdirectory of an untagged root module; direct mode must walk
# parent paths to resolve the module's pseudo-version.
assert_matches \
  "GOPROXY=direct mise install --dry-run 'go:github.com/noperator/sol/cmd/sol@latest' 2>&1" \
  'go:github.com/noperator/sol/cmd/sol@0\.0\.0-[0-9]{14}-[0-9a-f]+'

# Required to properly cleanup as go installs read-only sources
if [ -d ~/go ]; then
  chmod -R +w ~/go
fi
