#!/bin/bash
set -e

# NexusGuard Server Installer
# Installs server-core, dashboard-ui, and configures systemd + nginx

# Defaults
SERVER_PORT=8080
WEB_PORT=80
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=nexusguard
DB_PASSWORD=nexusguard
DB_NAME=nexusguard
CONF_DIR="/etc/nexusguard"
CONF_FILE="$CONF_DIR/nexusguard.conf"
SERVICE_NAME="nexusguard-server"
NGINX_CONF="/etc/nginx/conf.d/nexusguard.conf"
DASHBOARD_DIR="/usr/share/nexusguard/dashboard"
BINARY_DIR="/usr/local/bin"

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

info() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }

usage() {
    cat << EOF
NexusGuard Server Installer

Usage: $0 [OPTIONS]

Options:
    --server-port PORT    API server port (default: 8080)
    --web-port PORT       Nginx web port (default: 80)
    --db-host HOST        PostgreSQL host (default: 127.0.0.1)
    --db-port PORT        PostgreSQL port (default: 5432)
    --db-user USER        PostgreSQL user (default: nexusguard)
    --db-pass PASS        PostgreSQL password (default: nexusguard)
    --db-name NAME        PostgreSQL database name (default: nexusguard)
    --help                Show this help message

Prerequisites:
    - nginx installed and running
    - PostgreSQL installed and running
    - Redis installed and running
    - Pre-built binaries in ./bin/ directory

This script will:
    1. Create PostgreSQL database and user
    2. Copy server-core binary to /usr/local/bin/
    3. Copy dashboard dist to /usr/share/nexusguard/dashboard/
    4. Create /etc/nexusguard/nexusguard.conf
    5. Run database migration
    6. Create systemd service
    7. Configure nginx
EOF
    exit 0
}

# Parse arguments
while [[ "$#" -gt 0 ]]; do
    case $1 in
        --server-port) SERVER_PORT="$2"; shift ;;
        --web-port) WEB_PORT="$2"; shift ;;
        --db-host) DB_HOST="$2"; shift ;;
        --db-port) DB_PORT="$2"; shift ;;
        --db-user) DB_USER="$2"; shift ;;
        --db-pass) DB_PASSWORD="$2"; shift ;;
        --db-name) DB_NAME="$2"; shift ;;
        --help) usage ;;
        *) error "Unknown parameter: $1" ;;
    esac
    shift
done

# Check root
if [ "$EUID" -ne 0 ]; then
    error "Please run as root"
fi

# Check dependencies
command -v nginx >/dev/null 2>&1 || error "nginx is not installed"
command -v systemctl >/dev/null 2>&1 || error "systemctl is not installed"
command -v psql >/dev/null 2>&1 || error "PostgreSQL client (psql) is not installed"
command -v redis-cli >/dev/null 2>&1 || error "Redis client (redis-cli) is not installed"

# Check for pre-built binaries
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SERVER_BINARY="$SCRIPT_DIR/bin/server-core"
DASHBOARD_DIST="$SCRIPT_DIR/apps/dashboard-ui/dist"

if [ ! -f "$SERVER_BINARY" ]; then
    error "Server binary not found at $SERVER_BINARY. Build first: cd apps/server-core && go build -o ../../bin/server-core ."
fi

if [ ! -d "$DASHBOARD_DIST" ]; then
    error "Dashboard dist not found at $DASHBOARD_DIST. Build first: cd apps/dashboard-ui && npm run build"
fi

# Check PostgreSQL connection
if ! psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "SELECT 1" >/dev/null 2>&1; then
    warn "Cannot connect to PostgreSQL with current credentials. Trying with postgres user..."
    if ! psql -h "$DB_HOST" -p "$DB_PORT" -U postgres -d postgres -c "SELECT 1" >/dev/null 2>&1; then
        error "Cannot connect to PostgreSQL. Please ensure PostgreSQL is running and accessible."
    fi
    PG_SUPERUSER="postgres"
else
    PG_SUPERUSER="$DB_USER"
fi

# Check Redis connection
if ! redis-cli -h "${DB_HOST}" -p 6379 ping >/dev/null 2>&1; then
    error "Cannot connect to Redis. Please ensure Redis is running."
fi

info "Installing NexusGuard Server..."

# Create directories
info "Creating directories..."
mkdir -p "$CONF_DIR"
mkdir -p "$DASHBOARD_DIR"
mkdir -p "$BINARY_DIR"

# Setup PostgreSQL database
info "Setting up PostgreSQL database..."
DB_EXISTS=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$PG_SUPERUSER" -d postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" 2>/dev/null || echo "")
if [ "$DB_EXISTS" != "1" ]; then
    info "Creating database user: $DB_USER"
    psql -h "$DB_HOST" -p "$DB_PORT" -U "$PG_SUPERUSER" -d postgres -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';" >/dev/null 2>&1 || warn "User $DB_USER may already exist"
fi

DB_EXISTS=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$PG_SUPERUSER" -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'" 2>/dev/null || echo "")
if [ "$DB_EXISTS" != "1" ]; then
    info "Creating database: $DB_NAME"
    psql -h "$DB_HOST" -p "$DB_PORT" -U "$PG_SUPERUSER" -d postgres -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;" >/dev/null 2>&1 || warn "Database $DB_NAME may already exist"
fi

# Copy server binary
info "Installing server-core binary..."
cp "$SERVER_BINARY" "$BINARY_DIR/$SERVICE_NAME"
chmod +x "$BINARY_DIR/$SERVICE_NAME"

# Copy dashboard dist
info "Installing dashboard files..."
cp -r "$DASHBOARD_DIST"/* "$DASHBOARD_DIR/"

# Create config file (only if not exists)
if [ ! -f "$CONF_FILE" ]; then
    info "Creating config file with auto-generated secrets..."
    
    RANDOM_JWT=$(openssl rand -hex 32)
    RANDOM_SALT=$(openssl rand -hex 32)
    
    cat << EOF > "$CONF_FILE"
# NexusGuard Configuration
# Generated by install.sh on $(date)

# Database
DB_HOST=$DB_HOST
DB_PORT=$DB_PORT
DB_USER=$DB_USER
DB_PASSWORD=$DB_PASSWORD
DB_NAME=$DB_NAME

# Redis
REDIS_ADDR=127.0.0.1:6379

# Security (auto-generated)
JWT_SECRET=$RANDOM_JWT
SERVER_SALT=$RANDOM_SALT

# Network
NFTABLES_TABLE=nexusguard
IPAM_POOL=10.8.0.0/16

# Server
GIN_MODE=release
PORT=$SERVER_PORT

# Dashboard
CORS_ALLOWED_ORIGINS=http://localhost:$WEB_PORT
SHARE_LINK_TTL=24h
EOF
    chmod 600 "$CONF_FILE"
    info "Config file created at $CONF_FILE"
else
    info "Config file already exists, skipping..."
fi

# Run database migration
info "Running database migration..."
set +e
"$BINARY_DIR/$SERVICE_NAME" -migrate-prod 2>&1 | tail -5
set -e
info "Database migration completed."

# Create systemd service
info "Creating systemd service..."
cat << EOF > "/etc/systemd/system/$SERVICE_NAME.service"
[Unit]
Description=NexusGuard SD-WAN Server
After=network.target postgresql.service redis.service
Wants=postgresql.service redis.service

[Service]
Type=simple
User=root
WorkingDirectory=$BINARY_DIR
EnvironmentFile=$CONF_FILE
ExecStart=$BINARY_DIR/$SERVICE_NAME
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

# Security hardening
NoNewPrivileges=false
ProtectSystem=false
ProtectHome=false

[Install]
WantedBy=multi-user.target
EOF

# Create nginx config
info "Creating nginx configuration..."
cat << EOF > "$NGINX_CONF"
server {
    listen       $WEB_PORT;
    listen  [::]:$WEB_PORT;
    server_name  localhost;

    # Inject runtime config into HTML responses
    sub_filter '</head>' '<script>window.__CONFIG__ = { apiBaseUrl: "/api/v1" };</script></head>';
    sub_filter_once on;
    sub_filter_types text/html;

    location /api/ {
        proxy_pass http://127.0.0.1:$SERVER_PORT;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
    }

    location / {
        root $DASHBOARD_DIR;
        try_files \$uri \$uri/ /index.html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   $DASHBOARD_DIR;
    }
}
EOF

# Enable and start service
info "Enabling and starting service..."
systemctl daemon-reload
systemctl enable "$SERVICE_NAME"
systemctl start "$SERVICE_NAME"

# Reload nginx
info "Reloading nginx..."
nginx -t && systemctl reload nginx

info "Installation complete!"
echo ""
info "Access URL: http://localhost:$WEB_PORT"
info "Config file: $CONF_FILE"
info "Service status: systemctl status $SERVICE_NAME"
echo ""
info "Secrets were auto-generated. Edit $CONF_FILE to customize if needed."
info "Restart after changes: systemctl restart $SERVICE_NAME"
echo ""
info "To create admin user: $BINARY_DIR/$SERVICE_NAME -create-admin -user admin -pass 'YourPassword!'"
