#!/usr/bin/env bash
# IMVEE Satellite Agent - Remote Installation Script
# Usage: curl -fsSL https://downloads.dev.imvee.de/satellite/latest/remote-install.sh | sudo bash -s -- --token=TOKEN [OPTIONS]
set -euo pipefail

# ============================================================================
# Configuration & Defaults
# ============================================================================
SCRIPT_VERSION="1.1.0"
# Default: latest — wird zur Laufzeit via $DOWNLOAD_BASE_URL/latest/VERSION auf die
# konkrete Versions-String aufgelöst (Versions-Drift-freie Installation, Issue #2)
AGENT_VERSION="${AGENT_VERSION:-latest}"
GITHUB_REPO="${GITHUB_REPO:-imvee/satellite}"  # nur für Documentation= in der systemd-Unit
DOWNLOAD_BASE_URL="${DOWNLOAD_BASE_URL:-https://downloads.dev.imvee.de/satellite}"
INSTALL_DIR="${INSTALL_DIR:-/usr/local/imvee-satellite}"
QUEUE_DIR="${QUEUE_DIR:-/var/lib/imvee-satellite}"
LOG_DIR="${LOG_DIR:-/var/log/imvee-satellite}"
PLIST_DEST="/Library/LaunchDaemons/com.imvee.satellite.plist"
ENV_FILE="$INSTALL_DIR/agent.env"

# CLI Arguments
ENROLLMENT_TOKEN="${IMVEE_ENROLLMENT_TOKEN:-}"  # Support ENV variable
SERVER_URL="${SERVER_URL:-https://socsuite.dev.imvee.de}"
SKIP_START=0
FORCE_REINSTALL=0
DEBUG=0

# ============================================================================
# Logging
# ============================================================================
log() { printf "[%s] %s\n" "$1" "$2"; }
info() { log "INFO" "$*"; }
warn() { log "WARN" "$*" >&2; }
err() { log "ERROR" "$*" >&2; }
abort() { err "$*"; exit 1; }
debug() { if [ $DEBUG -eq 1 ]; then log "DEBUG" "$*"; fi; }

# ============================================================================
# Parse Arguments
# ============================================================================
parse_args() {
  while [[ $# -gt 0 ]]; do
    case $1 in
      --token=*)
        ENROLLMENT_TOKEN="${1#*=}"
        shift
        ;;
      --token)
        ENROLLMENT_TOKEN="$2"
        shift 2
        ;;
      --server=*)
        SERVER_URL="${1#*=}"
        shift
        ;;
      --server)
        SERVER_URL="$2"
        shift 2
        ;;
      --version=*)
        AGENT_VERSION="${1#*=}"
        shift
        ;;
      --skip-start)
        SKIP_START=1
        shift
        ;;
      --force)
        FORCE_REINSTALL=1
        shift
        ;;
      --debug)
        DEBUG=1
        shift
        ;;
      -h|--help)
        show_help
        exit 0
        ;;
      *)
        warn "Unknown option: $1"
        shift
        ;;
    esac
  done
}

show_help() {
  cat <<EOF
IMVEE Satellite Agent - Remote Installation Script

Usage:
  curl -fsSL https://downloads.dev.imvee.de/satellite/latest/remote-install.sh | \\
    sudo bash -s -- --token=TOKEN [OPTIONS]

Required:
  --token=TOKEN         Enrollment token from SOCsuite UI

Optional:
  --server=URL          SOCsuite server URL (default: https://socsuite.dev.imvee.de)
  --skip-start          Don't start the agent service after installation
  --force               Force reinstallation even if already installed
  --debug               Enable debug output
  -h, --help            Show this help message

Examples:
  # Basic installation (neueste Version via 'latest')
  curl -fsSL https://downloads.dev.imvee.de/satellite/latest/remote-install.sh | \\
    sudo bash -s -- --token=abc123xyz

  # Mit festgepinnter Version
  curl -fsSL https://downloads.dev.imvee.de/satellite/latest/remote-install.sh | \\
    sudo bash -s -- --token=abc123xyz --version=v0.4.1

  # With custom server
  curl -fsSL https://downloads.dev.imvee.de/satellite/latest/remote-install.sh | \\
    sudo bash -s -- --token=abc123xyz --server=https://custom.socsuite.local
EOF
}

# ============================================================================
# System Detection
# ============================================================================
detect_os() {
  local os
  os=$(uname -s)
  case "$os" in
    Darwin)
      echo "darwin"
      ;;
    Linux)
      echo "linux"
      ;;
    *)
      abort "Unsupported OS: $os (only macOS and Linux supported)"
      ;;
  esac
}

detect_arch() {
  local arch
  arch=$(uname -m)
  case "$arch" in
    x86_64|amd64)
      echo "amd64"
      ;;
    arm64|aarch64)
      echo "arm64"
      ;;
    *)
      abort "Unsupported architecture: $arch"
      ;;
  esac
}

# ============================================================================
# Enrollment & Server Communication
# ============================================================================

# Sammelt System-Informationen für Agent-Registrierung
collect_system_info() {
  local hostname mac_addr ip_addr os_version os_name

  # Hostname: Nur kurzer Name ohne Domain-Suffix
  hostname="$(hostname -s 2>/dev/null || hostname | cut -d'.' -f1)"

  # OS Name und Version ermitteln
  if [ "$(uname -s)" = "Darwin" ]; then
    os_name="macOS"
    # Ermittle macOS Version - kann ProductVersion (z.B. 26.2) oder Marketing-Version (15.2) sein
    os_version="$(sw_vers -productVersion 2>/dev/null || echo "unknown")"

    # Wenn ProductVersion im Build-Format (z.B. 26.x), mappe zu Marketing-Version
    if [[ "$os_version" =~ ^[2-9][0-9]\.[0-9]$ ]]; then
      local build_version
      build_version="$(sw_vers -buildVersion 2>/dev/null)"
      case "$build_version" in
        25A*) os_version="15.0" ;;
        25B*) os_version="15.1" ;;
        25C*) os_version="15.2" ;;
        25D*) os_version="15.3" ;;
        24A*) os_version="14.0" ;;
        24B*) os_version="14.1" ;;
        24C*) os_version="14.2" ;;
        24D*) os_version="14.3" ;;
        24E*) os_version="14.4" ;;
        24F*) os_version="14.5" ;;
        24G*) os_version="14.6" ;;
        23A*) os_version="13.0" ;;
        23B*) os_version="13.1" ;;
        23C*) os_version="13.2" ;;
        23D*) os_version="13.3" ;;
        23E*) os_version="13.4" ;;
        23F*) os_version="13.5" ;;
        23G*) os_version="13.6" ;;
        *)
          # Fallback: Versuche ProductUserVisibleVersion
          local visible_version
          visible_version="$(defaults read /System/Library/CoreServices/SystemVersion.plist ProductUserVisibleVersion 2>/dev/null || echo "")"
          if [ -n "$visible_version" ] && [[ "$visible_version" =~ ^[0-9]+\.[0-9]+ ]]; then
            os_version="$visible_version"
          fi
          ;;
      esac
    fi
  else
    # Linux
    os_name="Linux"
    os_version="$(uname -r 2>/dev/null || echo "unknown")"
    # Versuche spezifischere Distribution zu ermitteln
    if [ -f /etc/os-release ]; then
      # shellcheck disable=SC1091
      . /etc/os-release
      os_name="${NAME:-Linux}"
      os_version="${VERSION_ID:-$os_version}"
    fi
  fi

  # MAC-Adresse ermitteln (erste aktive Netzwerkschnittstelle)
  if [ "$(uname -s)" = "Darwin" ]; then
    mac_addr="$(ifconfig en0 2>/dev/null | awk '/ether/{print $2}' || echo "")"
    [ -z "$mac_addr" ] && mac_addr="$(ifconfig en1 2>/dev/null | awk '/ether/{print $2}' || echo "")"
  else
    mac_addr="$(ip link show | awk '/ether/{print $2; exit}' 2>/dev/null || echo "")"
  fi
  [ -z "$mac_addr" ] && mac_addr="00:00:00:00:00:00"

  # IP-Adresse ermitteln
  if [ "$(uname -s)" = "Darwin" ]; then
    ip_addr="$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || echo "127.0.0.1")"
  else
    ip_addr="$(hostname -I 2>/dev/null | awk '{print $1}' || echo "127.0.0.1")"
  fi

  # JSON formatieren (Backend-kompatibel)
  printf '{"hostname":"%s","os_name":"%s","os_version":"%s","mac_address":"%s","ip_address":"%s","agent_version":"%s"}' \
    "$hostname" "$os_name" "$os_version" "$mac_addr" "$ip_addr" "$AGENT_VERSION"
}

# Registriert den Agent beim Backend mit Enrollment Token
register_agent_with_backend() {
  local api_url="$1"
  local enrollment_token="$2"
  local system_info agent_id api_key response http_code body

  info "Registriere Agent beim Backend ($api_url)..."
  info "Verwende Enrollment Token: ${enrollment_token:0:15}..."

  system_info="$(collect_system_info)"
  debug "System Info: $system_info"

  # POST /ingest/enroll — öffentlicher Endpoint, kein API-Key erforderlich.
  # Enrollment-Token wird als JSON-Feld 'token' im Body mitgesendet (kein Authorization-Header).
  # Entspricht dem Enterprise Zero-Touch Enrollment Pattern (siehe backend agent_enrollment.go).
  local payload
  payload="$(echo "$system_info" | jq --arg token "$enrollment_token" '. + {token: $token}')"

  response="$(curl -k -s -w "\n%{http_code}" -X POST \
    -H "Content-Type: application/json" \
    -d "$payload" \
    "${api_url}/ingest/enroll" 2>&1)" || {
    err "Agent-Registrierung fehlgeschlagen (curl error)"
    return 1
  }

  # Split response and HTTP code
  http_code="$(echo "$response" | tail -n 1)"
  body="$(echo "$response" | sed '$d')"

  debug "HTTP Code: $http_code"
  debug "Response Body: $body"

  if [ "$http_code" != "200" ] && [ "$http_code" != "201" ]; then
    err "Agent-Registrierung fehlgeschlagen (HTTP $http_code): $body"
    return 1
  fi

  # Parse JSON response (einfacher grep/sed Ansatz für bash)
  agent_id="$(echo "$body" | grep -o '"id":"[^"]*"' | cut -d'"' -f4)"
  api_key="$(echo "$body" | grep -o '"api_key":"[^"]*"' | cut -d'"' -f4)"

  if [ -z "$agent_id" ] || [ -z "$api_key" ]; then
    err "Konnte ID oder API-Key nicht aus Response parsen: $body"
    return 1
  fi

  info "✓ Agent erfolgreich registriert (ID: ${agent_id:0:8}...)"

  # Speichere Agent-ID
  local agent_id_file="$QUEUE_DIR/agent.id"
  echo -n "$agent_id" > "$agent_id_file"
  chmod 0644 "$agent_id_file"

  # Export für weitere Verwendung
  REGISTERED_AGENT_ID="$agent_id"
  REGISTERED_API_KEY="$api_key"

  return 0
}

enroll_agent() {
  local token="$1"
  local server="${2:-}"

  info "Enrolling agent with SOCsuite..."

  # Trim Whitespace von Token
  token="$(echo "$token" | tr -d ' \n\r\t')"

  # If no server URL provided, try to auto-detect
  if [ -z "$server" ]; then
    for url in "https://socsuite.dev.imvee.de" "https://api.socsuite.dev.imvee.de" "https://api.siem.socsuite.dev.imvee.de"; do
      if curl -fsSLk --max-time 5 "$url/api/v1/health" >/dev/null 2>&1; then
        server="$url"
        debug "Auto-detected server: $server"
        break
      fi
    done
  fi

  if [ -z "$server" ]; then
    abort "Could not auto-detect server URL. Please provide --server=URL"
  fi

  # Determine API URL (ensure /api/v1 path)
  local api_url="$server"
  if [[ ! "$api_url" =~ /api/v1$ ]]; then
    api_url="${server%/}/api/v1"
  fi

  # Versuche Agent-Registrierung mit neuem Backend-Endpoint
  if register_agent_with_backend "$api_url" "$token"; then
    info "✓ Agent erfolgreich registriert via Enrollment Token"
    local agent_token="$REGISTERED_API_KEY"
    local agent_id="$REGISTERED_AGENT_ID"
  else
    warn "⚠️  Registrierung mit Enrollment Token fehlgeschlagen"
    warn "    Prüfe Token-Gültigkeit und Backend-Erreichbarkeit: $api_url"
    abort "Agent kann ohne API-Key nicht starten"
  fi

  # Get system info for env file
  local hostname
  hostname=$(hostname -s 2>/dev/null || hostname | cut -d'.' -f1)
  local os_name os_version
  if [ "$(uname -s)" = "Darwin" ]; then
    os_name="macOS"
    # Ermittle macOS Version - kann ProductVersion oder Marketing-Version sein
    os_version="$(sw_vers -productVersion 2>/dev/null || echo "unknown")"

    # Wenn ProductVersion im Build-Format, mappe zu Marketing-Version
    if [[ "$os_version" =~ ^[2-9][0-9]\.[0-9]$ ]]; then
      local build_version
      build_version="$(sw_vers -buildVersion 2>/dev/null)"
      case "$build_version" in
        25A*) os_version="15.0" ;;
        25B*) os_version="15.1" ;;
        25C*) os_version="15.2" ;;
        25D*) os_version="15.3" ;;
        24A*) os_version="14.0" ;;
        24B*) os_version="14.1" ;;
        24C*) os_version="14.2" ;;
        24D*) os_version="14.3" ;;
        24E*) os_version="14.4" ;;
        24F*) os_version="14.5" ;;
        24G*) os_version="14.6" ;;
        23A*) os_version="13.0" ;;
        23B*) os_version="13.1" ;;
        23C*) os_version="13.2" ;;
        23D*) os_version="13.3" ;;
        23E*) os_version="13.4" ;;
        23F*) os_version="13.5" ;;
        23G*) os_version="13.6" ;;
      esac
    fi
  else
    os_name="Linux"
    os_version="$(uname -r 2>/dev/null || echo "unknown")"
    if [ -f /etc/os-release ]; then
      # shellcheck disable=SC1091
      . /etc/os-release
      os_name="${NAME:-Linux}"
      os_version="${VERSION_ID:-$os_version}"
    fi
  fi

  # Write comprehensive config to env file
  cat > "$ENV_FILE" <<EOF
# IMVEE Satellite Agent Configuration
# Generated by remote-install.sh on $(date)

# ============================================================================
# AUTHENTICATION (Enterprise Best Practice)
# ============================================================================
# Primary API Key - Use this for all agent authentication
IMVEE_API_KEY=$agent_token

# Backend API URL
API_URL=$api_url

# Agent Identity
SOCSUITE_AGENT_ID=$agent_id

# ============================================================================
# DEPRECATED VARIABLES (Backwards Compatibility - Remove in v0.2.0)
# ============================================================================
# WARNING: These variables are deprecated. Please migrate to IMVEE_API_KEY
AGENT_TOKEN=$agent_token
SOCSUITE_API_KEY=$agent_token

# Server Configuration (legacy)
SOCSUITE_SERVER=$server
ENROLLMENT_TOKEN=$token

# ============================================================================
# OPENSEARCH CONNECTION
# ============================================================================
OPENSEARCH_URL=${server%/}
OPENSEARCH_USER=admin
OPENSEARCH_PASSWORD=admin

# Legacy OpenSearch variables (compatibility)
OS_URL=${server%/}
OS_BASE_PATH=
OS_USER=admin
OS_PASS=admin

# Index (Tagesindex-Muster) – dynamisch im Agenten aufgelöst
IMVEE_INDEX=imvee-satellite-{YYYY}.{MM}.{DD}

# ============================================================================
# AGENT CONFIGURATION
# ============================================================================
# Multi-Queue Support
IMVEE_QUEUE=$QUEUE_DIR/queue.jsonl
IMVEE_LOG_DIR=$LOG_DIR
IMVEE_DEBUG=${DEBUG}
IMVEE_LOG_STDOUT=0

# TLS Optionen
IMVEE_TLS_SKIP_VERIFY=1
IMVEE_CA_FILE=

# Proxy-Verhalten (default: Proxy aus)
IMVEE_ALLOW_PROXY=0

# Hook / Logging Optionen
IMVEE_LOG_MODE=after
IMVEE_CAPTURE_EXIT=1
IMVEE_IGNORE_LEADING_SPACE=1
IMVEE_IGNORE_REGEX="(pass|secret|ssh-add)"
IMVEE_REDACT_TOKENS="--password=,--token=,--api-key="
IMVEE_TENANT_ID=
IMVEE_ENABLE_DOCKER_LOGS=1
IMVEE_DOCKER_MODE=cli

# Docker Collector Controls
IMVEE_DOCKER_FOLLOW_LOGS=1
IMVEE_DOCKER_FOLLOW_MODE=burst
IMVEE_DOCKER_MAX_FOLLOWERS=5
OS_VERSION=$os_version
IMVEE_DOCKER_LOGS_ONLY_LABELED=0
IMVEE_DOCKER_LOGS_LABEL=
IMVEE_DOCKER_IMAGE_BUILD_EVENTS=1

# Metadata
AGENT_VERSION=$AGENT_VERSION
INSTALLED_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)
PLATFORM=$os_name
ARCH=$(detect_arch)
HOSTNAME=$hostname
EOF

  chmod 0640 "$ENV_FILE"
  info "✓ Configuration written: $ENV_FILE"
  info "  Agent ID: ${agent_id:0:8}..."
  info "  API Token: ${agent_token:0:15}... (${#agent_token} chars)"
}

# ============================================================================
# Version Resolution
# ============================================================================

# Löst AGENT_VERSION='latest' auf den konkreten Versions-String des
# Downloads-Servers auf (latest/VERSION, Fallback: Root-VERSION).
# Bleibt 'latest' stehen, wenn keine Auflösung möglich ist — die URLs
# funktionieren dann weiterhin über den 'latest'-Symlink.
resolve_version() {
  local resolved
  if [ "$AGENT_VERSION" != "latest" ]; then
    return 0
  fi
  resolved="$(curl -fsSLk --max-time 10 "${DOWNLOAD_BASE_URL}/latest/VERSION" 2>/dev/null || true)"
  if [ -z "$resolved" ]; then
    resolved="$(curl -fsSLk --max-time 10 "${DOWNLOAD_BASE_URL}/VERSION" 2>/dev/null || true)"
  fi
  if [ -n "$resolved" ]; then
    AGENT_VERSION="$resolved"
    info "Version 'latest' aufgelöst: $AGENT_VERSION"
  else
    warn "Konnte 'latest' nicht auf konkrete Version auflösen — verwende Pfad 'latest' direkt"
  fi
}

# ============================================================================
# Download & Verify Binary
# ============================================================================
download_binary() {
  local os="$1"
  local arch="$2"

  info "Downloading agent version $AGENT_VERSION for $os/$arch..."

  # Determine binary name based on OS
  local binary_name="imvee-satellite-agent-${os}-${arch}"
  local download_url="$DOWNLOAD_BASE_URL/$AGENT_VERSION/$binary_name"
  local checksum_url="$DOWNLOAD_BASE_URL/$AGENT_VERSION/checksums.txt"

  local tmp_dir
  tmp_dir=$(mktemp -d)
  # shellcheck disable=SC2064
  trap "rm -rf '$tmp_dir'" EXIT

  local binary_path="$tmp_dir/$binary_name"
  local checksum_path="$tmp_dir/checksums.txt"

  # Download binary
  debug "Downloading from: $download_url"
  if ! curl -fsSLk -o "$binary_path" "$download_url"; then
    abort "Failed to download binary from $download_url"
  fi

  # Download and verify checksum
  info "Verifying checksum..."
  if curl -fsSLk -o "$checksum_path" "$checksum_url" 2>/dev/null; then
    local expected_sum
    expected_sum=$(grep "$binary_name" "$checksum_path" | awk '{print $1}')
    if [ -n "$expected_sum" ]; then
      local actual_sum
      if command -v shasum >/dev/null 2>&1; then
        actual_sum=$(shasum -a 256 "$binary_path" | awk '{print $1}')
      elif command -v sha256sum >/dev/null 2>&1; then
        actual_sum=$(sha256sum "$binary_path" | awk '{print $1}')
      else
        warn "No checksum tool available, skipping verification"
      fi

      if [ -n "$actual_sum" ]; then
        if [ "$expected_sum" = "$actual_sum" ]; then
          info "Checksum verified ✓"
        else
          abort "Checksum mismatch! Expected: $expected_sum, Got: $actual_sum"
        fi
      fi
    else
      warn "Checksum not found in checksums.txt, skipping verification"
    fi
  else
    warn "Could not download checksums.txt, skipping verification"
  fi

  # Install binary
  mkdir -p "$INSTALL_DIR"
  cp "$binary_path" "$INSTALL_DIR/agent"
  chmod 0755 "$INSTALL_DIR/agent"

  # Download and install uninstall script
  debug "Downloading uninstall script..."
  local uninstall_url="$DOWNLOAD_BASE_URL/$AGENT_VERSION/uninstall.sh"
  if curl -fsSLk -o "$tmp_dir/uninstall.sh" "$uninstall_url"; then
    cp "$tmp_dir/uninstall.sh" "$INSTALL_DIR/uninstall.sh"
    chmod 0755 "$INSTALL_DIR/uninstall.sh"
    debug "Uninstall script installed"
  else
    warn "Could not download uninstall script (non-critical)"
  fi

  info "Binary installed to $INSTALL_DIR/agent"
}

# ============================================================================
# Service Installation (macOS)
# ============================================================================
install_launchd_service() {
  local current_user="${SUDO_USER:-$USER}"
  local user_home
  user_home="$(eval echo ~"$current_user")"

  info "Installing LaunchD service..."

  # Create agent wrapper script
  local wrapper_script="$INSTALL_DIR/agent-wrapper.sh"
  cat > "$wrapper_script" <<'WRAPPER_EOF'
#!/bin/bash
set -euo pipefail

# Installationspfad (fix eingebettet)
INSTALL_DIR_PATH="__INSTALL_DIR_PATH__"
ENV_FILE="$INSTALL_DIR_PATH/agent.env"

# Ensure HOME is set (launchd may not set it). Required for docker CLI context.
export HOME="__AGENT_HOME__"

if [ -f "$ENV_FILE" ]; then
  # Export alle in agent.env gesetzten Variablen
  set -a
  # shellcheck disable=SC1090
  source "$ENV_FILE"
  set +a
fi

# Proxy-Umgebung standardmäßig neutralisieren (opt-in via IMVEE_ALLOW_PROXY=1)
if [ "${IMVEE_ALLOW_PROXY:-0}" != "1" ]; then
  unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY all_proxy ALL_PROXY no_proxy NO_PROXY
fi

# OS_URL-Host zu NO_PROXY hinzufügen
if [ -n "${OS_URL:-}" ]; then
  url_no_scheme="${OS_URL#*://}"
  os_host="${url_no_scheme%%[:/]*}"
  if [ -n "${os_host}" ]; then
    base_domain="${os_host#*.}"
    cur_no_proxy="${NO_PROXY:-${no_proxy:-}}"
    add_list="$os_host"
    if [ -n "$base_domain" ] && [ "$base_domain" != "$os_host" ]; then
      add_list="$add_list,.$base_domain"
    fi
    if [ -n "${cur_no_proxy}" ]; then
      export NO_PROXY="$cur_no_proxy,$add_list"
    else
      export NO_PROXY="$add_list"
    fi
    export no_proxy="$NO_PROXY"
  fi
fi

exec "$INSTALL_DIR_PATH/agent" "$@"
WRAPPER_EOF

  chmod 0755 "$wrapper_script"

  # Replace placeholders
  sed -i '' "s|__INSTALL_DIR_PATH__|$INSTALL_DIR|g" "$wrapper_script" 2>/dev/null || \
    sed -i "s|__INSTALL_DIR_PATH__|$INSTALL_DIR|g" "$wrapper_script"
  sed -i '' "s|__AGENT_HOME__|$user_home|g" "$wrapper_script" 2>/dev/null || \
    sed -i "s|__AGENT_HOME__|$user_home|g" "$wrapper_script"

  # Remove Quarantine attributes (Gatekeeper)
  if command -v xattr >/dev/null 2>&1; then
    xattr -cr "$INSTALL_DIR" 2>/dev/null || true
    xattr -cr "$INSTALL_DIR/agent" 2>/dev/null || true
    xattr -cr "$wrapper_script" 2>/dev/null || true
  fi

  # Create plist
  cat > "$PLIST_DEST" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.imvee.satellite</string>

    <key>ProgramArguments</key>
    <array>
        <string>$wrapper_script</string>
    </array>

    <key>RunAtLoad</key>
    <true/>

    <key>KeepAlive</key>
    <dict>
        <key>SuccessfulExit</key>
        <false/>
        <key>Crashed</key>
        <true/>
    </dict>

    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin</string>
        <key>HOME</key>
        <string>$user_home</string>
    </dict>

    <key>StandardOutPath</key>
    <string>$LOG_DIR/agent.out.log</string>

    <key>StandardErrorPath</key>
    <string>$LOG_DIR/agent.err.log</string>

    <key>WorkingDirectory</key>
    <string>$INSTALL_DIR</string>

    <key>ProcessType</key>
    <string>Background</string>

    <key>Nice</key>
    <integer>0</integer>

    <key>ThrottleInterval</key>
    <integer>10</integer>
</dict>
</plist>
EOF

  # Remove Quarantine from plist
  if command -v xattr >/dev/null 2>&1; then
    xattr -cr "$PLIST_DEST" 2>/dev/null || true
  fi

  # Validate plist syntax
  if command -v plutil >/dev/null 2>&1; then
    /usr/bin/plutil -lint "$PLIST_DEST" || abort "Invalid plist: $PLIST_DEST"
  fi

  chown root:wheel "$PLIST_DEST"
  chmod 0644 "$PLIST_DEST"

  # Preflight checks
  [ -x "$INSTALL_DIR/agent" ] || abort "Agent not executable: $INSTALL_DIR/agent"
  [ -x "$wrapper_script" ] || abort "Wrapper not executable: $wrapper_script"
  [ -d "$LOG_DIR" ] || abort "Log directory missing: $LOG_DIR"
  [ -f "$LOG_DIR/agent.out.log" ] || abort "Log file missing: $LOG_DIR/agent.out.log"
  [ -f "$LOG_DIR/agent.err.log" ] || abort "Log file missing: $LOG_DIR/agent.err.log"

  info "✓ LaunchD service installed with wrapper"
}

# ============================================================================
# Service Installation (Linux systemd)
# ============================================================================
install_systemd_service() {
  local service_file="/etc/systemd/system/imvee-satellite.service"

  info "Installing systemd service..."

  cat > "$service_file" <<EOF
[Unit]
Description=IMVEE Satellite Agent
Documentation=https://github.com/$GITHUB_REPO
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=$INSTALL_DIR/agent
Restart=on-failure
RestartSec=10s
StandardOutput=append:$LOG_DIR/agent.out.log
StandardError=append:$LOG_DIR/agent.err.log
WorkingDirectory=$INSTALL_DIR
EnvironmentFile=$ENV_FILE

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=$QUEUE_DIR $LOG_DIR

[Install]
WantedBy=multi-user.target
EOF

  chmod 0644 "$service_file"
  systemctl daemon-reload

  info "systemd service installed"
}

# ============================================================================
# ZSH Hook Installation
# ============================================================================
install_zsh_hook() {
  local hook_file="$INSTALL_DIR/zsh_hook.sh"
  local current_user="${SUDO_USER:-$USER}"
  local user_home

  # Get user home directory
  user_home="$(eval echo ~"$current_user")"

  info "Installing ZSH command hook..."

  # Create ZSH hook script with enhanced features
  cat > "$hook_file" <<'EOF'
#!/usr/bin/env zsh
# IMVEE Satellite - ZSH Command Hook

# User-Queue für interaktive Sessions (User-owned, root-lesbar)
IMVEE_QUEUE="${IMVEE_QUEUE:-$HOME/.local/share/imvee-satellite/queue.jsonl}"
IMVEE_DOCKER_QUEUE="${IMVEE_DOCKER_QUEUE:-$HOME/.local/share/imvee-satellite/docker.queue.jsonl}"
IMVEE_LOG_MODE="${IMVEE_LOG_MODE:-after}"
IMVEE_CAPTURE_EXIT="${IMVEE_CAPTURE_EXIT:-1}"
IMVEE_IGNORE_LEADING_SPACE="${IMVEE_IGNORE_LEADING_SPACE:-1}"
IMVEE_IGNORE_REGEX="${IMVEE_IGNORE_REGEX:-(pass|secret|ssh-add)}"

# Ensure queue directory exists
[ -d "$(dirname "$IMVEE_QUEUE")" ] || mkdir -p "$(dirname "$IMVEE_QUEUE")"

log_command() {
  local cmd="$1"
  local exit_code="${2:-0}"
  local timestamp log_mode

  # Skip empty commands
  [[ -z "$cmd" ]] && return

  # Skip commands starting with space if configured
  if [[ "$IMVEE_IGNORE_LEADING_SPACE" == "1" && "$cmd" =~ ^[[:space:]] ]]; then
    return
  fi

  # Skip commands matching ignore regex
  if [[ -n "$IMVEE_IGNORE_REGEX" && "$cmd" =~ $IMVEE_IGNORE_REGEX ]]; then
    return
  fi

  # Determine log mode for event
  if [[ "$IMVEE_LOG_MODE" == "before" ]]; then
    log_mode="preexec"
  else
    log_mode="precmd"
  fi

  # Get timestamp
  timestamp="$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u +%FT%TZ)"

  # Redact sensitive tokens (simplified for bash compatibility)
  local redacted_cmd="$cmd"
  if [[ -n "$IMVEE_REDACT_TOKENS" ]]; then
    # Simple redaction for common patterns
    redacted_cmd="${redacted_cmd//--password=[^[:space:]]*/--password=***}"
    redacted_cmd="${redacted_cmd//--token=[^[:space:]]*/--token=***}"
    redacted_cmd="${redacted_cmd//--api-key=[^[:space:]]*/--api-key=***}"
  fi

  # Escape JSON special characters
  redacted_cmd="${redacted_cmd//\\/\\\\}"
  redacted_cmd="${redacted_cmd//\"/\\\"}"
  redacted_cmd="${redacted_cmd//$'\n'/\\n}"
  redacted_cmd="${redacted_cmd//$'\r'/\\r}"
  redacted_cmd="${redacted_cmd//$'\t'/\\t}"

  # Create JSON event
  local json_event="{\"timestamp\":\"$timestamp\",\"type\":\"shell_command\",\"user\":\"$USER\",\"hostname\":\"$HOSTNAME\",\"shell\":\"zsh\",\"command\":\"$redacted_cmd\",\"exit_code\":$exit_code,\"pwd\":\"$PWD\",\"session_id\":\"$$\",\"log_mode\":\"$log_mode\"}"

  # Append to queue (async, non-blocking)
  (echo "$json_event" >> "$IMVEE_QUEUE" 2>/dev/null &)
}

# Setup hooks based on log mode
if [[ "$IMVEE_LOG_MODE" == "before" ]]; then
  preexec() { log_command "$1" 0; }
elif [[ "$IMVEE_LOG_MODE" == "after" ]]; then
  precmd() {
    local last_exit=$?
    if [[ "$IMVEE_CAPTURE_EXIT" == "1" ]]; then
      log_command "${history[$HISTCMD]}" "$last_exit"
    else
      log_command "${history[$HISTCMD]}" 0
    fi
  }
fi
EOF

  chmod 0755 "$hook_file"

  # Setup user queue directory with correct permissions
  local user_queue_dir="$user_home/.local/share/imvee-satellite"
  if [ ! -d "$user_queue_dir" ]; then
    info "Creating user queue directory: $user_queue_dir"
    if [ "$current_user" != "root" ]; then
      sudo -u "$current_user" mkdir -p "$user_queue_dir"
    else
      mkdir -p "$user_queue_dir"
    fi
  fi

  # Set directory permissions (user-owned, root-readable)
  chmod 0755 "$user_home/.local" 2>/dev/null || true
  chmod 0755 "$user_home/.local/share" 2>/dev/null || true
  chmod 0755 "$user_queue_dir"

  # Create queue files if they don't exist (as user)
  if [ "$current_user" != "root" ]; then
    sudo -u "$current_user" touch "$user_queue_dir/queue.jsonl" "$user_queue_dir/docker.queue.jsonl" 2>/dev/null || true
  else
    touch "$user_queue_dir/queue.jsonl" "$user_queue_dir/docker.queue.jsonl" 2>/dev/null || true
  fi

  # Set file permissions
  chmod 0644 "$user_queue_dir"/*.jsonl 2>/dev/null || true

  # Configure .zshenv for user queue paths
  local zshenv_file="$user_home/.zshenv"
  if [ ! -f "$zshenv_file" ] || ! grep -q "IMVEE_QUEUE" "$zshenv_file" 2>/dev/null; then
    info "Configuring user queue path in $zshenv_file"
    if [ "$current_user" != "root" ]; then
      sudo -u "$current_user" bash -c "cat >> '$zshenv_file'" <<'ZSHENV_EOF'

# IMVEE Satellite - User-Queue-Pfade (Shell-Hook)
export IMVEE_QUEUE="$HOME/.local/share/imvee-satellite/queue.jsonl"
export IMVEE_DOCKER_QUEUE="$HOME/.local/share/imvee-satellite/docker.queue.jsonl"
ZSHENV_EOF
      chmod 0644 "$zshenv_file"
    else
      cat >> "$zshenv_file" <<'ZSHENV_EOF'

# IMVEE Satellite - User-Queue-Pfade (Shell-Hook)
export IMVEE_QUEUE="$HOME/.local/share/imvee-satellite/queue.jsonl"
export IMVEE_DOCKER_QUEUE="$HOME/.local/share/imvee-satellite/docker.queue.jsonl"
ZSHENV_EOF
      chmod 0644 "$zshenv_file"
    fi
    info "✓ User queue paths configured in $zshenv_file"
  fi

  # Add to /etc/zshrc if not already present
  local zshrc="/etc/zshrc"
  local source_line="source $hook_file"
  local backup_zshrc="/etc/zshrc.imvee.bak"

  if [ -f "$zshrc" ]; then
    # Clean up any old/malformed entries
    if grep -Fq 'imvee-satellit' "$zshrc" 2>/dev/null || grep -Fq "$hook_file" "$zshrc" 2>/dev/null; then
      info "Cleaning up old hook entries in $zshrc"
      local tmp_clean
      tmp_clean="$(mktemp)"
      sed -E '/^[[:space:]]*source[[:space:]]+\/usr\/local\/imvee\-satellit/d' "$zshrc" > "$tmp_clean"
      cat "$tmp_clean" > "$zshrc"
      rm -f "$tmp_clean"
    fi

    # Add correct hook line if missing
    if ! grep -Fqx "$source_line" "$zshrc"; then
      cp "$zshrc" "$backup_zshrc" 2>/dev/null || true
      {
        echo ""
        echo "# IMVEE Satellite Agent Hook"
        echo "$source_line"
      } >> "$zshrc"
      info "✓ ZSH hook added to $zshrc"
    else
      info "✓ ZSH hook already configured"
    fi
  else
    warn "$zshrc not found – hook not registered"
  fi

  info "✓ ZSH hook installed (User-Queue: $user_queue_dir)"
}

# ============================================================================
# Main Installation Flow
# ============================================================================
main() {
  info "IMVEE Satellite Agent Installer v$SCRIPT_VERSION"
  info "Version: $AGENT_VERSION"
  echo ""

  parse_args "$@"

  # Validate requirements
  if [ -z "$ENROLLMENT_TOKEN" ]; then
    abort "Enrollment token required. Use --token=TOKEN or see --help"
  fi

  # 'latest' → konkrete Version auflösen (für checksums.txt + agent.env)
  resolve_version

  if [ "$(id -u)" -ne 0 ]; then
    abort "This script must be run as root (use sudo)"
  fi

  # Detect system
  local os
  os=$(detect_os)
  local arch
  arch=$(detect_arch)
  info "Detected system: $os/$arch"

  # Check if already installed
  if [ -f "$INSTALL_DIR/agent" ] && [ $FORCE_REINSTALL -eq 0 ]; then
    warn "Agent already installed at $INSTALL_DIR/agent"
    warn "Use --force to reinstall"
    exit 0
  fi

  # Get current user for queue setup
  local current_user="${SUDO_USER:-$USER}"
  local user_home
  user_home="$(eval echo ~"$current_user")"

  # Create directories
  mkdir -p "$INSTALL_DIR" "$QUEUE_DIR" "$LOG_DIR"

  # Create system queue files
  local queue_file="$QUEUE_DIR/queue.jsonl"
  local docker_queue_file="$QUEUE_DIR/docker.queue.jsonl"
  [ -f "$queue_file" ] || (umask 002; : > "$queue_file")
  [ -f "$docker_queue_file" ] || (umask 002; : > "$docker_queue_file")

  # Create log files
  touch "$LOG_DIR/agent.out.log" "$LOG_DIR/agent.err.log" || abort "Cannot create log files"

  # Set permissions for system directories
  chmod 0755 "$INSTALL_DIR" "$LOG_DIR" "$QUEUE_DIR"
  chmod 0644 "$queue_file" "$docker_queue_file"
  chmod 0644 "$LOG_DIR"/*.log

  # Log directory must be owned by root (LaunchD service runs as root)
  chown -R root:wheel "$LOG_DIR" 2>/dev/null || true

  # Create user queue directory (for interactive shell sessions)
  local user_queue_dir="$user_home/.local/share/imvee-satellite"
  if [ ! -d "$user_queue_dir" ]; then
    info "Creating user queue directory: $user_queue_dir"
    if [ "$current_user" != "root" ]; then
      sudo -u "$current_user" mkdir -p "$user_queue_dir"
    else
      mkdir -p "$user_queue_dir"
    fi
  fi

  # Set directory permissions (user-owned, root-readable)
  chmod 0755 "$user_home/.local" 2>/dev/null || true
  chmod 0755 "$user_home/.local/share" 2>/dev/null || true
  chmod 0755 "$user_queue_dir"

  # Create user queue files if they don't exist
  if [ -f "$user_queue_dir/queue.jsonl" ] && [ "$(stat -f '%Su' "$user_queue_dir/queue.jsonl" 2>/dev/null || echo "unknown")" = "root" ]; then
    info "Cleaning up root-owned queue files..."
    rm -f "$user_queue_dir/queue.jsonl" "$user_queue_dir/docker.queue.jsonl"
  fi

  # Create as user
  if [ "$current_user" != "root" ]; then
    sudo -u "$current_user" touch "$user_queue_dir/queue.jsonl" "$user_queue_dir/docker.queue.jsonl" 2>/dev/null || true
  else
    touch "$user_queue_dir/queue.jsonl" "$user_queue_dir/docker.queue.jsonl" 2>/dev/null || true
  fi

  # Set file permissions
  chmod 0644 "$user_queue_dir"/*.jsonl 2>/dev/null || true

  info "✓ Multi-queue system configured:"
  info "  System Queue: $queue_file"
  info "  User Queue: $user_queue_dir/queue.jsonl"

  # Update env file to include user queue in IMVEE_QUEUE (comma-separated)
  if [ -f "$ENV_FILE" ]; then
    # Replace IMVEE_QUEUE line to include both queues
    if [ "$(uname -s)" = "Darwin" ]; then
      sed -i '' "s|^IMVEE_QUEUE=.*|IMVEE_QUEUE=$user_queue_dir/queue.jsonl,$queue_file|" "$ENV_FILE"
    else
      sed -i "s|^IMVEE_QUEUE=.*|IMVEE_QUEUE=$user_queue_dir/queue.jsonl,$queue_file|" "$ENV_FILE"
    fi
  else
    echo "IMVEE_QUEUE=$user_queue_dir/queue.jsonl,$queue_file" >> "$ENV_FILE"
  fi

  # Download and install binary
  download_binary "$os" "$arch"

  # Enroll with SOCsuite
  enroll_agent "$ENROLLMENT_TOKEN" "$SERVER_URL"

  # Install service based on OS
  if [ "$os" = "darwin" ]; then
    install_launchd_service
    install_zsh_hook
  elif [ "$os" = "linux" ]; then
    install_systemd_service
  fi

  # Start service
  if [ $SKIP_START -eq 0 ]; then
    info "Starting agent service..."
    if [ "$os" = "darwin" ]; then
      # Unload any existing service first
      launchctl bootout system "$PLIST_DEST" 2>/dev/null || true
      launchctl unload -w "$PLIST_DEST" 2>/dev/null || true
      sleep 1

      # Try bootstrap first (modern macOS), fallback to load (older macOS)
      if launchctl bootstrap system "$PLIST_DEST" 2>/dev/null; then
        info "Service started ✓ (bootstrap)"
        sleep 2
      elif launchctl load -w "$PLIST_DEST" 2>/dev/null; then
        info "Service started ✓ (load)"
        sleep 2
      else
        warn "Failed to start service with launchctl"
        info "Trying alternative method..."
        # Alternative: Enable and kickstart
        launchctl enable system/com.imvee.satellite 2>/dev/null || true
        if launchctl kickstart -k system/com.imvee.satellite 2>/dev/null; then
          info "Service started ✓ (kickstart)"
        else
          warn "Failed to start service. Check logs: $LOG_DIR/agent.err.log"
          warn "Manual start: sudo launchctl load -w $PLIST_DEST"
        fi
      fi

      # Verify service is running
      sleep 1
      if launchctl list | grep -q com.imvee.satellite; then
        info "✓ Service is running and registered"
      else
        warn "⚠ Service may not be running. Check: sudo launchctl list | grep imvee"
      fi

    elif [ "$os" = "linux" ]; then
      systemctl enable imvee-satellite
      if systemctl start imvee-satellite; then
        info "Service started ✓"
        sleep 2
        if systemctl is-active --quiet imvee-satellite; then
          info "✓ Service is running"
        fi
      else
        warn "Failed to start service. Check: systemctl status imvee-satellite"
      fi
    fi
  else
    info "Service start skipped (--skip-start)"
  fi

  echo ""
  info "✓ Installation complete!"
  info "Configuration: $ENV_FILE"
  info "Queue: $QUEUE_DIR/queue.jsonl"
  info "Logs: $LOG_DIR/"

  if [ "$os" = "darwin" ]; then
    info "Service: launchctl list com.imvee.satellite"
    info "Logs: tail -f $LOG_DIR/agent.out.log"
  elif [ "$os" = "linux" ]; then
    info "Service: systemctl status imvee-satellite"
    info "Logs: journalctl -u imvee-satellite -f"
  fi
}

# Run main
main "$@"
