#!/usr/bin/env bash

# A bun install with no lockfile entry checks the archive against the checksum
# Bun publishes in SHASUMS256.txt, not only against one mise.lock already holds.

RELEASE="$(mktemp -d "${TMPDIR:-/tmp}/bun-release.XXXXXX")"

# How SHASUMS256.txt is answered is read from "$RELEASE/mode": "genuine" lists
# the archive's checksum, "tampered" another checksum, "other-file" lists only
# another archive, "absent" is a 404 and "error" a 500
start_http_server --dir "$RELEASE" --handler - <<'PY'
import hashlib
import io
import zipfile
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path

state_file = Path("last-requested-zip.txt").absolute()
mode_file = Path("mode").absolute()
script = b"""#!/usr/bin/env bash
echo 1.3.10
"""

class Handler(BaseHTTPRequestHandler):
    def reply(self, data):
        self.send_response(200)
        self.send_header("Content-Length", str(len(data)))
        self.end_headers()
        self.wfile.write(data)

    def do_GET(self):
        path = self.path.split("?", 1)[0]
        if path.endswith(".zip"):
            zip_name = Path(path).name
            body = io.BytesIO()
            with zipfile.ZipFile(body, "w") as zf:
                info = zipfile.ZipInfo(f"{zip_name.removesuffix('.zip')}/bun")
                info.create_system = 3
                info.external_attr = 0o755 << 16
                zf.writestr(info, script)
            data = body.getvalue()
            state_file.write_text(f"{zip_name}\n{hashlib.sha256(data).hexdigest()}\n")
            return self.reply(data)
        if path.endswith("SHASUMS256.txt") and state_file.exists():
            zip_name, sha = state_file.read_text().splitlines()[:2]
            mode = mode_file.read_text().strip()
            if mode == "absent":
                return self.send_error(404)
            if mode == "error":
                return self.send_error(500)
            if mode == "tampered":
                sha = "0" * 64
            if mode == "other-file":
                zip_name = "bun-other-platform.zip"
            return self.reply(f"{sha}  {zip_name}\n".encode())
        self.send_error(404)


SERVER_CLASS = HTTPServer
PY

MISE_URL_REPLACEMENTS="$(printf '{\"https://github.com/oven-sh/bun/releases/download\":\"http://127.0.0.1:%s\"}' "$HTTP_PORT")"
export MISE_URL_REPLACEMENTS
# Retries would turn the 500 case into minutes of backoff
export MISE_HTTP_RETRIES=0

echo tampered >"$RELEASE/mode"
assert_fail "mise install bun@1.3.10" "Checksum mismatch"
assert_directory_not_exists "$MISE_DATA_DIR/installs/bun/1.3.10/bin"

# A checksum file that exists must list the archive
echo other-file >"$RELEASE/mode"
assert_fail "mise install bun@1.3.10" "does not list a checksum for this archive"
assert_directory_not_exists "$MISE_DATA_DIR/installs/bun/1.3.10/bin"

# A failed request is not taken for a release without checksums
echo error >"$RELEASE/mode"
assert_fail "mise install bun@1.3.10" "failed to fetch checksum"
assert_directory_not_exists "$MISE_DATA_DIR/installs/bun/1.3.10/bin"

echo genuine >"$RELEASE/mode"
assert_succeed "mise install bun@1.3.10"
assert_contains "mise x bun@1.3.10 -- bun -v" "1.3.10"

# A release that never published SHASUMS256.txt installs with a warning
mise uninstall bun@1.3.10
echo absent >"$RELEASE/mode"
assert_contains "mise install bun@1.3.10 2>&1" "skipping checksum verification"
