#!/bin/bash
#
# Volt Platform - Installation Script
# https://armoredgate.com
#
# Usage:
#   curl -sSL https://get.armoredgate.com/volt | sh
#

set -eo pipefail

# Configuration
INSTALL_DIR="${INSTALL_DIR:-/usr/local}"
CONFIG_DIR="${CONFIG_DIR:-/etc/volt}"
DATA_DIR="${DATA_DIR:-/var/lib/volt}"
RUN_DIR="${RUN_DIR:-/var/run/volt}"
VERSION="${VOLT_VERSION:-latest}"
BASE_URL="https://get.armoredgate.com"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log() { echo -e "${GREEN}[volt]${NC} $1"; }
info() { echo -e "${BLUE}[volt]${NC} $1"; }
warn() { echo -e "${YELLOW}[volt]${NC} $1"; }
error() { echo -e "${RED}[volt]${NC} $1" >&2; }

check_root() {
    if [ "$(id -u)" -ne 0 ]; then
        error "This script must be run as root"
        exit 1
    fi
}

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

detect_os() {
    if [ ! -f /etc/os-release ]; then
        error "Cannot detect OS (no /etc/os-release)"
        exit 1
    fi
    . /etc/os-release
    echo "$ID"
}

check_dependencies() {
    log "Checking dependencies..."

    local missing=""

    # Required: systemd
    if ! command -v systemctl >/dev/null 2>&1; then
        error "systemd is required but not found"
        exit 1
    fi

    # Required: systemd-nspawn (container runtime)
    if ! command -v systemd-nspawn >/dev/null 2>&1; then
        missing="$missing systemd-container"
    fi

    # Required commands
    for cmd in ip curl iptables; do
        if ! command -v "$cmd" >/dev/null 2>&1; then
            missing="$missing $cmd"
        fi
    done

    # Install missing packages
    if [ -n "$missing" ]; then
        # Map command names to package names
        local packages=""
        for pkg in $missing; do
            case "$pkg" in
                iptables) packages="$packages iptables" ;;
                ip) packages="$packages iproute2" ;;
                curl) packages="$packages curl" ;;
                systemd-container) packages="$packages systemd-container" ;;
                *) packages="$packages $pkg" ;;
            esac
        done

        info "Installing missing packages:$packages"
        local os
        os=$(detect_os)
        case "$os" in
            debian|ubuntu)
                apt-get update -qq >/dev/null 2>&1
                apt-get install -y -qq $packages >/dev/null 2>&1
                ;;
            fedora|rhel|centos|rocky|almalinux)
                dnf install -y -q $packages >/dev/null 2>&1
                ;;
            arch|manjaro)
                pacman -S --noconfirm $packages >/dev/null 2>&1
                ;;
            *)
                error "Please install manually:$packages"
                exit 1
                ;;
        esac
    fi

    # Kernel version check
    local kver
    kver=$(uname -r | cut -d. -f1-2)
    local kmajor
    kmajor=$(echo "$kver" | cut -d. -f1)
    local kminor
    kminor=$(echo "$kver" | cut -d. -f2)
    if [ "$kmajor" -lt 5 ] || { [ "$kmajor" -eq 5 ] && [ "$kminor" -lt 10 ]; }; then
        warn "Kernel $kver detected. Kernel >= 5.10 recommended for full Landlock support."
    fi

    # Landlock support
    if [ -f /sys/kernel/security/landlock/abi_version ]; then
        local abi
        abi=$(cat /sys/kernel/security/landlock/abi_version)
        info "Landlock ABI version $abi detected"
    else
        warn "Landlock not available (kernel >= 5.13 recommended)"
    fi

    # KVM support (for VMs)
    if [ -c /dev/kvm ]; then
        info "KVM available (VM support enabled)"
    else
        info "KVM not available (container-only mode)"
    fi

    log "Dependencies OK"
}

create_directories() {
    log "Creating directories..."
    mkdir -p "$INSTALL_DIR/bin"
    mkdir -p "$CONFIG_DIR"
    mkdir -p "$DATA_DIR"/{containers,vms,images,storage,cas}
    mkdir -p "$RUN_DIR"
    chmod 755 "$CONFIG_DIR" "$DATA_DIR" "$RUN_DIR"
}

install_binary() {
    log "Installing Volt..."

    local arch
    arch=$(detect_arch)

    # Check if we can build from source
    if [ -f "go.mod" ] && command -v go >/dev/null 2>&1; then
        info "Building from source..."
        go build -o "$INSTALL_DIR/bin/volt" ./cmd/volt
    else
        # Download pre-built binary
        local url="${BASE_URL}/releases/volt-linux-${arch}"
        info "Downloading Volt for linux/${arch}..."

        if curl -fsSL "$url" -o "$INSTALL_DIR/bin/volt" 2>/dev/null; then
            chmod +x "$INSTALL_DIR/bin/volt"
            log "Binary installed to $INSTALL_DIR/bin/volt"
        else
            warn "Pre-built binary not yet available for linux/${arch}"
            warn "Volt is currently in early access. Build from source:"
            echo ""
            info "  git clone https://git.armoredgate.com/ArmoredGate/volt.git"
            info "  cd volt && go build -o /usr/local/bin/volt ./cmd/volt"
            echo ""
            warn "Continuing with setup (directories, config, networking)..."
        fi
    fi
}

install_config() {
    log "Creating default configuration..."

    if [ ! -f "$CONFIG_DIR/config.yaml" ]; then
        cat > "$CONFIG_DIR/config.yaml" << 'EOF'
# Volt Platform Configuration
# https://docs.armoredgate.com

# Storage backend
storage:
  driver: stellarium
  path: /var/lib/volt/cas
  dedup: true

# Container runtime
containers:
  runtime: systemd-nspawn
  default_memory: 256M
  default_cpus: 1

# VM runtime (requires KVM)
vms:
  enabled: auto
  vmm: neutron-stardust
  default_memory: 128M
  default_kernel: /var/lib/volt/kernels/default

# Security
security:
  landlock: true
  seccomp: true
  capabilities: drop-all

# Networking
network:
  bridge: voltbr0
  subnet: 10.10.0.0/16
  dns: true

# Logging
logging:
  level: info
  format: json
EOF
    else
        info "Config already exists at $CONFIG_DIR/config.yaml"
    fi
}

setup_networking() {
    log "Setting up networking..."

    # Create bridge if it doesn't exist
    if ! ip link show voltbr0 >/dev/null 2>&1; then
        ip link add voltbr0 type bridge
        ip addr add 10.10.0.1/16 dev voltbr0
        ip link set voltbr0 up
    else
        info "Bridge voltbr0 already exists"
    fi

    # Enable IP forwarding
    sysctl -w net.ipv4.ip_forward=1 > /dev/null

    # Persist IP forwarding
    if [ -d /etc/sysctl.d ]; then
        echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-volt.conf
    fi

    # Setup NAT (idempotent)
    iptables -t nat -C POSTROUTING -s 10.10.0.0/16 -j MASQUERADE 2>/dev/null || \
        iptables -t nat -A POSTROUTING -s 10.10.0.0/16 -j MASQUERADE
    iptables -C FORWARD -i voltbr0 -j ACCEPT 2>/dev/null || \
        iptables -A FORWARD -i voltbr0 -j ACCEPT
    iptables -C FORWARD -o voltbr0 -j ACCEPT 2>/dev/null || \
        iptables -A FORWARD -o voltbr0 -j ACCEPT

    log "Networking configured (bridge: voltbr0, subnet: 10.10.0.0/16)"
}

setup_systemd_units() {
    log "Installing systemd unit templates..."

    # Container template unit
    cat > /etc/systemd/system/volt-container@.service << 'EOF'
[Unit]
Description=Volt Container: %i
After=network.target
Wants=network.target

[Service]
Type=notify
NotifyAccess=all
ExecStart=/usr/bin/systemd-nspawn --machine=%i --boot --network-bridge=voltbr0 --directory=/var/lib/volt/containers/%i
KillMode=mixed
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

    systemctl daemon-reload
}

print_summary() {
    echo ""
    log "============================================"
    log "  Volt Platform installed successfully!"
    log "============================================"
    echo ""
    info "Config:  $CONFIG_DIR/config.yaml"
    info "Data:    $DATA_DIR"
    echo ""

    if [ -x "$INSTALL_DIR/bin/volt" ]; then
        info "Version: $($INSTALL_DIR/bin/volt version 2>/dev/null || echo 'binary installed')"
        echo ""
        info "Quick start:"
        echo "  volt run --name hello alpine echo 'Hello from Volt'"
        echo "  volt ps"
    else
        info "Build from source to complete installation:"
        echo "  git clone https://git.armoredgate.com/ArmoredGate/volt.git"
        echo "  cd volt && go build -o /usr/local/bin/volt ./cmd/volt"
    fi
    echo ""
    info "Documentation: https://docs.armoredgate.com"
    info "Source code:    https://git.armoredgate.com/ArmoredGate/volt"
    echo ""
}

uninstall() {
    check_root
    local purge=0
    [ "${1:-}" = "--purge" ] && purge=1
    log "Uninstalling Volt Platform..."

    # systemd units
    systemctl stop 'volt-container@*' 2>/dev/null || true
    rm -f /etc/systemd/system/volt-container@.service
    systemctl daemon-reload 2>/dev/null || true

    # binary
    rm -f "$INSTALL_DIR/bin/volt" && info "Removed $INSTALL_DIR/bin/volt"

    # networking (reverse setup_networking)
    iptables -t nat -D POSTROUTING -s 10.10.0.0/16 -j MASQUERADE 2>/dev/null || true
    iptables -D FORWARD -i voltbr0 -j ACCEPT 2>/dev/null || true
    iptables -D FORWARD -o voltbr0 -j ACCEPT 2>/dev/null || true
    if ip link show voltbr0 >/dev/null 2>&1; then ip link del voltbr0 2>/dev/null && info "Removed bridge voltbr0"; fi
    rm -f /etc/sysctl.d/99-volt.conf

    # config
    rm -f "$CONFIG_DIR/config.yaml"; rmdir "$CONFIG_DIR" 2>/dev/null || true

    # data (preserved unless --purge)
    if [ "$purge" = 1 ]; then
        warn "Purging data directory $DATA_DIR"; rm -rf "$DATA_DIR"
    else
        info "Data preserved at $DATA_DIR"
        info "To remove it too: curl -sSL ${BASE_URL}/volt | sh -s uninstall --purge"
    fi
    echo ""
    log "Volt uninstalled."
}

main() {
    case "${1:-install}" in
        uninstall|remove)
            shift 2>/dev/null || true
            uninstall "$@"
            ;;
        install|"")
            echo ""
            log "Volt Platform Installer"
            log "https://armoredgate.com"
            echo ""
            check_root
            check_dependencies
            create_directories
            install_binary
            install_config
            setup_networking
            setup_systemd_units
            print_summary
            ;;
        *)
            echo "Usage: curl -sSL ${BASE_URL}/volt | sh [-s install|uninstall [--purge]]"
            exit 1
            ;;
    esac
}

main "$@"
