#!/usr/bin/env bash
set -Eeuo pipefail
trap 'status=$?; printf "\033[1;31mERROR:\033[0m uninstall failed near line %s: %s\n" "$LINENO" "$BASH_COMMAND" >&2; exit "$status"' ERR

CONFIG_FILE="/etc/kageos-helper.env"

if [[ -r "$CONFIG_FILE" ]]; then
  # shellcheck disable=SC1091
  source "$CONFIG_FILE"
fi

KAGEOS_CONTAINER_NAME="${KAGEOS_CONTAINER_NAME:-kageos}"
KAGEOS_INSTALL_DIR="${KAGEOS_INSTALL_DIR:-/opt/kageos}"
KAGEOS_DATA_DIR="${KAGEOS_DATA_DIR:-${KAGEOS_INSTALL_DIR%/}/data}"
KAGEOS_CONTAINER_ENGINE="${KAGEOS_CONTAINER_ENGINE:-${KAGEOS_ENGINE:-auto}}"
KAGEOS_IMAGE="${KAGEOS_IMAGE:-}"
KAGEOS_APP_BASE_IMAGE="${KAGEOS_APP_BASE_IMAGE:-}"
KAGEOS_TLS_MODE="${KAGEOS_TLS_MODE:-}"
KAGEOS_HTTP_PORT="${KAGEOS_HTTP_PORT:-}"
KAGEOS_HTTPS_PORT="${KAGEOS_HTTPS_PORT:-}"

YES=0
PURGE=0
REMOVE_IMAGES=0
REMOVE_LEGACY_DEV=0
DRY_RUN=0

usage() {
  cat <<'EOF'
kageos production uninstaller

Usage:
  curl -fsSL https://kageos.com/uninstall-prod.sh | sudo bash -s -- --yes
  curl -fsSL https://kageos.com/uninstall-prod.sh | sudo bash -s -- --yes --purge
  curl -fsSL https://kageos.com/uninstall-prod.sh | sudo bash -s -- --yes --purge --remove-images

What it removes:
  - The kageos outer container from Docker/Podman.
  - /usr/local/bin/kageos and /etc/kageos-helper.env.
  - Scoped host FORWARD rules created by the kageos installer.
  - Persistent data only when --purge is passed.
  - kageos/kagebase image tags only when --remove-images is passed.

Options:
  --yes                       Required to make changes.
  --purge                     Delete persistent data and install directory.
  --remove-images             Remove known kageos/kagebase image tags.
  --remove-legacy-dev         Also remove old ai-agent-os-dev-* containers.
  --container-name NAME       Container name. Defaults to kageos.
  --install-dir DIR           Install directory. Defaults to /opt/kageos.
  --data-dir DIR              Data directory. Defaults to <install-dir>/data.
  --container-engine ENGINE   auto, podman, or docker. Defaults to auto.
  --dry-run                   Print the plan and commands without changing the host.
  --help                      Show this help.

Notes:
  This script is intentionally scoped to kageos-managed resources. It does not
  remove unrelated services such as 1Panel, external MySQL, Nginx, or Redis.
EOF
}

log() {
  printf '\033[1;36m==>\033[0m %s\n' "$*"
}

warn() {
  printf '\033[1;33mWARN:\033[0m %s\n' "$*" >&2
}

die() {
  printf '\033[1;31mERROR:\033[0m %s\n' "$*" >&2
  exit 1
}

need_value() {
  local option="$1"
  shift
  [[ $# -gt 0 && -n "${1:-}" ]] || die "$option requires a value"
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --yes|-y)
      YES=1
      ;;
    --purge)
      PURGE=1
      ;;
    --remove-images)
      REMOVE_IMAGES=1
      ;;
    --remove-legacy-dev)
      REMOVE_LEGACY_DEV=1
      ;;
    --container-name)
      shift
      need_value "--container-name" "$@"
      KAGEOS_CONTAINER_NAME="$1"
      ;;
    --install-dir)
      shift
      need_value "--install-dir" "$@"
      KAGEOS_INSTALL_DIR="$1"
      ;;
    --data-dir)
      shift
      need_value "--data-dir" "$@"
      KAGEOS_DATA_DIR="$1"
      ;;
    --container-engine)
      shift
      need_value "--container-engine" "$@"
      KAGEOS_CONTAINER_ENGINE="$1"
      ;;
    --dry-run)
      DRY_RUN=1
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      usage >&2
      die "unknown option: $1"
      ;;
  esac
  shift
done

KAGEOS_DATA_DIR="${KAGEOS_DATA_DIR:-${KAGEOS_INSTALL_DIR%/}/data}"

if [[ "${EUID:-$(id -u)}" -ne 0 && "$DRY_RUN" != "1" ]]; then
  die "run this uninstaller with sudo"
fi

case "$KAGEOS_CONTAINER_ENGINE" in
  auto|podman|docker) ;;
  *) die "--container-engine must be auto, podman, or docker" ;;
esac

engines=()
if [[ "$KAGEOS_CONTAINER_ENGINE" == "auto" ]]; then
  command -v podman >/dev/null 2>&1 && engines+=("podman")
  command -v docker >/dev/null 2>&1 && engines+=("docker")
else
  if command -v "$KAGEOS_CONTAINER_ENGINE" >/dev/null 2>&1; then
    engines+=("$KAGEOS_CONTAINER_ENGINE")
  else
    warn "container engine not found: ${KAGEOS_CONTAINER_ENGINE}"
  fi
fi

run_cmd() {
  if [[ "$DRY_RUN" == "1" ]]; then
    printf '+'
    printf ' %q' "$@"
    printf '\n'
    return 0
  fi
  "$@"
}

safe_path() {
  local path="$1"
  [[ -n "$path" ]] || return 1
  case "$path" in
    /|/.|/..|/bin|/boot|/dev|/etc|/home|/lib|/lib64|/opt|/proc|/root|/run|/sbin|/sys|/tmp|/usr|/var)
      return 1
      ;;
  esac
  [[ "$path" == /* ]] || return 1
  return 0
}

remove_file_if_exists() {
  local path="$1"
  if [[ -e "$path" || -L "$path" ]]; then
    log "Removing ${path}"
    run_cmd rm -f "$path"
  fi
}

remove_dir_if_exists() {
  local path="$1"
  if ! safe_path "$path"; then
    die "refusing to remove unsafe path: ${path}"
  fi
  if [[ -e "$path" || -L "$path" ]]; then
    log "Removing ${path}"
    run_cmd rm -rf "$path"
  fi
}

remove_container_from_engine() {
  local engine="$1"
  local name="$2"
  if "$engine" container inspect "$name" >/dev/null 2>&1; then
    log "Removing ${engine} container: ${name}"
    if [[ "$DRY_RUN" == "1" ]]; then
      run_cmd "$engine" rm -f "$name"
    else
      "$engine" rm -f "$name" >/dev/null
    fi
  fi
}

remove_image_from_engine() {
  local engine="$1"
  local image="$2"
  [[ -n "$image" ]] || return 0
  if "$engine" image inspect "$image" >/dev/null 2>&1; then
    log "Removing ${engine} image: ${image}"
    if [[ "$DRY_RUN" == "1" ]]; then
      run_cmd "$engine" rmi -f "$image"
    else
      "$engine" rmi -f "$image" >/dev/null 2>&1 || true
    fi
  fi
}

remove_forward_rule_for_port() {
  local port="$1"
  [[ -n "$port" ]] || return 0
  command -v iptables >/dev/null 2>&1 || return 0

  while iptables -C FORWARD -p tcp --dport "$port" -m comment --comment "kageos public port ${port}" -j ACCEPT 2>/dev/null; do
    log "Removing host FORWARD rule for kageos port ${port}"
    run_cmd iptables -D FORWARD -p tcp --dport "$port" -m comment --comment "kageos public port ${port}" -j ACCEPT
  done
}

remove_host_forward_rules() {
  remove_forward_rule_for_port "$KAGEOS_HTTP_PORT"
  if [[ "$KAGEOS_TLS_MODE" == "https" || "$KAGEOS_TLS_MODE" == "redirect" ]]; then
    if [[ "$KAGEOS_HTTPS_PORT" != "$KAGEOS_HTTP_PORT" ]]; then
      remove_forward_rule_for_port "$KAGEOS_HTTPS_PORT"
    fi
  fi
}

print_plan() {
  cat <<EOF
kageos uninstall plan

container:       ${KAGEOS_CONTAINER_NAME}
install dir:     ${KAGEOS_INSTALL_DIR}
data dir:        ${KAGEOS_DATA_DIR}
engines:         ${engines[*]:-(none found)}
purge data:      ${PURGE}
remove images:   ${REMOVE_IMAGES}
legacy dev:      ${REMOVE_LEGACY_DEV}
dry run:         ${DRY_RUN}
EOF
}

print_plan

if [[ "$YES" != "1" && "$DRY_RUN" != "1" ]]; then
  cat >&2 <<'EOF'

No changes were made. Re-run with --yes to uninstall.
Use --purge only when you also want to delete persistent data.
EOF
  exit 0
fi

if [[ "${#engines[@]}" -eq 0 ]]; then
  warn "no Docker or Podman binary found; continuing with file cleanup"
fi

for engine in "${engines[@]}"; do
  remove_container_from_engine "$engine" "$KAGEOS_CONTAINER_NAME"
  if [[ "$REMOVE_LEGACY_DEV" == "1" ]]; then
    remove_container_from_engine "$engine" "ai-agent-os-dev-mysql"
    remove_container_from_engine "$engine" "ai-agent-os-dev-nats"
    remove_container_from_engine "$engine" "ai-agent-os-dev-minio"
  fi
done

remove_host_forward_rules
remove_file_if_exists /usr/local/bin/kageos
remove_file_if_exists "$CONFIG_FILE"

if [[ "$PURGE" == "1" ]]; then
  if [[ "$KAGEOS_DATA_DIR" != "$KAGEOS_INSTALL_DIR" ]]; then
    remove_dir_if_exists "$KAGEOS_DATA_DIR"
  fi
  remove_dir_if_exists "$KAGEOS_INSTALL_DIR"
else
  log "Data kept: ${KAGEOS_DATA_DIR}"
fi

if [[ "$REMOVE_IMAGES" == "1" ]]; then
  images=(
    "$KAGEOS_IMAGE"
    "$KAGEOS_APP_BASE_IMAGE"
    "docker.io/qiayanai/kageos:latest"
    "docker.io/qiayanai/kagebase:latest"
    "qiayanai/kageos:latest"
    "qiayanai/kagebase:latest"
    "crpi-pp1889gb5d5betoy.cn-beijing.personal.cr.aliyuncs.com/qiayanai/kageos:latest"
    "crpi-pp1889gb5d5betoy.cn-beijing.personal.cr.aliyuncs.com/qiayanai/kagebase:latest"
  )
  for engine in "${engines[@]}"; do
    for image in "${images[@]}"; do
      remove_image_from_engine "$engine" "$image"
    done
  done
fi

log "Remaining relevant listening ports:"
if command -v ss >/dev/null 2>&1; then
  ss -lntp 2>/dev/null | grep -E ':(80|443|8080|8090|3306|4222|9000|9001|13306|14222|19000|19001)\b' || true
else
  warn "ss command not found; skipped port report"
fi

log "kageos uninstall complete"
