#!/bin/sh
# Host-safe entry point for the pinned RVBox build toolchain.
set -eu

repo_root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
compose_file=$repo_root/deploy/compose.yaml
toolchain_image=rvbox-dev-toolchain:latest
cache_volumes='rvbox-dev_rvbox-go-build rvbox-dev_rvbox-go-mod'

usage() {
    cat <<'EOF'
usage: scripts/build build|verify|doctor|recover|clean [options]

  build             build supported binaries in the pinned toolchain
  verify            run the normal pinned verification gate
  doctor            read-only toolchain/artifact/cache availability report
  recover           rebuild a missing/broken toolchain image, then build
  clean             print owned cleanup targets; no deletion without --execute

clean options:
  --artifacts       remove only this repository's ignored bin/ directory
  --toolchain       remove only rvbox-dev-toolchain:latest
  --caches          remove only the two named RVBox Go cache volumes
  --all             select all three owned target classes
  --execute          perform the selected deletion (otherwise dry run)
  --yes              skip the interactive confirmation; requires --execute

Run artifacts below .test-runs/ are deliberately not a build-clean target.
Use scripts/test-env purge --run-id ID (or its explicit --all workflow) so a
resumable test environment is never removed by a build cleanup operation.
EOF
}

fail() { printf '%s\n' "build: $*" >&2; exit 2; }

docker_ready() {
    docker version >/dev/null 2>&1 || fail "Docker is unavailable; start or repair Docker, then retry"
    docker compose -f "$compose_file" version >/dev/null 2>&1 || fail "Docker Compose is unavailable"
}

ensure_toolchain() {
    docker_ready
    if ! docker image inspect "$toolchain_image" >/dev/null 2>&1; then
        printf '%s\n' "build: toolchain image is absent; rebuilding from $compose_file" >&2
        docker compose -f "$compose_file" build toolchain
    fi
}

run_make() {
    target=$1
    ensure_toolchain
    cd "$repo_root"
    exec docker compose -f "$compose_file" run --rm toolchain make "$target"
}

size_of() {
    path=$1
    if [ -e "$path" ]; then du -sh "$path" 2>/dev/null | awk '{print $1}' || printf '%s' '?'; else printf '%s' '0'; fi
}

doctor() {
    docker_ready
    printf 'repository=%s\n' "$repo_root"
    if docker image inspect "$toolchain_image" >/dev/null 2>&1; then
        printf 'toolchain_image=%s present\n' "$toolchain_image"
    else
        printf 'toolchain_image=%s absent (scripts/build build will rebuild it)\n' "$toolchain_image"
    fi
    for volume in $cache_volumes; do
        if docker volume inspect "$volume" >/dev/null 2>&1; then
            printf 'cache_volume=%s present\n' "$volume"
        else
            printf 'cache_volume=%s absent (Go will repopulate it)\n' "$volume"
        fi
    done
    printf 'build_artifacts=%s size=%s\n' "$repo_root/bin" "$(size_of "$repo_root/bin")"
    printf '%s\n' 'test artifacts are managed separately by scripts/test-env'
}

confirm() {
    [ "$yes" = yes ] && return 0
    [ -t 0 ] || fail "--execute without a terminal requires --yes"
    printf '%s' 'Proceed with exactly the printed RVBox cleanup targets? [y/N] ' >&2
    read -r answer
    [ "$answer" = y ] || [ "$answer" = Y ] || fail "cleanup cancelled"
}

clean() {
    artifacts=no
    toolchain=no
    caches=no
    execute=no
    yes=no
    while [ "$#" -gt 0 ]; do
        case $1 in
            --artifacts) artifacts=yes ;;
            --toolchain) toolchain=yes ;;
            --caches) caches=yes ;;
            --all) artifacts=yes; toolchain=yes; caches=yes ;;
            --execute) execute=yes ;;
            --yes) yes=yes ;;
            --help|-h) usage; return 0 ;;
            *) fail "unknown clean option $1" ;;
        esac
        shift
    done
    [ "$artifacts" = yes ] || [ "$toolchain" = yes ] || [ "$caches" = yes ] || fail "select at least one clean target"
    docker_ready
    printf '%s\n' 'RVBox cleanup targets:'
    if [ "$artifacts" = yes ]; then
        if [ -L "$repo_root/bin" ]; then fail "refusing symlink build-artifact target $repo_root/bin"; fi
        printf '  artifact_dir=%s size=%s\n' "$repo_root/bin" "$(size_of "$repo_root/bin")"
    fi
    if [ "$toolchain" = yes ]; then
        if docker image inspect "$toolchain_image" >/dev/null 2>&1; then
            users=$(docker ps -a --filter "ancestor=$toolchain_image" --format '{{.ID}}' | wc -l | tr -d ' ')
            printf '  toolchain_image=%s containers=%s\n' "$toolchain_image" "$users"
            [ "$users" = 0 ] || fail "refusing to remove an image still referenced by containers"
        else
            printf '  toolchain_image=%s absent\n' "$toolchain_image"
        fi
    fi
    if [ "$caches" = yes ]; then
        for volume in $cache_volumes; do
            if docker volume inspect "$volume" >/dev/null 2>&1; then
                printf '  cache_volume=%s\n' "$volume"
            else
                printf '  cache_volume=%s absent\n' "$volume"
            fi
        done
    fi
    if [ "$execute" != yes ]; then
        printf '%s\n' 'dry run only; rerun with --execute (and optionally --yes) to delete these exact targets'
        return 0
    fi
    confirm
    if [ "$artifacts" = yes ] && [ -d "$repo_root/bin" ]; then rm -rf "$repo_root/bin"; fi
    if [ "$toolchain" = yes ] && docker image inspect "$toolchain_image" >/dev/null 2>&1; then docker image rm "$toolchain_image"; fi
    if [ "$caches" = yes ]; then
        for volume in $cache_volumes; do
            if docker volume inspect "$volume" >/dev/null 2>&1; then docker volume rm "$volume"; fi
        done
    fi
    printf '%s\n' 'RVBox build cleanup complete; scripts/build recover will recreate the toolchain and build artifacts.'
}

command=${1:-build}
shift || true
case $command in
    build|verify) [ "$#" -eq 0 ] || fail "$command does not accept additional arguments"; run_make "$command" ;;
    doctor) [ "$#" -eq 0 ] || fail "doctor does not accept additional arguments"; doctor ;;
    recover) [ "$#" -eq 0 ] || fail "recover does not accept additional arguments"; docker_ready; docker compose -f "$compose_file" build toolchain; run_make build ;;
    clean) clean "$@" ;;
    --help|-h) usage ;;
    *) usage >&2; fail "unknown command $command" ;;
esac
