#!/bin/bash
# Deployment script for GNSS Guard Server to AWS EC2 (Debian)
# Uses Docker with Nginx + Certbot for SSL

set -e

# =============================================================================
# CONFIGURATION - Edit these values before deploying
# =============================================================================

# AWS EC2 Instance
SERVER_USER="admin"
SERVER_HOST="gnss.tototheo.com"
SERVER_PORT="22"

# SSH Key file (relative to project root or absolute path)
SSH_KEY="server/.cert/Cortex-01.pem"

# Environment file to deploy (relative to project root)
# Copy server/env.example to server/.env.prod and configure it
ENV_FILE="server/.env.prod"

# Domain for SSL (required for Let's Encrypt)
# Must match GNSS_SERVER_DOMAIN in your env file
SERVER_DOMAIN="gnss.tototheo.com"

# Email for Let's Encrypt notifications
LETSENCRYPT_EMAIL="alexander.s@tototheo.com"

# =============================================================================
# END OF CONFIGURATION
# =============================================================================

PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REMOTE_PATH="/opt/gnss-guard-server"

# Helper for display: include port in ssh commands if non-standard
if [ "${SERVER_PORT}" = "22" ]; then
    SSH_DISPLAY="ssh -i ${SSH_KEY} ${SERVER_USER}@${SERVER_HOST}"
else
    SSH_DISPLAY="ssh -i ${SSH_KEY} -p ${SERVER_PORT} ${SERVER_USER}@${SERVER_HOST}"
fi

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

log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Resolve SSH key path
get_ssh_key_path() {
    if [[ "${SSH_KEY}" = /* ]]; then
        echo "${SSH_KEY}"
    else
        echo "${PROJECT_DIR}/${SSH_KEY}"
    fi
}

# SSH/SCP wrapper with key-based auth
ssh_cmd() {
    local key_path=$(get_ssh_key_path)
    ssh -i "${key_path}" -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${SERVER_PORT} "$@"
}

scp_cmd() {
    local key_path=$(get_ssh_key_path)
    scp -i "${key_path}" -P ${SERVER_PORT} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$@"
}

# =============================================================================
# HELPER FUNCTIONS
# =============================================================================

test_connection() {
    log_info "Testing SSH connection to ${SERVER_USER}@${SERVER_HOST}:${SERVER_PORT}..."
    if ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "echo 'Connection successful'" 2>/dev/null; then
        log_info "SSH connection successful"
        return 0
    else
        log_error "SSH connection failed. Please ensure:"
        log_error "  1. EC2 instance is running and accessible at ${SERVER_HOST}"
        log_error "  2. Security group allows SSH from your IP"
        log_error "  3. SSH key is configured at ${SSH_KEY}"
        return 1
    fi
}

install_docker() {
    log_info "Installing Docker..."
    
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "sudo bash -s" << 'DOCKER_EOF'
set -e

# Check if Docker is already installed
if command -v docker &> /dev/null; then
    echo "Docker is already installed"
    docker --version
    exit 0
fi

# Install Docker using official script
curl -fsSL https://get.docker.com | sh

# Add current user to docker group
usermod -aG docker $SUDO_USER || true

# Install Docker Compose plugin, rsync, and PostgreSQL client
apt-get update
apt-get install -y docker-compose-plugin rsync postgresql-client

# Start and enable Docker
systemctl enable docker
systemctl start docker

echo "Docker installed successfully"
docker --version
docker compose version
DOCKER_EOF
    
    log_info "Docker installed"
}

ensure_rsync() {
    # Ensure rsync is installed on the remote server
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "which rsync > /dev/null 2>&1 || sudo apt-get update && sudo apt-get install -y rsync" > /dev/null 2>&1
}

ensure_postgresql_client() {
    # Ensure postgresql-client is installed on the remote server
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "which psql > /dev/null 2>&1 || sudo apt-get update && sudo apt-get install -y postgresql-client" > /dev/null 2>&1
}

install_fail2ban() {
    log_info "Installing and configuring fail2ban..."
    
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "sudo bash -s" << 'FAIL2BAN_EOF'
set -e

# Install fail2ban
if ! command -v fail2ban-server &> /dev/null; then
    apt-get update
    apt-get install -y fail2ban
    echo "fail2ban installed"
else
    echo "fail2ban already installed"
fi

# Create local jail configuration
cat > /etc/fail2ban/jail.local << 'JAIL_EOF'
# GNSS Guard Server - fail2ban configuration
# Auto-generated by deploy_server.sh

[DEFAULT]
# Ban for 1 hour after 5 failures
bantime = 3600
findtime = 600
maxretry = 5

# Use iptables for banning
banaction = iptables-multiport

# Email notifications (uncomment and configure if needed)
# destemail = admin@example.com
# sendername = Fail2Ban
# action = %(action_mwl)s

# Whitelist internal networks (add your office IPs if needed)
ignoreip = 127.0.0.1/8 ::1

# =============================================================================
# SSH Protection
# =============================================================================
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600

# =============================================================================
# Nginx Protection (HTTP/HTTPS)
# =============================================================================

# Block IPs with too many login failures (401)
[nginx-login]
enabled = true
port = http,https
filter = nginx-login
logpath = /var/log/nginx/access.log
backend = auto
maxretry = 10
findtime = 300
bantime = 3600

# Block IPs with excessive 4xx errors (scanners)
[nginx-badbots]
enabled = true
port = http,https
filter = nginx-badbots
logpath = /var/log/nginx/access.log
backend = auto
maxretry = 30
findtime = 60
bantime = 7200

# Block IPs hammering the validation endpoint
[nginx-ratelimit]
enabled = true
port = http,https
filter = nginx-ratelimit
logpath = /var/log/nginx/access.log
backend = auto
maxretry = 100
findtime = 60
bantime = 1800
JAIL_EOF

# Create nginx login filter (detects failed login attempts)
cat > /etc/fail2ban/filter.d/nginx-login.conf << 'FILTER_EOF'
# Fail2Ban filter for nginx login failures
# Matches 401 responses on login-related endpoints

[Definition]
failregex = ^<HOST> .* "(GET|POST) /login.*" 401
            ^<HOST> .* "(GET|POST) /api/v1/.*" 401
ignoreregex =
FILTER_EOF

# Create nginx badbots filter (detects scanners and bad bots)
cat > /etc/fail2ban/filter.d/nginx-badbots.conf << 'FILTER_EOF'
# Fail2Ban filter for nginx bad bots and scanners
# Matches excessive 403/404 errors

[Definition]
failregex = ^<HOST> .* "(GET|POST|HEAD) .*" (403|404)
ignoreregex = ^<HOST> .* "(GET|POST) /api/v1/validation" 
              ^<HOST> .* "GET /health"
              ^<HOST> .* "GET /static/"
              ^<HOST> .* "GET /favicon.ico"
FILTER_EOF

# Create nginx rate limit filter (detects endpoint hammering)
cat > /etc/fail2ban/filter.d/nginx-ratelimit.conf << 'FILTER_EOF'
# Fail2Ban filter for nginx rate limiting
# Matches high-frequency requests to any endpoint

[Definition]
failregex = ^<HOST> .* "(GET|POST) /api/v1/validation" [0-9]{3}
ignoreregex =
FILTER_EOF

# Ensure nginx log directory and files exist before fail2ban starts
mkdir -p /var/log/nginx
touch /var/log/nginx/access.log
touch /var/log/nginx/error.log
chmod 644 /var/log/nginx/access.log /var/log/nginx/error.log

# Enable fail2ban
systemctl enable fail2ban

# Restart fail2ban and wait for it to start
systemctl restart fail2ban
sleep 2

# Check if fail2ban started successfully
if systemctl is-active --quiet fail2ban; then
    echo "fail2ban configured and started successfully"
    fail2ban-client status
else
    echo "fail2ban service failed to start, checking logs..."
    journalctl -u fail2ban --no-pager -n 20
    # Try to start it again
    systemctl start fail2ban
fi
FAIL2BAN_EOF
    
    log_info "fail2ban installed and configured"
}

ensure_database() {
    log_info "Ensuring database exists..."
    
    # Ensure postgresql-client is available
    ensure_postgresql_client
    
    # Extract database connection info from env file on server
    local db_url=$(ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "grep '^GNSS_SERVER_DATABASE_URL=' ${REMOTE_PATH}/.env.prod 2>/dev/null | cut -d'=' -f2- | tr -d '\"' | tr -d \"'\"")
    
    if [ -z "${db_url}" ]; then
        log_warn "GNSS_SERVER_DATABASE_URL not found in .env.prod, skipping database check"
        return 0
    fi
    
    # Parse the database URL: postgresql://user:password@host:port/database
    local db_user=$(echo "${db_url}" | sed -n 's|postgresql://\([^:]*\):.*|\1|p')
    local db_pass=$(echo "${db_url}" | sed -n 's|postgresql://[^:]*:\([^@]*\)@.*|\1|p')
    local db_host=$(echo "${db_url}" | sed -n 's|postgresql://[^@]*@\([^:/]*\).*|\1|p')
    local db_port=$(echo "${db_url}" | sed -n 's|postgresql://[^@]*@[^:]*:\([0-9]*\)/.*|\1|p')
    local db_name=$(echo "${db_url}" | sed -n 's|postgresql://[^@]*@[^/]*/\([^?]*\).*|\1|p')
    
    [ -z "${db_port}" ] && db_port="5432"
    
    if [ -z "${db_host}" ] || [ -z "${db_name}" ] || [ -z "${db_user}" ]; then
        log_warn "Could not parse database URL, skipping database check"
        return 0
    fi
    
    log_info "Checking if database '${db_name}' exists on ${db_host}..."
    
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "PGPASSWORD='${db_pass}' psql -h ${db_host} -p ${db_port} -U ${db_user} -d postgres -tc \"SELECT 1 FROM pg_database WHERE datname = '${db_name}'\" | grep -q 1 || PGPASSWORD='${db_pass}' psql -h ${db_host} -p ${db_port} -U ${db_user} -d postgres -c \"CREATE DATABASE ${db_name}\""
    
    if [ $? -eq 0 ]; then
        log_info "Database '${db_name}' ready"
    else
        log_warn "Could not verify/create database (may require manual creation)"
    fi
}

deploy_server_files() {
    log_info "Deploying server files to ${SERVER_USER}@${SERVER_HOST}:${REMOTE_PATH}..."
    
    ensure_rsync
    
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "sudo mkdir -p ${REMOTE_PATH} && sudo chown ${SERVER_USER}:${SERVER_USER} ${REMOTE_PATH}"
    
    local ssh_key_path=$(get_ssh_key_path)
    local rsync_ssh="ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p ${SERVER_PORT}"
    if [ -n "${SSH_KEY}" ] && [ -f "${ssh_key_path}" ]; then
        rsync_ssh="${rsync_ssh} -i ${ssh_key_path}"
    fi
    
    # Backup SSL nginx config if it exists
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "test -f ${REMOTE_PATH}/nginx/conf.d/default.conf && \
        grep -q 'ssl_certificate' ${REMOTE_PATH}/nginx/conf.d/default.conf && \
        cp ${REMOTE_PATH}/nginx/conf.d/default.conf /tmp/nginx-ssl-backup.conf || true" 2>/dev/null
    
    rsync -avz --delete \
        -e "${rsync_ssh}" \
        --exclude='.env*' \
        --exclude='env.example' \
        --exclude='.cert/' \
        --exclude='*.pem' \
        --exclude='.DS_Store' \
        --exclude='__pycache__' \
        --exclude='*.pyc' \
        "${PROJECT_DIR}/server/" "${SERVER_USER}@${SERVER_HOST}:${REMOTE_PATH}/"
    
    # Restore SSL nginx config if it was backed up
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "test -f /tmp/nginx-ssl-backup.conf && \
        cp /tmp/nginx-ssl-backup.conf ${REMOTE_PATH}/nginx/conf.d/default.conf && \
        rm /tmp/nginx-ssl-backup.conf && echo 'SSL nginx config restored' || true" 2>/dev/null
    
    log_info "Server files deployed successfully"
}

deploy_env_file() {
    log_info "Deploying server environment file..."
    
    local env_file_path="${PROJECT_DIR}/${ENV_FILE}"
    
    if [ ! -f "${env_file_path}" ]; then
        log_error "Environment file not found: ${env_file_path}"
        log_error ""
        log_error "Please create it first:"
        log_error "  cp server/env.example server/.env.prod"
        log_error "  # Edit server/.env.prod with your configuration"
        return 1
    fi
    
    if ! grep -q "^GNSS_SERVER_DATABASE_URL=" "${env_file_path}" || \
       grep -q "your-password\|your-rds-endpoint" "${env_file_path}"; then
        log_warn "Environment file may have placeholder values!"
        log_warn "Please ensure GNSS_SERVER_DATABASE_URL is properly configured."
    fi
    
    scp_cmd "${env_file_path}" "${SERVER_USER}@${SERVER_HOST}:${REMOTE_PATH}/.env.prod"
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "chmod 600 ${REMOTE_PATH}/.env.prod"
    
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cat >> ${REMOTE_PATH}/.env.prod << EOF

# SSL settings (added by deploy script)
LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
EOF"
    
    log_info "Environment file deployed"
}

clean_docker() {
    log_info "Cleaning Docker build cache and unused images..."
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "docker system prune -f && docker builder prune -f 2>/dev/null || true"
    log_info "Docker cache cleaned"
}

stop_server() {
    log_info "Stopping Docker containers..."
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH} && docker compose down 2>/dev/null || true"
    log_info "Containers stopped"
}

build_and_start() {
    local CLEAN_BUILD=$1
    
    ensure_database
    
    if [ "$CLEAN_BUILD" = "true" ]; then
        clean_docker
    fi
    
    log_info "Building and starting Docker containers..."
    
    if ! ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH} && docker compose up -d --build" 2>&1; then
        log_warn "Build failed, attempting clean rebuild..."
        clean_docker
        ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH} && docker compose build --no-cache && docker compose up -d"
    fi
    
    sleep 5
    
    log_info "Container status:"
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH} && docker compose ps"
}

setup_ssl() {
    log_info "Setting up SSL certificate with Let's Encrypt..."
    
    if [ -z "${SERVER_DOMAIN}" ] || [ "${SERVER_DOMAIN}" = "gnss.yourdomain.com" ]; then
        log_error "SERVER_DOMAIN not configured properly"
        log_error "Edit deploy_server.sh and set SERVER_DOMAIN"
        return 1
    fi
    
    log_info "Requesting SSL certificate for ${SERVER_DOMAIN}..."
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH} && docker compose run --rm --entrypoint certbot certbot certonly --webroot --webroot-path=/var/www/certbot --email ${LETSENCRYPT_EMAIL} --agree-tos --no-eff-email --non-interactive -d ${SERVER_DOMAIN}"
    
    log_info "Configuring nginx for SSL..."
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH}/nginx/conf.d && \
        cp gnss-guard-ssl.conf.template gnss-guard-ssl.conf && \
        sed -i 's/YOUR_DOMAIN_HERE/${SERVER_DOMAIN}/g' gnss-guard-ssl.conf && \
        rm -f default.conf && \
        mv gnss-guard-ssl.conf default.conf"
    
    log_info "Reloading nginx..."
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH} && docker compose restart nginx"
    
    log_info "SSL setup complete!"
    log_info "Your server is now accessible at: https://${SERVER_DOMAIN}"
}

show_status() {
    log_info "Server status:"
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH} && docker compose ps"
}

show_logs() {
    local FOLLOW=$1
    if [ "$FOLLOW" = "true" ]; then
        log_info "Following server logs (Ctrl+C to stop)..."
        ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH} && docker compose logs -f gnss-server"
    else
        log_info "Recent server logs:"
        ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH} && docker compose logs --tail=100 gnss-server"
    fi
}

show_rds_instructions() {
    echo ""
    echo "============================================================================="
    echo "AWS RDS PostgreSQL Setup Instructions"
    echo "============================================================================="
    echo ""
    echo "1. Create an RDS PostgreSQL instance:"
    echo "   - Engine: PostgreSQL 15+"
    echo "   - Instance class: db.t3.micro (free tier) or larger"
    echo "   - Storage: 20GB General Purpose SSD"
    echo "   - VPC: Same as your EC2 instance"
    echo "   - Public access: No (recommended)"
    echo ""
    echo "2. Configure Security Group:"
    echo "   - Allow inbound PostgreSQL (port 5432) from EC2 security group"
    echo ""
    echo "3. Create database and user (connect from EC2 instance):"
    echo "   psql -h YOUR_RDS_ENDPOINT -U postgres"
    echo "   CREATE DATABASE gnss_guard;"
    echo "   CREATE USER gnss_admin WITH PASSWORD 'YOUR_SECURE_PASSWORD';"
    echo "   GRANT ALL PRIVILEGES ON DATABASE gnss_guard TO gnss_admin;"
    echo ""
    echo "4. Create and configure your environment file:"
    echo "   cp server/env.example server/.env.prod"
    echo "   # Edit server/.env.prod and set GNSS_SERVER_DATABASE_URL"
    echo ""
    echo "============================================================================="
}

show_ec2_instructions() {
    echo ""
    echo "============================================================================="
    echo "AWS EC2 Setup Instructions"
    echo "============================================================================="
    echo ""
    echo "1. Launch EC2 instance:"
    echo "   - AMI: Debian 12 (or Ubuntu 22.04)"
    echo "   - Instance type: t3.micro (free tier) or t3.small"
    echo "   - Storage: 20GB"
    echo ""
    echo "2. Configure Security Group - Allow inbound:"
    echo "   - SSH (22) from your IP"
    echo "   - HTTP (80) from anywhere"
    echo "   - HTTPS (443) from anywhere"
    echo "   - PostgreSQL (5432) to/from your RDS security group"
    echo ""
    echo "3. Connect and test:"
    echo "   ssh -i your-key.pem admin@YOUR_EC2_IP"
    echo ""
    echo "4. Configure this script:"
    echo "   SERVER_HOST=\"YOUR_EC2_IP\""
    echo "   SERVER_USER=\"admin\"  # or 'ubuntu' for Ubuntu AMI"
    echo ""
    echo "============================================================================="
}

# =============================================================================
# MAIN
# =============================================================================

show_fail2ban_status() {
    log_info "fail2ban status:"
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "sudo fail2ban-client status 2>/dev/null || echo 'fail2ban not installed'"
    echo ""
    log_info "Jail details:"
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "sudo fail2ban-client status sshd 2>/dev/null || true"
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "sudo fail2ban-client status nginx-login 2>/dev/null || true"
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "sudo fail2ban-client status nginx-badbots 2>/dev/null || true"
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "sudo fail2ban-client status nginx-ratelimit 2>/dev/null || true"
}

# =============================================================================
# LOCAL MODE - Run server locally with converted client database
# =============================================================================

run_local() {
    local asset_name="${1:-Local Asset}"
    local client_db="${PROJECT_DIR}/data/gnss_guard.db"
    local server_db="${PROJECT_DIR}/server/data/server_local.db"
    local env_file="${PROJECT_DIR}/server/.env.local"
    
    log_info "Running server in local mode..."
    
    # Check if client database exists
    if [ ! -f "${client_db}" ]; then
        log_error "Client database not found: ${client_db}"
        log_error "Please ensure data/gnss_guard.db exists (from client installation)"
        return 1
    fi
    
    # Check for Python
    if ! command -v python3 &> /dev/null; then
        log_error "Python 3 is required but not found"
        return 1
    fi
    
    # Create server data directory
    mkdir -p "${PROJECT_DIR}/server/data"
    
    # Convert client database to server format
    log_info "Converting client database to server format..."
    log_info "  Asset name: ${asset_name}"
    
    if ! python3 "${PROJECT_DIR}/server/tools/import_client_db_to_sqlite.py" \
        --asset-name "${asset_name}" \
        --input "${client_db}" \
        --output "${server_db}"; then
        log_error "Database conversion failed"
        return 1
    fi
    
    echo ""
    
    # Create local environment file
    log_info "Creating local environment file..."
    cat > "${env_file}" << EOF
# Local server configuration (auto-generated)
# SQLite database for local testing

GNSS_SERVER_DATABASE_URL=sqlite:///${server_db}
GNSS_SERVER_WEB_USERNAME=test
GNSS_SERVER_WEB_PASSWORD=Tototheo.25!
GNSS_SERVER_SECRET_KEY=local-dev-secret-key-change-in-production
GNSS_SERVER_DEBUG=true
GNSS_SERVER_HOST=127.0.0.1
GNSS_SERVER_PORT=8000
EOF
    
    log_info "Environment file created: ${env_file}"
    echo ""
    
    # Install server dependencies if needed
    if [ -f "${PROJECT_DIR}/server/requirements.txt" ]; then
        log_info "Checking server dependencies..."
        pip3 install -q -r "${PROJECT_DIR}/server/requirements.txt" 2>/dev/null || {
            log_warn "Some dependencies may not be installed. Running anyway..."
        }
    fi
    
    echo ""
    log_info "=============================================="
    log_info "Starting local GNSS Guard Server"
    log_info "=============================================="
    echo ""
    log_info "Dashboard: http://localhost:8000"
    log_info "Login:     admin / localadmin123"
    echo ""
    log_info "Press Ctrl+C to stop the server"
    echo ""
    
    # Change to server directory and run
    cd "${PROJECT_DIR}/server"
    
    # Set environment file path
    export ENV_FILE="${env_file}"
    
    # Run the server using uvicorn
    python3 -m uvicorn main:app --host 127.0.0.1 --port 8000 --reload --env-file "${env_file}"
}

unban_ip() {
    local ip=$1
    log_info "Unbanning IP ${ip} from all jails..."
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "sudo fail2ban-client unban ${ip} 2>/dev/null || echo 'IP not banned or fail2ban not running'"
    log_info "Done"
}

# =============================================================================
# IMPORT CLIENT DATABASES - Import .db files from server/import/ to PostgreSQL
# =============================================================================
# Filename format: {asset_id}_{asset_name}.db
# Example: 2_msc_charlotte.db -> Asset ID: 2, Asset Name: "MSC Charlotte"
# =============================================================================

import_client_databases() {
    local import_dir="${PROJECT_DIR}/server/import"
    local import_script="${PROJECT_DIR}/server/tools/import_client_db_to_postgres.py"
    
    # Check if import directory exists and has .db files
    if [ ! -d "${import_dir}" ]; then
        log_info "No import directory found at server/import/, skipping import"
        return 0
    fi
    
    local db_files=$(find "${import_dir}" -maxdepth 1 -name "*.db" -type f 2>/dev/null)
    if [ -z "${db_files}" ]; then
        log_info "No .db files found in server/import/, skipping import"
        return 0
    fi
    
    log_info "Found client databases to import:"
    echo "${db_files}" | while read -r f; do
        echo "  - $(basename "$f")"
    done
    echo ""
    
    # Get database URL from env file on server
    local db_url=$(ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "grep '^GNSS_SERVER_DATABASE_URL=' ${REMOTE_PATH}/.env.prod 2>/dev/null | cut -d'=' -f2- | tr -d '\"' | tr -d \"'\"")
    
    if [ -z "${db_url}" ]; then
        log_error "GNSS_SERVER_DATABASE_URL not found in .env.prod, cannot import databases"
        return 1
    fi
    
    # Create import directory on server
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "mkdir -p ${REMOTE_PATH}/import"
    
    # Copy import script to server
    log_info "Deploying import script to server..."
    scp_cmd "${import_script}" "${SERVER_USER}@${SERVER_HOST}:${REMOTE_PATH}/import/"
    
    # Install psycopg2 on server if not present
    log_info "Ensuring psycopg2-binary is installed on server..."
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "sudo apt-get update -qq && sudo apt-get install -y -qq python3-pip libpq-dev > /dev/null 2>&1; sudo pip3 install --break-system-packages psycopg2-binary 2>/dev/null || sudo pip3 install psycopg2-binary 2>/dev/null || pip3 install psycopg2-binary"
    
    # Process each .db file
    echo "${db_files}" | while read -r db_file; do
        local filename=$(basename "${db_file}")
        
        # Parse filename: {asset_id}_{asset_name}.db
        # Example: 2_msc_charlotte.db -> asset_id=2, asset_name="MSC Charlotte"
        local asset_id=$(echo "${filename}" | sed -n 's/^\([0-9]*\)_.*/\1/p')
        local asset_name_raw=$(echo "${filename}" | sed -n 's/^[0-9]*_\(.*\)\.db$/\1/p')
        
        if [ -z "${asset_id}" ] || [ -z "${asset_name_raw}" ]; then
            log_warn "Could not parse filename '${filename}' (expected format: {id}_{name}.db)"
            log_warn "Skipping this file..."
            continue
        fi
        
        # Convert asset name: msc_charlotte -> MSC Charlotte
        # Replace underscores with spaces, capitalize each word
        local asset_name=$(echo "${asset_name_raw}" | tr '_' ' ' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1')
        # Handle uppercase acronyms like MSC (use space/start boundaries for compatibility)
        asset_name=$(echo "${asset_name}" | sed 's/^Msc /MSC /g; s/ Msc / MSC /g; s/ Msc$/ MSC/g; s/^Msc$/MSC/g')
        
        log_info "Importing: ${filename}"
        log_info "  Asset ID:   ${asset_id}"
        log_info "  Asset Name: ${asset_name}"
        
        # Copy database file to server
        scp_cmd "${db_file}" "${SERVER_USER}@${SERVER_HOST}:${REMOTE_PATH}/import/"
        
        # Run import script on server
        ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH}/import && python3 import_client_db_to_postgres.py \
            --input '${filename}' \
            --asset-name '${asset_name}' \
            --asset-id ${asset_id} \
            --database-url '${db_url}'"
        
        if [ $? -eq 0 ]; then
            log_info "Successfully imported ${filename}"
            # Optionally move processed file to .imported
            # ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "mv ${REMOTE_PATH}/import/${filename} ${REMOTE_PATH}/import/${filename}.imported"
        else
            log_error "Failed to import ${filename}"
        fi
        
        echo ""
    done
    
    log_info "Database import complete"
}

show_help() {
    echo "Usage: $0 [OPTIONS]"
    echo ""
    echo "GNSS Guard Server Deployment Script (Docker + Nginx)"
    echo ""
    echo "Options:"
    echo "  --start, -s    Deploy and start server (default if no options)"
    echo "  --debug, -d    Deploy and follow logs in terminal (foreground mode)"
    echo "  --ssl          Setup SSL certificate with Let's Encrypt"
    echo "  --clean, -c    Clean Docker cache before building"
    echo "  --stop         Stop server containers"
    echo "  --restart      Restart server containers"
    echo "  --status       Show container status"
    echo "  --logs         Show recent server logs"
    echo "  --logs-all     Show all container logs"
    echo "  --fail2ban     Show fail2ban status and banned IPs"
    echo "  --unban IP     Unban a specific IP address"
    echo "  --import       Import client databases from server/import/ to PostgreSQL"
    echo "  --local [NAME] Run server locally with converted client database"
    echo "  --rds          Show RDS setup instructions"
    echo "  --ec2          Show EC2 setup instructions"
    echo "  --help, -h     Show this help message"
    echo ""
    echo "Environment variables:"
    echo "  SERVER_USER    SSH username (default: admin)"
    echo "  SERVER_HOST    Server hostname/IP (default: from config)"
    echo "  SERVER_PORT    SSH port (default: 22)"
    echo "  ENV_FILE       Path to env file (default: server/.env.prod)"
    echo ""
    echo "Examples:"
    echo "  $0              Deploy and start server (production mode)"
    echo "  $0 --debug      Deploy and follow logs in terminal"
    echo "  $0 --ssl        Setup SSL certificate after deployment"
    echo "  $0 --clean      Deploy with clean Docker cache"
    echo "  $0 --status     Check server status"
    echo "  $0 --local      Run locally with data/gnss_guard.db"
    echo "  $0 --local 'MSC Charlotte'  Run locally with custom asset name"
    echo "  $0 --import     Import databases from server/import/"
    echo ""
    echo "Import database format:"
    echo "  Place .db files in server/import/ with format: {id}_{name}.db"
    echo "  Example: 2_msc_charlotte.db -> Asset ID: 2, Name: 'MSC Charlotte'"
    echo ""
    echo "First-time deployment:"
    echo "  1. Setup AWS: $0 --ec2 (follow instructions)"
    echo "  2. Setup RDS: $0 --rds (follow instructions)"
    echo "  3. Create env file: cp server/env.example server/.env.prod"
    echo "  4. Edit server/.env.prod with your configuration"
    echo "  5. Edit CONFIGURATION section in this script"
    echo "  6. Run: $0"
    echo "  7. Configure DNS to point ${SERVER_DOMAIN} to your server"
    echo "  8. Run: $0 --ssl"
    echo ""
    echo "Access:"
    echo "  Before SSL: http://${SERVER_HOST}"
    echo "  After SSL:  https://${SERVER_DOMAIN}"
    echo ""
}

# Parse options
DEBUG_MODE=false
CLEAN_BUILD=false
SSL_SETUP=false
STOP_ONLY=false
RESTART_ONLY=false
STATUS_ONLY=false
LOGS_ONLY=false
LOGS_ALL=false
SHOW_RDS=false
SHOW_EC2=false
SHOW_FAIL2BAN=false
UNBAN_IP=""
START_MODE=true
LOCAL_MODE=false
LOCAL_ASSET_NAME=""
IMPORT_ONLY=false

while [[ $# -gt 0 ]]; do
    case $1 in
        --start|-s)
            START_MODE=true
            shift
            ;;
        --debug|-d)
            DEBUG_MODE=true
            START_MODE=true
            shift
            ;;
        --ssl)
            SSL_SETUP=true
            START_MODE=false
            shift
            ;;
        --clean|-c)
            CLEAN_BUILD=true
            shift
            ;;
        --stop)
            STOP_ONLY=true
            START_MODE=false
            shift
            ;;
        --restart)
            RESTART_ONLY=true
            START_MODE=false
            shift
            ;;
        --status)
            STATUS_ONLY=true
            START_MODE=false
            shift
            ;;
        --logs)
            LOGS_ONLY=true
            START_MODE=false
            shift
            ;;
        --logs-all)
            LOGS_ALL=true
            START_MODE=false
            shift
            ;;
        --fail2ban)
            SHOW_FAIL2BAN=true
            START_MODE=false
            shift
            ;;
        --import)
            IMPORT_ONLY=true
            START_MODE=false
            shift
            ;;
        --local)
            LOCAL_MODE=true
            START_MODE=false
            # Check for optional asset name
            if [[ -n "$2" && ! "$2" =~ ^-- ]]; then
                LOCAL_ASSET_NAME="$2"
                shift
            fi
            shift
            ;;
        --unban)
            if [[ -n "$2" && ! "$2" =~ ^-- ]]; then
                UNBAN_IP="$2"
                START_MODE=false
                shift 2
            else
                log_error "--unban requires an IP address"
                exit 1
            fi
            ;;
        --rds)
            SHOW_RDS=true
            START_MODE=false
            shift
            ;;
        --ec2)
            SHOW_EC2=true
            START_MODE=false
            shift
            ;;
        --help|-h)
            show_help
            exit 0
            ;;
        *)
            log_error "Unknown option: $1"
            echo "Use --help for usage information"
            exit 1
            ;;
    esac
done

# Handle info-only commands (no connection needed)
if [ "$SHOW_RDS" = "true" ]; then
    show_rds_instructions
    exit 0
fi

if [ "$SHOW_EC2" = "true" ]; then
    show_ec2_instructions
    exit 0
fi

# Test connection for all other operations
test_connection || exit 1

# Handle single operations
if [ "$STOP_ONLY" = "true" ]; then
    stop_server
    exit 0
fi

if [ "$RESTART_ONLY" = "true" ]; then
    stop_server
    build_and_start "$CLEAN_BUILD"
    exit 0
fi

if [ "$STATUS_ONLY" = "true" ]; then
    show_status
    exit 0
fi

if [ "$LOGS_ONLY" = "true" ]; then
    show_logs "true"
    exit 0
fi

if [ "$LOGS_ALL" = "true" ]; then
    log_info "Following all container logs (Ctrl+C to stop)..."
    ssh_cmd "${SERVER_USER}@${SERVER_HOST}" "cd ${REMOTE_PATH} && docker compose logs -f"
    exit 0
fi

if [ "$SHOW_FAIL2BAN" = "true" ]; then
    show_fail2ban_status
    exit 0
fi

if [ -n "$UNBAN_IP" ]; then
    unban_ip "$UNBAN_IP"
    exit 0
fi

if [ "$LOCAL_MODE" = "true" ]; then
    run_local "$LOCAL_ASSET_NAME"
    exit 0
fi

if [ "$IMPORT_ONLY" = "true" ]; then
    import_client_databases
    exit 0
fi

if [ "$SSL_SETUP" = "true" ]; then
    setup_ssl
    exit 0
fi

# Full deployment
log_info "Starting deployment to ${SERVER_USER}@${SERVER_HOST}"
log_info "Target: ${REMOTE_PATH}"

install_docker
stop_server
deploy_server_files
deploy_env_file || exit 1
build_and_start "$CLEAN_BUILD"

# Install fail2ban after containers are running (so nginx logs exist)
install_fail2ban

# Import client databases from server/import/ if any exist
import_client_databases

echo ""
log_info "Deployment completed successfully!"
echo ""
log_info "Server management commands:"
log_info "  Status:  $0 --status"
log_info "  Stop:    $0 --stop"
log_info "  Restart: $0 --restart"
log_info "  Logs:    $0 --logs"
echo ""

if [ "$DEBUG_MODE" = "true" ]; then
    log_info "Starting debug mode (following logs)..."
    log_info "Press Ctrl+C to stop"
    echo ""
    show_logs "true"
else
    log_info "GNSS Guard Server is now running!"
    echo ""
    log_info "Next steps:"
    log_info "  1. Ensure DNS is configured: ${SERVER_DOMAIN} -> ${SERVER_HOST}"
    log_info "  2. Run: $0 --ssl"
    log_info "  3. Access dashboard: https://${SERVER_DOMAIN}"
    echo ""
    log_info "Import assets:"
    log_info "  curl -X POST https://${SERVER_DOMAIN}/api/v1/admin/assets/import/batch \\"
    log_info "    -H 'Content-Type: application/json' \\"
    log_info "    -d @.configs/assets.csv"
fi


# ============================================================================
# QUICK REFERENCE COMMANDS
# ============================================================================
#
# Deploy and manage server:
#   ./deploy_server.sh              # Deploy and start (production)
#   ./deploy_server.sh --debug      # Deploy and follow logs
#   ./deploy_server.sh --clean      # Deploy with clean Docker cache
#   ./deploy_server.sh --ssl        # Setup SSL certificate
#
# Server management:
#   ./deploy_server.sh --status     # Show container status
#   ./deploy_server.sh --stop       # Stop containers
#   ./deploy_server.sh --restart    # Restart containers
#   ./deploy_server.sh --logs       # Follow server logs
#   ./deploy_server.sh --logs-all   # Follow all container logs
#
# Security (fail2ban):
#   ./deploy_server.sh --fail2ban   # Show fail2ban status and banned IPs
#   ./deploy_server.sh --unban IP   # Unban a specific IP address
#
# Local development:
#   ./deploy_server.sh --local              # Run locally with data/gnss_guard.db
#   ./deploy_server.sh --local 'My Asset'   # Run locally with custom asset name
#
# Import client databases:
#   ./deploy_server.sh --import             # Import .db files from server/import/
#   # Filename format: {id}_{name}.db (e.g., 2_msc_charlotte.db)
#
# Setup instructions:
#   ./deploy_server.sh --ec2        # EC2 setup instructions
#   ./deploy_server.sh --rds        # RDS setup instructions
#
# Direct SSH access:
#   ssh -i server/.cert/Cortex-01.pem admin@gnss.tototheo.com
#
# Docker commands on server:
#   docker compose ps               # Container status
#   docker compose logs -f          # Follow all logs
#   docker compose exec gnss-server bash  # Shell into server
#
# ============================================================================
