#!/usr/bin/env bash
#
# Iapetus installer — https://get.iapetus.dev
#
# Interactive:
#   curl -fsSL https://get.iapetus.dev | bash
#
# Non-interactive (CI):
#   curl -fsSL https://get.iapetus.dev | bash -s -- --component desktop --token ghp_xxx
#
# Options:
#   --component, -c   desktop | web | develop | mcp
#   --token, -t       GitHub PAT with repo scope
#   --version, -v     Release version (default: latest)
#
# Environment:
#   IAPETUS_TOKEN     Alternative to --token
#
set -euo pipefail

REPO="demec/iapetus"
INSTALL_DIR="/usr/local/bin"

COMPONENT=""
TOKEN=""
VERSION=""

while [[ $# -gt 0 ]]; do
  case "$1" in
    --component|-c) COMPONENT="$2"; shift 2 ;;
    --token|-t)     TOKEN="$2"; shift 2 ;;
    --version|-v)   VERSION="$2"; shift 2 ;;
    --help|-h)
      cat <<'EOF'
Iapetus installer — https://get.iapetus.dev

Interactive:
  curl -fsSL https://get.iapetus.dev | bash

Non-interactive:
  curl -fsSL https://get.iapetus.dev | bash -s -- --component desktop --token ghp_xxx

Options:
  --component, -c   desktop | web | develop | mcp
  --token, -t       GitHub PAT with repo scope
  --version, -v     Release version (default: latest)

Environment:
  IAPETUS_TOKEN     Alternative to --token
EOF
      exit 0 ;;
    *) echo "Unknown option: $1" >&2; exit 1 ;;
  esac
done

TOKEN="${TOKEN:-${IAPETUS_TOKEN:-}}"

# --- TTY for interactive prompts (works when piped from curl) ---
if [ -r /dev/tty ]; then
  TTY=/dev/tty
else
  TTY=""
fi

prompt_required_tty() {
  if [[ -z "$TTY" ]]; then
    echo "Error: no interactive terminal available." >&2
    echo "Pass --component and --token explicitly for non-interactive installs." >&2
    exit 1
  fi
}

# --- Interactive component menu ---
if [[ -z "$COMPONENT" ]]; then
  prompt_required_tty
  cat <<'EOF'

  Iapetus installer · https://iapetus.dev

  1) Desktop app       (iapetus)
  2) Web API           (iapetus-web-agent)
  3) Develop agent     (develop-agent)
  4) MCP Server        (iapetus-mcp-server)

EOF
  printf "Select [1-4]: "
  read -r CHOICE < "$TTY"
  case "$CHOICE" in
    1) COMPONENT=desktop ;;
    2) COMPONENT=web ;;
    3) COMPONENT=develop ;;
    4) COMPONENT=mcp ;;
    *) echo "Invalid choice: $CHOICE" >&2; exit 1 ;;
  esac
fi

# --- Interactive token prompt ---
if [[ -z "$TOKEN" ]]; then
  prompt_required_tty
  cat <<'EOF'

  Iapetus is distributed via a private GitHub repository.
  Paste a GitHub Personal Access Token (repo scope):
  Create one at https://github.com/settings/tokens

EOF
  printf "Token: "
  read -r -s TOKEN < "$TTY"
  echo ""
  [[ -z "$TOKEN" ]] && { echo "Error: no token provided." >&2; exit 1; }
fi

# --- Prereqs ---
if ! command -v jq &>/dev/null; then
  echo "Error: jq is required. Install with: sudo apt-get install -y jq" >&2
  exit 1
fi

# --- Helpers ---
gh_api() {
  curl -fsSL \
    -H "Authorization: token ${TOKEN}" \
    -H "Accept: application/vnd.github+json" \
    "$@"
}

gh_download() {
  curl -fsSL \
    -H "Authorization: token ${TOKEN}" \
    -H "Accept: application/octet-stream" \
    "$@"
}

echo "Validating token..."
if ! gh_api "https://api.github.com/repos/${REPO}" >/dev/null 2>&1; then
  echo "Error: cannot access ${REPO}. Token needs 'repo' scope." >&2
  exit 1
fi

TMPDIR="$(mktemp -d)"
trap 'rm -rf "$TMPDIR"' EXIT

# --- Installers ---
install_desktop() {
  case "$(uname -m)" in
    x86_64)  ARCH_LABEL="amd64" ;;
    aarch64) ARCH_LABEL="arm64" ;;
    *) echo "Error: unsupported architecture: $(uname -m)" >&2; exit 1 ;;
  esac

  USE_DEB=false
  if command -v dpkg &>/dev/null && command -v apt-get &>/dev/null; then
    USE_DEB=true
  fi

  if [[ -n "$VERSION" ]]; then
    echo "Fetching release ${VERSION}..."
    RELEASE_JSON="$(gh_api "https://api.github.com/repos/${REPO}/releases/tags/${VERSION}")"
  else
    echo "Fetching latest Iapetus desktop release..."
    RELEASE_JSON="$(gh_api "https://api.github.com/repos/${REPO}/releases?per_page=100" \
      | jq '[.[] | select(
          (.tag_name | startswith("develop-agent-")      | not) and
          (.tag_name | startswith("iapetus-web-agent-")  | not) and
          (.tag_name | startswith("iapetus-mcp-server-") | not)
        )] | first')"
  fi

  TAG="$(echo "$RELEASE_JSON" | jq -r '.tag_name')"
  [[ -z "$TAG" || "$TAG" == "null" ]] && { echo "Error: no release found." >&2; exit 1; }
  echo "Version: ${TAG}"

  if $USE_DEB; then PATTERN='\.deb'; LABEL='.deb package'
  else              PATTERN='\.AppImage'; LABEL='AppImage'; fi

  echo "Looking for ${LABEL} (${ARCH_LABEL})..."
  ASSET_INFO="$(echo "$RELEASE_JSON" | jq -r \
    --arg p "$PATTERN" --arg a "$ARCH_LABEL" \
    '[.assets[] | select(.name | test($p)) | select(.name | test($a))] | first | "\(.url)\t\(.name)"')"

  if [[ -z "$ASSET_INFO" || "$ASSET_INFO" == "null"* ]]; then
    ASSET_INFO="$(echo "$RELEASE_JSON" | jq -r \
      --arg p "$PATTERN" \
      '[.assets[] | select(.name | test($p))] | first | "\(.url)\t\(.name)"')"
  fi

  URL="$(echo "$ASSET_INFO" | cut -f1)"
  NAME="$(echo "$ASSET_INFO" | cut -f2)"
  if [[ -z "$URL" || "$URL" == "null" ]]; then
    echo "Error: no matching asset in ${TAG}." >&2
    echo "$RELEASE_JSON" | jq -r '.assets[].name' | sed 's/^/  /' >&2
    exit 1
  fi

  echo "Downloading ${NAME}..."
  gh_download "$URL" -o "${TMPDIR}/${NAME}"

  if $USE_DEB; then
    echo "Installing .deb..."
    sudo dpkg -i "${TMPDIR}/${NAME}"
    sudo apt-get install -f -y
    echo "Installed iapetus ${TAG} via dpkg."
  else
    echo "Installing AppImage to ${INSTALL_DIR}/iapetus..."
    chmod +x "${TMPDIR}/${NAME}"
    sudo mv "${TMPDIR}/${NAME}" "${INSTALL_DIR}/iapetus"
    echo "Installed iapetus ${TAG}."
  fi

  # vnet-agent sidecar
  VNET_URL="$(echo "$RELEASE_JSON" | jq -r '.assets[] | select(.name == "vnet-agent") | .url')"
  if [[ -n "$VNET_URL" && "$VNET_URL" != "null" ]]; then
    echo "Downloading vnet-agent..."
    gh_download "$VNET_URL" -o "${TMPDIR}/vnet-agent"
    chmod +x "${TMPDIR}/vnet-agent"
    sudo mv "${TMPDIR}/vnet-agent" "${INSTALL_DIR}/vnet-agent"
    echo "Installed vnet-agent."
  fi
}

install_binary_agent() {
  local bin_name="$1" tag_prefix="$2" display="$3"

  if [[ -n "$VERSION" ]]; then
    TAG="${tag_prefix}${VERSION}"
    echo "Fetching ${display} release ${TAG}..."
    RELEASE_JSON="$(gh_api "https://api.github.com/repos/${REPO}/releases/tags/${TAG}")"
  else
    echo "Fetching latest ${display} release..."
    RELEASE_JSON="$(gh_api "https://api.github.com/repos/${REPO}/releases?per_page=100" \
      | jq --arg p "$tag_prefix" '[.[] | select(.tag_name | startswith($p))] | first')"
  fi

  TAG="$(echo "$RELEASE_JSON" | jq -r '.tag_name')"
  [[ -z "$TAG" || "$TAG" == "null" ]] && { echo "Error: no ${display} release found." >&2; exit 1; }
  echo "Version: ${TAG}"

  ASSET_URL="$(echo "$RELEASE_JSON" | jq -r --arg n "$bin_name" \
    '.assets[] | select(.name == $n) | .url')"
  if [[ -z "$ASSET_URL" || "$ASSET_URL" == "null" ]]; then
    echo "Error: ${bin_name} not found in release ${TAG}." >&2
    echo "$RELEASE_JSON" | jq -r '.assets[].name' | sed 's/^/  /' >&2
    exit 1
  fi

  echo "Downloading ${bin_name}..."
  gh_download "$ASSET_URL" -o "${TMPDIR}/${bin_name}"
  chmod +x "${TMPDIR}/${bin_name}"
  sudo mv "${TMPDIR}/${bin_name}" "${INSTALL_DIR}/${bin_name}"
  echo "Installed ${bin_name} ${TAG} to ${INSTALL_DIR}/${bin_name}."
}

case "$COMPONENT" in
  desktop) install_desktop ;;
  web)     install_binary_agent "iapetus-web-agent"  "iapetus-web-agent-"  "iapetus-web-agent" ;;
  develop) install_binary_agent "develop-agent"      "develop-agent-"      "develop-agent" ;;
  mcp)     install_binary_agent "iapetus-mcp-server" "iapetus-mcp-server-" "iapetus-mcp-server" ;;
  *) echo "Unknown component: $COMPONENT (expected desktop|web|develop|mcp)" >&2; exit 1 ;;
esac

echo ""
echo "Done."
