#!/bin/bash

# C-Relay Build and Restart Script
# Builds the project first, then stops any running relay and starts a new one in the background

echo "=== C Nostr Relay Build and Restart Script ==="

# Parse command line arguments
PRESERVE_DATABASE=false
HELP=false
USE_TEST_KEYS=false
ADMIN_KEY=""
RELAY_KEY=""
PORT_OVERRIDE=""
DEBUG_LEVEL="5"

# Key validation function
validate_hex_key() {
    local key="$1"
    local key_type="$2"
    
    if [ ${#key} -ne 64 ]; then
        echo "ERROR: $key_type key must be exactly 64 characters"
        return 1
    fi
    
    if ! [[ "$key" =~ ^[0-9a-fA-F]{64}$ ]]; then
        echo "ERROR: $key_type key must contain only hex characters (0-9, a-f, A-F)"
        return 1
    fi
    
    return 0
}

while [[ $# -gt 0 ]]; do
    case $1 in
        -a|--admin-key)
            if [ -z "$2" ]; then
                echo "ERROR: Admin key option requires a value"
                HELP=true
                shift
            else
                ADMIN_KEY="$2"
                shift 2
            fi
            ;;
        -r|--relay-key)
            if [ -z "$2" ]; then
                echo "ERROR: Relay key option requires a value"
                HELP=true
                shift
            else
                RELAY_KEY="$2"
                shift 2
            fi
            ;;
        -p|--port)
            if [ -z "$2" ]; then
                echo "ERROR: Port option requires a value"
                HELP=true
                shift
            else
                PORT_OVERRIDE="$2"
                shift 2
            fi
            ;;
        -d|--preserve-database)
            PRESERVE_DATABASE=true
            shift
            ;;
        --test-keys|-t)
            USE_TEST_KEYS=true
            shift
            ;;
        --debug-level=*)
            DEBUG_LEVEL="${1#*=}"
            shift
            ;;
        -d=*)
            DEBUG_LEVEL="${1#*=}"
            shift
            ;;
        --debug-level)
            if [ -z "$2" ]; then
                echo "ERROR: Debug level option requires a value"
                HELP=true
                shift
            else
                DEBUG_LEVEL="$2"
                shift 2
            fi
            ;;
        -d)
            if [ -z "$2" ]; then
                echo "ERROR: Debug level option requires a value"
                HELP=true
                shift
            else
                DEBUG_LEVEL="$2"
                shift 2
            fi
            ;;
        --help|-h)
            HELP=true
            shift
            ;;
        *)
            echo "Unknown option: $1"
            HELP=true
            shift
            ;;
    esac
done

# Validate custom keys if provided
if [ -n "$ADMIN_KEY" ]; then
    if ! validate_hex_key "$ADMIN_KEY" "Admin"; then
        exit 1
    fi
fi

if [ -n "$RELAY_KEY" ]; then
    if ! validate_hex_key "$RELAY_KEY" "Relay"; then
        exit 1
    fi
fi

# Validate port if provided
if [ -n "$PORT_OVERRIDE" ]; then
    if ! [[ "$PORT_OVERRIDE" =~ ^[0-9]+$ ]] || [ "$PORT_OVERRIDE" -lt 1 ] || [ "$PORT_OVERRIDE" -gt 65535 ]; then
        echo "ERROR: Port must be a number between 1 and 65535"
        exit 1
    fi
fi

# Validate strict port flag (only makes sense with port override)
if [ "$USE_TEST_KEYS" = true ] && [ -z "$PORT_OVERRIDE" ]; then
    echo "WARNING: --strict-port is always used with test keys. Consider specifying a custom port with -p."
fi

# Validate debug level if provided
if [ -n "$DEBUG_LEVEL" ]; then
    if ! [[ "$DEBUG_LEVEL" =~ ^[0-5]$ ]]; then
        echo "ERROR: Debug level must be 0-5, got: $DEBUG_LEVEL"
        exit 1
    fi
fi

# Show help
if [ "$HELP" = true ]; then
    echo "Usage: $0 [OPTIONS]"
    echo ""
    echo "Options:"
    echo "  -a, --admin-key <hex>    64-character hex admin private key"
    echo "  -r, --relay-key <hex>    64-character hex relay private key"
    echo "  -p, --port <port>        Custom port override (default: 8888)"
    echo "  -d, --debug-level <0-5>  Set debug level: 0=none, 1=errors, 2=warnings, 3=info, 4=debug, 5=trace"
    echo "  --preserve-database      Keep existing database files (don't delete for fresh start)"
    echo "  --test-keys, -t          Use deterministic test keys for development (admin: all 'a's, relay: all '1's)"
    echo "  --help, -h               Show this help message"
    echo ""
    echo "Event-Based Configuration:"
    echo "  This relay now uses event-based configuration stored directly in the database."
    echo "  On first startup, keys are automatically generated and printed once."
    echo "  Database file: <relay_pubkey>.db (created automatically)"
    echo ""
    echo "Examples:"
    echo "  $0                                    # Fresh start with random keys"
    echo "  $0 -a <admin-hex> -r <relay-hex>     # Use custom keys"
    echo "  $0 -a <admin-hex> -p 9000            # Custom admin key on port 9000"
    echo "  $0 -p 7777 --strict-port             # Fail if port 7777 unavailable (no fallback)"
    echo "  $0 -p 8080 --strict-port -d=3        # Custom port with strict binding and debug"
    echo "  $0 --debug-level=3                   # Start with debug level 3 (info)"
    echo "  $0 -d=5                              # Start with debug level 5 (trace)"
    echo "  $0 --preserve-database               # Preserve existing database and keys"
    echo "  $0 --test-keys                       # Use test keys for consistent development"
    echo "  $0 -t --preserve-database            # Use test keys and preserve database"
    echo ""
    echo "Key Format: Keys must be exactly 64 hexadecimal characters (0-9, a-f, A-F)"
    echo "Default behavior: Deletes existing database files to start fresh with new keys"
    echo "                 for development purposes"
    exit 0
fi

# Handle database file cleanup for fresh start
if [ "$PRESERVE_DATABASE" = false ]; then
    if ls *.db* >/dev/null 2>&1 || ls build/*.db* >/dev/null 2>&1; then
        echo "Removing existing database files (including WAL/SHM) to trigger fresh key generation..."
        rm -f *.db* build/*.db*
        echo "✓ Database files removed - will generate new keys and database"
    else
        echo "No existing database found - will generate fresh setup"
    fi
else
    echo "Preserving existing database files (build process does not touch database files)"
fi

# Clean up legacy files that are no longer used
rm -rf dev-config/ 2>/dev/null
rm -f db/c_nostr_relay.db* 2>/dev/null

# Embed web files into C headers before building
echo "Embedding web files..."
./embed_web_files.sh

# Build the project - ONLY static build
echo "Building project (static binary with SQLite JSON1 extension)..."
./build_static.sh

# Exit if static build fails - no fallback
if [ $? -ne 0 ]; then
    echo "ERROR: Static build failed. Cannot proceed without static binary."
    echo "Please fix the build errors and try again."
    exit 1
fi

# Check if build was successful
if [ $? -ne 0 ]; then
    echo "ERROR: Build failed. Cannot restart relay."
    exit 1
fi

# Check if static relay binary exists after build - ONLY use static binary
ARCH=$(uname -m)
case "$ARCH" in
    x86_64)
        BINARY_PATH="./build/c_relay_static_x86_64"
        ;;
    aarch64|arm64)
        BINARY_PATH="./build/c_relay_static_arm64"
        ;;
    *)
        BINARY_PATH="./build/c_relay_static_$ARCH"
        ;;
esac

# Verify static binary exists - no fallbacks
if [ ! -f "$BINARY_PATH" ]; then
    echo "ERROR: Static relay binary not found: $BINARY_PATH"
    echo ""
    echo "The relay requires the static binary with JSON1 support."
    echo "Please run: ./build_static.sh"
    echo ""
    exit 1
fi

echo "Using static binary: $BINARY_PATH"

echo "Build successful. Proceeding with relay restart..."

# Kill existing relay if running - start aggressive immediately
echo "Stopping any existing relay servers..."

# Get all relay processes and kill them immediately with -9
RELAY_PIDS=$(pgrep -f "c_relay_" || echo "")
if [ -n "$RELAY_PIDS" ]; then
    echo "Force killing relay processes immediately: $RELAY_PIDS"
    kill -9 $RELAY_PIDS 2>/dev/null
else
    echo "No existing relay processes found"
fi

# Ensure port 8888 is completely free with retry loop
echo "Ensuring port 8888 is available..."
for attempt in {1..15}; do
    if ! lsof -i :8888 >/dev/null 2>&1; then
        echo "Port 8888 is now free"
        break
    fi
    
    echo "Attempt $attempt: Port 8888 still in use, force killing..."
    # Kill anything using port 8888
    fuser -k 8888/tcp 2>/dev/null || true
    
    # Double-check for any remaining relay processes
    REMAINING_PIDS=$(pgrep -f "c_relay_" || echo "")
    if [ -n "$REMAINING_PIDS" ]; then
        echo "Killing remaining relay processes: $REMAINING_PIDS"
        kill -9 $REMAINING_PIDS 2>/dev/null || true
    fi
    
    sleep 2
    
    if [ $attempt -eq 15 ]; then
        echo "ERROR: Could not free port 8888 after 15 attempts"
        echo "Current processes using port:"
        lsof -i :8888 2>/dev/null || echo "No process details available"
        echo "You may need to manually kill processes or reboot"
        exit 1
    fi
done

# Final safety check - ensure no relay processes remain
FINAL_PIDS=$(pgrep -f "c_relay_" || echo "")
if [ -n "$FINAL_PIDS" ]; then
    echo "Final cleanup: killing processes $FINAL_PIDS"
    kill -9 $FINAL_PIDS 2>/dev/null || true
    sleep 1
fi

# Clean up PID file
rm -f relay.pid

# Database initialization is now handled automatically by the relay
# with event-based configuration system
echo "Database will be initialized automatically on startup if needed"

# Start relay in background with output redirection
echo "Starting relay server..."
echo "Debug: Current processes: $(ps aux | grep 'c_relay_' | grep -v grep || echo 'None')"

# Build command line arguments for relay binary
RELAY_ARGS=""

if [ -n "$ADMIN_KEY" ]; then
    RELAY_ARGS="$RELAY_ARGS -a $ADMIN_KEY"
    echo "Using custom admin key: ${ADMIN_KEY:0:16}..."
fi

if [ -n "$RELAY_KEY" ]; then
    RELAY_ARGS="$RELAY_ARGS -r $RELAY_KEY"
    echo "Using custom relay key: ${RELAY_KEY:0:16}..."
fi

if [ -n "$PORT_OVERRIDE" ]; then
    RELAY_ARGS="$RELAY_ARGS -p $PORT_OVERRIDE"
    echo "Using custom port: $PORT_OVERRIDE"
fi

if [ -n "$DEBUG_LEVEL" ]; then
    RELAY_ARGS="$RELAY_ARGS --debug-level=$DEBUG_LEVEL"
    echo "Using debug level: $DEBUG_LEVEL"
fi

# Change to build directory before starting relay so database files are created there
cd build
# Start relay in background and capture its PID
if [ "$USE_TEST_KEYS" = true ]; then
    echo "Using deterministic test keys for development..."
    ./$(basename $BINARY_PATH) -a 6a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3 -r 1111111111111111111111111111111111111111111111111111111111111111 --debug-level=$DEBUG_LEVEL --strict-port > ../relay.log 2>&1 &
elif [ -n "$RELAY_ARGS" ]; then
    echo "Starting relay with custom configuration..."
    ./$(basename $BINARY_PATH) $RELAY_ARGS --debug-level=$DEBUG_LEVEL --strict-port > ../relay.log 2>&1 &
else
    # No command line arguments needed for random key generation
    echo "Starting relay with random key generation..."
    ./$(basename $BINARY_PATH) --debug-level=$DEBUG_LEVEL --strict-port > ../relay.log 2>&1 &
fi
RELAY_PID=$!
# Change back to original directory
cd ..

echo "Started with PID: $RELAY_PID"

# Check if server is still running after short delay
sleep 3

# Check if process is still alive
if ps -p "$RELAY_PID" >/dev/null 2>&1; then
    echo "Relay started successfully!"
    echo "PID: $RELAY_PID"
    
    # Wait for relay to fully initialize and detect the actual port it's using
    sleep 2
    
    # Extract actual port from relay logs
    ACTUAL_PORT=""
    if [ -f relay.log ]; then
        # Look for the success message with actual port
        ACTUAL_PORT=$(grep "WebSocket relay started on ws://127.0.0.1:" relay.log 2>/dev/null | tail -1 | sed -n 's/.*ws:\/\/127\.0\.0\.1:\([0-9]*\).*/\1/p')
        
        # If we couldn't find the port in logs, try to detect from netstat
        if [ -z "$ACTUAL_PORT" ]; then
            ACTUAL_PORT=$(netstat -tln 2>/dev/null | grep -E ":888[0-9]" | head -1 | sed -n 's/.*:\([0-9]*\).*/\1/p')
        fi
    fi
    
    # Display the actual endpoint
    if [ -n "$ACTUAL_PORT" ]; then
        if [ "$ACTUAL_PORT" = "8888" ]; then
            echo "WebSocket endpoint: ws://127.0.0.1:$ACTUAL_PORT"
        else
            echo "WebSocket endpoint: ws://127.0.0.1:$ACTUAL_PORT (fell back from port 8888)"
        fi
    else
        echo "WebSocket endpoint: ws://127.0.0.1:8888 (port detection failed - check logs)"
    fi
    
    echo "HTTP endpoint: http://127.0.0.1:${ACTUAL_PORT:-8888}"
    echo "Log file: relay.log"
    echo ""

    # Save PID for debugging
    echo $RELAY_PID > relay.pid

    # Check if new keys were generated and display them
    sleep 1  # Give relay time to write initial logs
    if grep -q "IMPORTANT: SAVE THIS ADMIN PRIVATE KEY SECURELY!" relay.log 2>/dev/null; then
        echo "=== IMPORTANT: NEW ADMIN PRIVATE KEY GENERATED ==="
        echo ""
        # Extract and display the admin private key section from the log
        grep -A 15 -B 2 "IMPORTANT: SAVE THIS ADMIN PRIVATE KEY SECURELY!" relay.log | head -n 20
        echo ""
        echo "⚠️  SAVE THIS ADMIN PRIVATE KEY SECURELY - IT CONTROLS YOUR RELAY CONFIGURATION!"
        echo "⚠️  This key is needed to update configuration and is only displayed once"
        echo "⚠️  The relay and database information is also logged in relay.log for reference"
        echo ""
    fi

    echo "=== Event-Based Relay Server Running ==="
    echo "Configuration: Event-based (kind 33334 Nostr events)"
    echo "Database: Automatically created with relay pubkey naming"
    echo "To kill relay: pkill -f 'c_relay_'"
    echo "To check status: ps aux | grep c_relay_"
    echo "To view logs: tail -f relay.log"
    echo "Binary: $BINARY_PATH (zero configuration needed)"
    echo "Ready for Nostr client connections!"
else
    echo "ERROR: Relay failed to start"
    echo "Debug: Check relay.log for error details:"
    echo "--- Last 10 lines of relay.log ---"
    tail -n 10 relay.log 2>/dev/null || echo "No log file found"
    echo "--- End log ---"
    exit 1
fi

echo ""