#!/usr/bin/env bash
#
# install.sh — AASD (API Attack Surface Discovery) installer
#
# Supports: Debian 12+ | RHEL 9+ (AlmaLinux, Rocky Linux)
# Usage:    sudo bash install.sh [--release-url URL]
#
# Environment variables (all optional):
#   AASD_RELEASE_URL    — URL to download the dist/ tarball
#   AASD_AI_API_KEY     — DeepSeek API key (prompted if empty)
#   AASD_BASE_URL       — Public base URL (prompted if empty)
#   AASD_ADMIN_PASSWORD — Admin dashboard password (prompted if empty)
#

set -euo pipefail

# ──────────────────────────────────────────────
# Color helpers
# ──────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
info()  { echo -e "${CYAN}[INFO]${NC}  $*"; }
pass()  { echo -e "${GREEN}[OK]${NC}    $*"; }
warn()  { echo -e "${YELLOW}[WARN]${NC}  $*"; }
fail()  { echo -e "${RED}[FAIL]${NC}  $*"; exit 1; }

# ──────────────────────────────────────────────
# Root check
# ──────────────────────────────────────────────
if [[ $EUID -ne 0 ]]; then
  fail "This script must be run as root (sudo)."
fi

# ──────────────────────────────────────────────
# OS detection
# ──────────────────────────────────────────────
info "Detecting operating system..."

if [[ -f /etc/os-release ]]; then
  . /etc/os-release
  OS_ID="${ID,,}"
  OS_VERSION_ID="${VERSION_ID:-0}"
elif [[ -f /etc/redhat-release ]]; then
  OS_ID="rhel"
  OS_VERSION_ID="$(rpm -q --qf '%{VERSION}' $(rpm -q --whatprovides redhat-release) 2>/dev/null || echo '0')"
else
  fail "Unsupported OS. Only Debian 12+ and RHEL 9+ are supported."
fi

case "$OS_ID" in
  debian|ubuntu)
    PKG_MGR="apt-get"
    PKG_UPDATE="$PKG_MGR update -qq"
    PKG_INSTALL="$PKG_MGR install -y -qq"
    info "Detected Debian/Ubuntu — using apt"
    ;;
  rhel|centos|rocky|almalinux|fedora)
    PKG_MGR="dnf"
    PKG_UPDATE="$PKG_MGR check-update || true"
    PKG_INSTALL="$PKG_MGR install -y -q"
    info "Detected RHEL family — using dnf"
    ;;
  *)
    fail "Unsupported OS: $OS_ID. Only Debian 12+ and RHEL 9+ are supported."
    ;;
esac

# ──────────────────────────────────────────────
# Prerequisites
# ──────────────────────────────────────────────
info "Installing prerequisites..."
eval "$PKG_UPDATE"
eval "$PKG_INSTALL curl tar gzip"

# ──────────────────────────────────────────────
# Create 'app' user
# ──────────────────────────────────────────────
APP_USER="app"
APP_HOME="/opt/aasd"

if id "$APP_USER" &>/dev/null; then
  pass "User '$APP_USER' already exists"
else
  info "Creating user '$APP_USER' (system user, no login)..."
  case "$OS_ID" in
    debian|ubuntu)
      useradd --system --no-create-home --shell /usr/sbin/nologin "$APP_USER"
      ;;
    rhel|centos|rocky|almalinux|fedora)
      useradd --system --no-create-home --shell /sbin/nologin "$APP_USER"
      ;;
  esac
  pass "User '$APP_USER' created"
fi

# ──────────────────────────────────────────────
# Determine source of binaries + assets
# ──────────────────────────────────────────────
RELEASE_URL="${AASD_RELEASE_URL:-}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LOCAL_DIST="$SCRIPT_DIR/dist"
LOCAL_BIN="$SCRIPT_DIR/bin"

if [[ -n "$RELEASE_URL" ]]; then
  # Download from URL
  info "Downloading release archive from: $RELEASE_URL"
  TMP_DIR=$(mktemp -d)
  TARBALL="$TMP_DIR/aasd-release.tar.gz"
  curl -fsSL "$RELEASE_URL" -o "$TARBALL"
  [[ -s "$TARBALL" ]] || fail "Downloaded archive is empty — check RELEASE_URL"
  
  info "Extracting to $APP_HOME ..."
  mkdir -p "$APP_HOME"
  tar -xzf "$TARBALL" -C "$APP_HOME" --strip-components=1
  rm -rf "$TMP_DIR"
  pass "Release downloaded and extracted"
elif [[ -d "$LOCAL_DIST" ]]; then
  # Copy from local dist/ (full release bundle)
  info "Copying local dist/ to $APP_HOME ..."
  mkdir -p "$APP_HOME"
  cp -r "$LOCAL_DIST"/* "$APP_HOME/"
  pass "Local dist/ copied"
elif [[ -d "$LOCAL_BIN" ]]; then
  # Copy from local bin/ + source directory (dev workflow)
  info "Deploying from local bin/ and source files ..."
  mkdir -p "$APP_HOME"
  cp "$LOCAL_BIN"/aasd "$LOCAL_BIN"/gotestwaf "$APP_HOME/" 2>/dev/null || true
  cp "$SCRIPT_DIR/src/gotestwaf-config.yaml" "$APP_HOME/" 2>/dev/null || true
  cp -r "$SCRIPT_DIR/src/static" "$SCRIPT_DIR/src/templates" "$APP_HOME/" 2>/dev/null || true
  cp -r "$SCRIPT_DIR/src/gotestwaf/testcases" "$APP_HOME/" 2>/dev/null || true
  pass "Local binaries and assets deployed"
else
  fail "No release URL set (AASD_RELEASE_URL) and no local dist/ or bin/ found at $SCRIPT_DIR"
fi

# ──────────────────────────────────────────────
# Set ownership
# ──────────────────────────────────────────────
chown -R "$APP_USER:$APP_USER" "$APP_HOME"
chmod 755 "$APP_HOME"
pass "Ownership set to $APP_USER"

# ──────────────────────────────────────────────
# Create runtime directories
# ──────────────────────────────────────────────
mkdir -p "$APP_HOME/reports" "$APP_HOME/logs"
chown "$APP_USER:$APP_USER" "$APP_HOME/reports" "$APP_HOME/logs"

# ──────────────────────────────────────────────
# Configure secrets (prompt if not set via env)
# ──────────────────────────────────────────────
AI_API_KEY="${AASD_AI_API_KEY:-}"
BASE_URL="${AASD_BASE_URL:-}"
ADMIN_PASS="${AASD_ADMIN_PASSWORD:-}"

if [[ -z "$AI_API_KEY" ]]; then
  echo ""
  read -rp "Enter DeepSeek API key (or press Enter to skip AI reports): " AI_API_KEY
fi

if [[ -z "$BASE_URL" ]]; then
  echo ""
  read -rp "Enter public base URL (e.g. https://aasd.sechpoint.app): " BASE_URL
fi

if [[ -z "$ADMIN_PASS" ]]; then
  echo ""
  read -rp "Enter admin dashboard password: " ADMIN_PASS
  if [[ -z "$ADMIN_PASS" ]]; then
    ADMIN_PASS="$(tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c 16 || echo "aasd$(date +%s)")"
    warn "Generated random password: $ADMIN_PASS"
  fi
fi

# Write config.yaml
CONFIG_FILE="$APP_HOME/config.yaml"
cat > "$CONFIG_FILE" <<CONFIGEOF
ai:
  provider_url: "https://api.deepseek.com"
  api_key: "${AI_API_KEY:-}"
  model: "deepseek-chat"

server:
  base_url: "${BASE_URL:-}"

admin:
  username: "sechpoint"
  password: "${ADMIN_PASS:-}"
CONFIGEOF

chown "$APP_USER:$APP_USER" "$CONFIG_FILE"
chmod 600 "$CONFIG_FILE"
pass "Configuration written to $CONFIG_FILE"

# ──────────────────────────────────────────────
# Create systemd service
# ──────────────────────────────────────────────
SYSTEMD_FILE="/etc/systemd/system/aasd.service"

cat > "$SYSTEMD_FILE" <<SERVICEEOF
[Unit]
Description=AASD — API Attack Surface Discovery
Documentation=https://github.com/valllabh/aasd
After=network.target

[Service]
Type=simple
User=$APP_USER
Group=$APP_USER
WorkingDirectory=$APP_HOME
ExecStart=$APP_HOME/aasd
Restart=on-failure
RestartSec=5
LimitNOFILE=4096

# Security hardening
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=true

[Install]
WantedBy=multi-user.target
SERVICEEOF

chmod 644 "$SYSTEMD_FILE"
systemctl daemon-reload
systemctl enable aasd.service
pass "Systemd service created and enabled"

# ──────────────────────────────────────────────
# Start service
# ──────────────────────────────────────────────
info "Starting aasd.service..."
systemctl start aasd.service
sleep 2

if systemctl is-active --quiet aasd.service; then
  pass "aasd.service is running"
else
  warn "Service did not start — check: sudo journalctl -u aasd -n 50 --no-pager"
fi

# ──────────────────────────────────────────────
# Summary
# ──────────────────────────────────────────────
echo ""
echo -e "${GREEN}══════════════════════════════════════════════${NC}"
echo -e "${GREEN}  AASD installation complete${NC}"
echo -e "${GREEN}══════════════════════════════════════════════${NC}"
echo ""
echo "  URL:        http://$(hostname -I 2>/dev/null | awk '{print $1}'):8080"
echo "  Binary:     $APP_HOME/aasd"
echo "  Config:     $CONFIG_FILE"
echo "  Service:    aasd.service"
echo ""
echo "  Admin login: sechpoint / ${ADMIN_PASS:-<see config>}"
echo ""
echo "  Manage:"
echo "    sudo systemctl status aasd"
echo "    sudo journalctl -u aasd -f"
echo ""
