#!/usr/bin/env bash
set -euo pipefail

DEFAULT_DOWNLOAD_BASE_URL="https://terminaili.com/downloads/ipop-agent"

download_base_url="${IPOP_AGENT_DOWNLOAD_BASE_URL:-${DEFAULT_DOWNLOAD_BASE_URL}}"
install_dir="${IPOP_INSTALL_DIR:-}"
archive_override="${IPOP_AGENT_ARCHIVE:-}"
enrollment_token="${IPOP_NODE_ENROLLMENT_TOKEN:-${IPOP_ENROLLMENT_TOKEN:-}}"
skip_checksum="${IPOP_AGENT_SKIP_CHECKSUM:-}"
agent_args=()
doctor_args=()
service_args=()

usage() {
  cat <<EOF
Usage:
  install-ipop-agent.sh [--token TOKEN] [ipop-agent install options]

Environment:
  IPOP_AGENT_DOWNLOAD_BASE_URL  Base URL for ipop-agent archives.
  IPOP_AGENT_ARCHIVE            Use a local archive instead of downloading.
  IPOP_AGENT_SKIP_CHECKSUM      Set to 1 only for private test mirrors without .sha256 files.
  IPOP_INSTALL_DIR              Install directory. Defaults to /usr/local/bin or ~/.local/bin.
  IPOP_NODE_ENROLLMENT_TOKEN    Optional managed-fleet enrollment token, equivalent to --token.

Examples:
  curl -fsSL https://terminaili.com/downloads/ipop-agent/install.sh | bash
  curl -fsSL https://terminaili.com/downloads/ipop-agent/install.sh | bash -s -- --token TOKEN
  ./install-ipop-agent.sh --download-base-url https://terminaili.com/downloads/ipop-agent
  IPOP_AGENT_ARCHIVE=./ipop-agent-macos-arm64.tar.gz ./scripts/install-ipop-agent.sh
EOF
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --help|-h)
      usage
      exit 0
      ;;
    --token|-t)
      if [[ $# -lt 2 ]]; then
        echo "--token requires a token" >&2
        exit 2
      fi
      enrollment_token="$2"
      shift 2
      ;;
    --token=*)
      enrollment_token="${1#--token=}"
      shift
      ;;
    --download-base-url)
      if [[ $# -lt 2 ]]; then
        echo "--download-base-url requires a URL" >&2
        exit 2
      fi
      download_base_url="${2%/}"
      shift 2
      ;;
    --download-base-url=*)
      download_base_url="${1#--download-base-url=}"
      download_base_url="${download_base_url%/}"
      shift
      ;;
    --no-service|--no-start|--force|--start|--service)
      agent_args+=("$1")
      shift
      ;;
    --api-base-url|--node-name|--wallet-address|--model-cache-root|--session-file|--status-file|--agent-env-file)
      if [[ $# -lt 2 ]]; then
        echo "$1 requires a value" >&2
        exit 2
      fi
      agent_args+=("$1" "$2")
      doctor_args+=("$1" "$2")
      shift 2
      ;;
    --api-base-url=*|--node-name=*|--wallet-address=*|--model-cache-root=*|--session-file=*|--status-file=*|--agent-env-file=*)
      agent_args+=("$1")
      doctor_args+=("$1")
      shift
      ;;
    *)
      agent_args+=("$1")
      doctor_args+=("$1")
      shift
      ;;
  esac
done

require_cmd() {
  if ! command -v "$1" >/dev/null 2>&1; then
    echo "missing required command: $1" >&2
    exit 1
  fi
}

detect_os() {
  case "$(uname -s)" in
    Darwin) printf 'macos\n' ;;
    Linux) printf 'linux\n' ;;
    *)
      echo "unsupported OS: $(uname -s)" >&2
      exit 1
      ;;
  esac
}

detect_arch() {
  case "$(uname -m)" in
    arm64|aarch64) printf 'arm64\n' ;;
    x86_64|amd64) printf 'x64\n' ;;
    *)
      echo "unsupported architecture: $(uname -m)" >&2
      exit 1
      ;;
  esac
}

choose_install_dir() {
  if [[ -n "${install_dir}" ]]; then
    printf '%s\n' "${install_dir}"
    return 0
  fi
  if [[ -w "/usr/local/bin" ]]; then
    printf '/usr/local/bin\n'
    return 0
  fi
  if command -v sudo >/dev/null 2>&1; then
    printf '/usr/local/bin\n'
    return 0
  fi
  printf '%s\n' "${HOME}/.local/bin"
}

install_binary() {
  local source="$1"
  local destination_dir="$2"
  local destination="${destination_dir}/ipop-agent"

  if [[ "${destination_dir}" == "/usr/local/bin" && ! -w "${destination_dir}" ]]; then
    sudo install -m 0755 "${source}" "${destination}"
  else
    mkdir -p "${destination_dir}"
    install -m 0755 "${source}" "${destination}"
  fi
  printf '%s\n' "${destination}"
}

require_cmd tar

tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/ipop-agent-install.XXXXXX")"
trap 'rm -rf "${tmp_dir}"' EXIT

os="$(detect_os)"
arch="$(detect_arch)"
artifact="ipop-agent-${os}-${arch}.tar.gz"
archive_path="${tmp_dir}/${artifact}"

if [[ -n "${archive_override}" ]]; then
  cp "${archive_override}" "${archive_path}"
else
  require_cmd curl
  if ! curl -fsSL "${download_base_url}/${artifact}" -o "${archive_path}"; then
    echo "failed to download ${artifact} from ${download_base_url}" >&2
    echo "this platform may not have a prebuilt ipop-agent yet; see ${download_base_url}/manifest.json" >&2
    exit 1
  fi
  if [[ "${skip_checksum}" == "1" ]]; then
    echo "warning: skipping checksum verification because IPOP_AGENT_SKIP_CHECKSUM=1" >&2
  else
    if ! command -v shasum >/dev/null 2>&1 && ! command -v sha256sum >/dev/null 2>&1; then
      echo "missing shasum or sha256sum for archive verification" >&2
      exit 1
    fi
    if ! curl -fsSL "${download_base_url}/${artifact}.sha256" -o "${archive_path}.sha256"; then
      echo "missing checksum for ${artifact}; refusing to install unverified archive" >&2
      exit 1
    fi
    if command -v shasum >/dev/null 2>&1; then
      (cd "${tmp_dir}" && shasum -a 256 -c "${artifact}.sha256")
    else
      (cd "${tmp_dir}" && sha256sum -c "${artifact}.sha256")
    fi
  fi
fi

tar -xzf "${archive_path}" -C "${tmp_dir}"
if [[ ! -x "${tmp_dir}/ipop-agent" ]]; then
  echo "archive did not contain an executable ipop-agent binary" >&2
  exit 1
fi

destination_dir="$(choose_install_dir)"
installed_binary="$(install_binary "${tmp_dir}/ipop-agent" "${destination_dir}")"

if [[ -n "${enrollment_token}" ]]; then
  service_args+=(--token "${enrollment_token}")
fi

"${installed_binary}" install "${service_args[@]}" "${agent_args[@]}"
"${installed_binary}" doctor "${doctor_args[@]}" || true

cat <<EOF

ipop-agent installed at:
  ${installed_binary}

Useful commands:
  ipop-agent doctor
  ipop-agent service status
  ipop-agent service restart
EOF
