#!/usr/bin/env bash
# Credential table: where each agent runtime's auth file lives on the host and
# where that runtime expects it inside the container. Paths only — this library
# never reads, prints or exports a credential value.

AGENT_CRED_STAGING_ROOT=/sandbox-secrets
AGENT_CRED_RC_UNRESOLVED=10

_agent_cred_host_path() {
  case "${1-}" in
    codex)        printf '%s/auth.json\n' "${CODEX_HOME:-$HOME/.codex}" ;;
    claude)       printf '%s/.claude/.credentials.json\n' "$HOME" ;;
    cursor-agent) printf '%s/cursor/auth.json\n' "${XDG_CONFIG_HOME:-$HOME/.config}" ;;
    *) return 1 ;;
  esac
}

_agent_cred_container_path() {
  case "${1-}" in
    codex)        printf '.codex/auth.json\n' ;;
    claude)       printf '.claude/.credentials.json\n' ;;
    cursor-agent) printf '.config/cursor/auth.json\n' ;;
    *) return 1 ;;
  esac
}

agent_cred_runtimes() {
  printf '%s\n' codex claude cursor-agent
}

# <runtime> -> "<runtime>\t<host realpath>\t<container-relative path>".
# The realpath is the credential identity: for codex it resolves through the
# per-account symlink chain and names which account the run authenticates as.
agent_cred_resolve() {
  local runtime="${1-}" host_path container_path resolved

  if ! host_path="$(_agent_cred_host_path "$runtime")"; then
    printf 'agent_cred: unknown runtime: %s\n' "$runtime" >&2
    return "$AGENT_CRED_RC_UNRESOLVED"
  fi
  container_path="$(_agent_cred_container_path "$runtime")"

  if [[ -L "$host_path" && ! -e "$host_path" ]]; then
    printf 'agent_cred: %s credential is a broken symlink: %s\n' "$runtime" "$host_path" >&2
    return "$AGENT_CRED_RC_UNRESOLVED"
  fi
  if [[ ! -e "$host_path" ]]; then
    printf 'agent_cred: %s credential path does not exist: %s\n' "$runtime" "$host_path" >&2
    return "$AGENT_CRED_RC_UNRESOLVED"
  fi
  if ! resolved="$(readlink -f "$host_path" 2>/dev/null)" || [[ -z "$resolved" ]]; then
    printf 'agent_cred: %s credential path did not resolve: %s\n' "$runtime" "$host_path" >&2
    return "$AGENT_CRED_RC_UNRESOLVED"
  fi
  if [[ ! -f "$resolved" ]]; then
    printf 'agent_cred: %s credential is not a regular file: %s\n' "$runtime" "$resolved" >&2
    return "$AGENT_CRED_RC_UNRESOLVED"
  fi
  if [[ ! -r "$resolved" ]]; then
    printf 'agent_cred: %s credential is not readable: %s\n' "$runtime" "$resolved" >&2
    return "$AGENT_CRED_RC_UNRESOLVED"
  fi

  printf '%s\t%s\t%s\n' "$runtime" "$resolved" "$container_path"
}

# Read-only mount destination for the host credential inside the container.
agent_cred_staging_path() {
  local runtime="${1-}" staging_root="${2:-$AGENT_CRED_STAGING_ROOT}" container_path
  if ! container_path="$(_agent_cred_container_path "$runtime")"; then
    printf 'agent_cred: unknown runtime: %s\n' "$runtime" >&2
    return "$AGENT_CRED_RC_UNRESOLVED"
  fi
  printf '%s/%s/%s\n' "${staging_root%/}" "$runtime" "${container_path##*/}"
}

# POSIX-sh snippet run inside the container before the agent CLI: copies the
# read-only staging file into the container's writable HOME at the pathname the
# runtime expects, and removes that copy when the shell running it exits. The
# caller must keep that shell alive for the agent's lifetime (run the agent as a
# child and wait) — an exec would discard the trap and leave the copy behind.
# The staging path is baked in as a literal, so nothing inside the container can
# redirect where the credential is read from.
agent_cred_stage_script() {
  local runtime="${1-}" staging_root="${2:-$AGENT_CRED_STAGING_ROOT}" container_path staging_path
  if ! container_path="$(_agent_cred_container_path "$runtime")"; then
    printf 'agent_cred: unknown runtime: %s\n' "$runtime" >&2
    return "$AGENT_CRED_RC_UNRESOLVED"
  fi
  if [[ "$staging_root" == *"'"* ]]; then
    printf 'agent_cred: staging root must not contain a single quote: %s\n' "$staging_root" >&2
    return "$AGENT_CRED_RC_UNRESOLVED"
  fi
  staging_path="$(agent_cred_staging_path "$runtime" "$staging_root")"

  cat <<EOF
[ -n "\${HOME-}" ] || { echo 'agent_cred: HOME unset in container' >&2; exit $AGENT_CRED_RC_UNRESOLVED; }
agent_cred_target="\${HOME%/}/$container_path"
trap 'rm -f "\$agent_cred_target"' EXIT HUP INT TERM
mkdir -p "\${agent_cred_target%/*}" || { echo 'agent_cred: cannot create credential directory' >&2; exit $AGENT_CRED_RC_UNRESOLVED; }
[ -r '$staging_path' ] || { echo 'agent_cred: staging mount missing: $staging_path' >&2; exit $AGENT_CRED_RC_UNRESOLVED; }
cp '$staging_path' "\$agent_cred_target" || { echo 'agent_cred: credential copy failed' >&2; exit $AGENT_CRED_RC_UNRESOLVED; }
chmod 600 "\$agent_cred_target" || { echo 'agent_cred: cannot restrict credential mode' >&2; exit $AGENT_CRED_RC_UNRESOLVED; }
EOF
}
