#!/usr/bin/env bash
# NebulaSSH Linux Agent
# Connects to the NebulaSSH relay server and executes remote commands.
# Usage: nebulassh-agent [--relay URL] [--shell bash|sh|zsh] [--interval N]

set -euo pipefail

VERSION="1.0.0"
CONFIG_DIR="${HOME}/.config/nebulassh"
CONFIG_FILE="${CONFIG_DIR}/agent.conf"
LOG_FILE="${CONFIG_DIR}/agent.log"
PID_FILE="${CONFIG_DIR}/agent.pid"

# Defaults
RELAY_URL=""
AGENT_ID=""
AGENT_TOKEN=""
# One-time enrollment token (required the first time this machine enrolls).
# Provide via env NEBULASSH_ENROLL_TOKEN or --enroll-token. Ignored on reconnect.
ENROLL_TOKEN="${NEBULASSH_ENROLL_TOKEN:-}"
SHELL_TYPE="bash"
POLL_INTERVAL=2
CMD_TIMEOUT=120
RUNNING=true
REGISTERED=false
MAX_LOG_SIZE=1048576  # 1MB

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

# ─── Logging ───
log() {
    local level="$1"; shift
    local msg="$*"
    local ts
    ts=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$ts] [$level] $msg" >> "$LOG_FILE" 2>/dev/null
    case "$level" in
        INFO)  echo -e "${CYAN}[$ts]${NC} ${GREEN}[INFO]${NC} $msg" ;;
        WARN)  echo -e "${CYAN}[$ts]${NC} ${YELLOW}[WARN]${NC} $msg" ;;
        ERROR) echo -e "${CYAN}[$ts]${NC} ${RED}[ERROR]${NC} $msg" ;;
    esac
}

rotate_log() {
    if [[ -f "$LOG_FILE" ]] && [[ $(stat -f%z "$LOG_FILE" 2>/dev/null || stat -c%s "$LOG_FILE" 2>/dev/null) -gt $MAX_LOG_SIZE ]]; then
        mv "$LOG_FILE" "${LOG_FILE}.old"
    fi
}

# ─── Hardware ID Generation ───
generate_agent_id() {
    local machine_id=""
    local hostname=""
    local username=""

    # Get machine ID (Linux)
    if [[ -f /etc/machine-id ]]; then
        machine_id=$(cat /etc/machine-id)
    elif [[ -f /var/lib/dbus/machine-id ]]; then
        machine_id=$(cat /var/lib/dbus/machine-id)
    else
        machine_id=$(hostname | sha256sum | awk '{print $1}')
    fi

    hostname=$(hostname 2>/dev/null || echo "linux")
    username=$(whoami 2>/dev/null || echo "user")

    local fingerprint="${hostname}|${machine_id}|${username}"
    local hash
    hash=$(echo -n "$fingerprint" | sha256sum | awk '{print $1}')

    # Convert first 12 hex chars to digits (XXX-XXX-XXX-XXX format, matches Windows agent)
    local digits=""
    for i in $(seq 0 11); do
        local hex_char="${hash:$i:1}"
        local dec_val=$((16#$hex_char % 10))
        digits="${digits}${dec_val}"
    done

    echo "${digits:0:3}-${digits:3:3}-${digits:6:3}-${digits:9:3}"
}

# ─── Configuration ───
load_config() {
    mkdir -p "$CONFIG_DIR"

    if [[ -f "$CONFIG_FILE" ]]; then
        while IFS='=' read -r key value; do
            key=$(echo "$key" | xargs)
            value=$(echo "$value" | xargs)
            case "$key" in
                relay_url)     [[ -z "$RELAY_URL" ]] && RELAY_URL="$value" ;;
                agent_id)      AGENT_ID="$value" ;;
                shell)         [[ "$SHELL_TYPE" == "bash" ]] && SHELL_TYPE="$value" ;;
                poll_interval) POLL_INTERVAL="$value" ;;
            esac
        done < "$CONFIG_FILE"
    fi

    # Generate agent ID if not set
    if [[ -z "$AGENT_ID" ]]; then
        AGENT_ID=$(generate_agent_id)
    fi
}

save_config() {
    mkdir -p "$CONFIG_DIR"
    cat > "$CONFIG_FILE" <<EOF
relay_url=$RELAY_URL
agent_id=$AGENT_ID
shell=$SHELL_TYPE
poll_interval=$POLL_INTERVAL
EOF
}

# ─── HTTP Helpers ───
http_post() {
    local url="$1"
    local data="$2"
    local auth="${3:-false}"
    local extra_args=()

    if [[ "$auth" == "true" ]] && [[ -n "$AGENT_TOKEN" ]]; then
        extra_args+=(-H "X-Agent-Id: $AGENT_ID" -H "X-Agent-Token: $AGENT_TOKEN")
    fi

    curl -s -k --max-time 15 \
        -X POST \
        -H "Content-Type: application/json" \
        "${extra_args[@]}" \
        -d "$data" \
        "${RELAY_URL}${url}" 2>/dev/null
}

http_get() {
    local url="$1"
    local auth="${2:-false}"
    local extra_args=()

    if [[ "$auth" == "true" ]] && [[ -n "$AGENT_TOKEN" ]]; then
        extra_args+=(-H "X-Agent-Id: $AGENT_ID" -H "X-Agent-Token: $AGENT_TOKEN")
    fi

    curl -s -k --max-time 15 \
        "${extra_args[@]}" \
        "${RELAY_URL}${url}" 2>/dev/null
}

http_post_file() {
    local url="$1"
    local file_path="$2"

    curl -s -k --max-time 300 \
        -X POST \
        -H "X-Agent-Id: $AGENT_ID" \
        -H "X-Agent-Token: $AGENT_TOKEN" \
        -F "file=@${file_path}" \
        "${RELAY_URL}${url}" 2>/dev/null
}

http_download() {
    local url="$1"
    local output="$2"

    curl -s -k --max-time 300 \
        -H "X-Agent-Id: $AGENT_ID" \
        -H "X-Agent-Token: $AGENT_TOKEN" \
        -o "$output" \
        "${RELAY_URL}${url}" 2>/dev/null
}

# ─── JSON Helpers (minimal, no jq dependency) ───
json_val() {
    local json="$1"
    local key="$2"
    # Try python3 first, then python, then basic grep
    if command -v python3 &>/dev/null; then
        echo "$json" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$key',''))" 2>/dev/null
    elif command -v python &>/dev/null; then
        echo "$json" | python -c "import sys,json; d=json.load(sys.stdin); print(d.get('$key',''))" 2>/dev/null
    else
        echo "$json" | grep -o "\"$key\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" | head -1 | sed 's/.*: *"//;s/"$//'
    fi
}

json_array() {
    local json="$1"
    local key="$2"
    if command -v python3 &>/dev/null; then
        echo "$json" | python3 -c "
import sys, json
d = json.load(sys.stdin)
arr = d.get('$key', [])
for item in arr:
    print(json.dumps(item))
" 2>/dev/null
    elif command -v python &>/dev/null; then
        echo "$json" | python -c "
import sys, json
d = json.load(sys.stdin)
arr = d.get('$key', [])
for item in arr:
    print(json.dumps(item))
" 2>/dev/null
    fi
}

json_bool() {
    local json="$1"
    local key="$2"
    if command -v python3 &>/dev/null; then
        echo "$json" | python3 -c "import sys,json; d=json.load(sys.stdin); print(str(d.get('$key',False)).lower())" 2>/dev/null
    else
        echo "$json" | grep -o "\"$key\"[[:space:]]*:[[:space:]]*true" | head -1 | grep -q true && echo "true" || echo "false"
    fi
}

# ─── Agent Registration ───
register_agent() {
    local os_version
    os_version=$(uname -srm 2>/dev/null || echo "Linux")
    local machine_name
    machine_name=$(hostname 2>/dev/null || echo "linux")
    local username
    username=$(whoami 2>/dev/null || echo "user")

    log INFO "Registering agent ${AGENT_ID} with relay ${RELAY_URL}..."

    local payload
    payload=$(python3 -c "
import json
print(json.dumps({
    'AgentId': '$AGENT_ID',
    'MachineName': '$machine_name',
    'OsVersion': '$os_version',
    'Username': '$username',
    'EnrollToken': '$ENROLL_TOKEN'
}))
" 2>/dev/null || echo "{\"AgentId\":\"$AGENT_ID\",\"MachineName\":\"$machine_name\",\"OsVersion\":\"$os_version\",\"Username\":\"$username\",\"EnrollToken\":\"$ENROLL_TOKEN\"}")

    local response
    response=$(http_post "/api/connector/register" "$payload" "false")

    if [[ -z "$response" ]]; then
        log ERROR "No response from relay server"
        return 1
    fi

    local token
    token=$(json_val "$response" "token")

    if [[ -z "$token" ]]; then
        if [[ "$response" == *"Enrollment required"* ]]; then
            log ERROR "Enrollment required: this machine is not registered yet."
            log ERROR "Generate a one-time enrollment token in your NebulaSSH dashboard"
            log ERROR "(Agents & Connector), then run with:"
            log ERROR "    NEBULASSH_ENROLL_TOKEN=<token> $0 --relay $RELAY_URL"
        else
            log ERROR "Registration failed - no token received"
            log ERROR "Response: $response"
        fi
        return 1
    fi

    AGENT_TOKEN="$token"
    REGISTERED=true
    log INFO "Registration successful!"
    log INFO "Agent ID:  $AGENT_ID"
    log INFO "Machine:   $machine_name"
    log INFO "OS:        $os_version"
    log INFO "User:      $username"
    return 0
}

# ─── Command Execution ───
execute_command() {
    local cmd="$1"
    local shell="$2"
    local cmd_timeout="${CMD_TIMEOUT}"

    local shell_bin
    case "$shell" in
        bash)       shell_bin="bash" ;;
        sh)         shell_bin="sh" ;;
        zsh)        shell_bin="zsh" ;;
        powershell) shell_bin="pwsh" ;;
        *)          shell_bin="$SHELL_TYPE" ;;
    esac

    local tmpout
    tmpout=$(mktemp /tmp/nebula_out.XXXXXX)
    local tmperr
    tmperr=$(mktemp /tmp/nebula_err.XXXXXX)
    local tmpcode
    tmpcode=$(mktemp /tmp/nebula_code.XXXXXX)

    # Execute with timeout
    timeout "$cmd_timeout" "$shell_bin" -c "$cmd" > "$tmpout" 2> "$tmperr"
    echo $? > "$tmpcode"

    local exit_code
    exit_code=$(cat "$tmpcode" 2>/dev/null || echo "1")

    # If timeout killed it, exit code is 124
    if [[ "$exit_code" -eq 124 ]]; then
        echo "Command timed out after ${cmd_timeout}s" >> "$tmperr"
    fi

    # Write results to separate marker files for clean parsing
    local result_file
    result_file=$(mktemp /tmp/nebula_result.XXXXXX)
    echo "EXIT_CODE:${exit_code}" > "$result_file"
    echo "STDOUT_START" >> "$result_file"
    cat "$tmpout" >> "$result_file" 2>/dev/null
    echo "" >> "$result_file"
    echo "STDOUT_END" >> "$result_file"
    echo "STDERR_START" >> "$result_file"
    cat "$tmperr" >> "$result_file" 2>/dev/null
    echo "" >> "$result_file"
    echo "STDERR_END" >> "$result_file"

    cat "$result_file"
    rm -f "$tmpout" "$tmperr" "$tmpcode" "$result_file"
}

submit_result() {
    local cmd_id="$1"
    local exit_code="$2"
    local stdout="$3"
    local stderr="$4"

    local payload
    payload=$(python3 -c "
import json, sys
print(json.dumps({
    'CommandId': sys.argv[1],
    'Output': sys.argv[2],
    'Error': sys.argv[3],
    'ExitCode': int(sys.argv[4])
}))
" "$cmd_id" "$stdout" "$stderr" "$exit_code" 2>/dev/null)

    if [[ -z "$payload" ]]; then
        # Fallback without python
        local escaped_out
        escaped_out=$(echo "$stdout" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g' | tr '\n' '\n' | sed ':a;N;$!ba;s/\n/\\n/g')
        local escaped_err
        escaped_err=$(echo "$stderr" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g' | tr '\n' '\n' | sed ':a;N;$!ba;s/\n/\\n/g')
        payload="{\"CommandId\":\"$cmd_id\",\"Output\":\"$escaped_out\",\"Error\":\"$escaped_err\",\"ExitCode\":$exit_code}"
    fi

    http_post "/api/connector/result" "$payload" "true" >/dev/null 2>&1
}

# ─── Polling Loops ───
poll_commands() {
    local response
    response=$(http_post "/api/connector/heartbeat" "{}" "true")

    if [[ -z "$response" ]]; then
        return 1
    fi

    local ok
    ok=$(json_bool "$response" "ok")

    if [[ "$ok" != "true" ]]; then
        return 1
    fi

    # Parse commands array
    local commands
    commands=$(json_array "$response" "commands")

    if [[ -z "$commands" ]]; then
        return 0
    fi

    while IFS= read -r cmd_json; do
        [[ -z "$cmd_json" ]] && continue

        local cmd_id
        cmd_id=$(json_val "$cmd_json" "commandId")
        local command
        command=$(json_val "$cmd_json" "command")
        local shell
        shell=$(json_val "$cmd_json" "shell")

        if [[ -z "$cmd_id" ]] || [[ -z "$command" ]]; then
            continue
        fi

        log INFO "Executing command [$cmd_id]: $command (shell: ${shell:-$SHELL_TYPE})"

        # Execute in background to not block polling
        (
            local result
            result=$(execute_command "$command" "${shell:-$SHELL_TYPE}")

            local exit_code
            exit_code=$(echo "$result" | grep "^EXIT_CODE:" | head -1 | cut -d: -f2)
            local stdout
            stdout=$(echo "$result" | sed -n '/^STDOUT_START$/,/^STDOUT_END$/p' | sed '1d;$d' | sed '/^$/d')
            local stderr
            stderr=$(echo "$result" | sed -n '/^STDERR_START$/,/^STDERR_END$/p' | sed '1d;$d' | sed '/^$/d')

            log INFO "Command [$cmd_id] completed (exit: ${exit_code:-0})"
            submit_result "$cmd_id" "${exit_code:-0}" "$stdout" "$stderr"
        ) &
    done <<< "$commands"
}

poll_transfers() {
    local response
    response=$(http_get "/api/connector/transfers" "true")

    if [[ -z "$response" ]]; then
        return 1
    fi

    local transfers
    transfers=$(json_array "$response" "transfers")

    if [[ -z "$transfers" ]]; then
        return 0
    fi

    while IFS= read -r xfer_json; do
        [[ -z "$xfer_json" ]] && continue

        local xfer_id
        xfer_id=$(json_val "$xfer_json" "transferId")
        local xfer_type
        xfer_type=$(json_val "$xfer_json" "type")
        local remote_path
        remote_path=$(json_val "$xfer_json" "remotePath")
        local file_name
        file_name=$(json_val "$xfer_json" "fileName")

        if [[ -z "$xfer_id" ]]; then
            continue
        fi

        log INFO "Processing ${xfer_type} transfer [$xfer_id]: $remote_path"

        (
            if [[ "$xfer_type" == "upload" ]]; then
                handle_upload "$xfer_id" "$remote_path" "$file_name"
            elif [[ "$xfer_type" == "download" ]]; then
                handle_download "$xfer_id" "$remote_path" "$file_name"
            fi
        ) &
    done <<< "$transfers"
}

# ─── File Transfer Handlers ───
handle_upload() {
    local xfer_id="$1"
    local remote_path="$2"
    local file_name="$3"

    local tmp_file
    tmp_file=$(mktemp /tmp/nebula_upload.XXXXXX)

    # Download file data from relay
    http_download "/api/connector/transfer/${xfer_id}/data" "$tmp_file"

    if [[ ! -s "$tmp_file" ]]; then
        complete_transfer "$xfer_id" "false" "Failed to download file data from relay"
        rm -f "$tmp_file"
        return 1
    fi

    # Ensure target directory exists
    local target_dir
    target_dir=$(dirname "$remote_path")
    mkdir -p "$target_dir" 2>/dev/null

    # Move file to target
    if mv "$tmp_file" "$remote_path" 2>/dev/null; then
        log INFO "Upload complete: $remote_path"
        complete_transfer "$xfer_id" "true" ""
    else
        # Try with sudo if permission denied
        if sudo mv "$tmp_file" "$remote_path" 2>/dev/null; then
            log INFO "Upload complete (sudo): $remote_path"
            complete_transfer "$xfer_id" "true" ""
        else
            log ERROR "Upload failed: $remote_path"
            complete_transfer "$xfer_id" "false" "Failed to write file to $remote_path"
            rm -f "$tmp_file"
        fi
    fi
}

handle_download() {
    local xfer_id="$1"
    local remote_path="$2"
    local file_name="$3"

    if [[ ! -f "$remote_path" ]]; then
        log ERROR "Download failed: File not found: $remote_path"
        complete_transfer "$xfer_id" "false" "File not found: $remote_path"
        return 1
    fi

    # Upload file to relay
    local response
    response=$(http_post_file "/api/connector/transfer/${xfer_id}/data" "$remote_path")

    if [[ -n "$response" ]]; then
        log INFO "Download complete: $remote_path"
        complete_transfer "$xfer_id" "true" ""
    else
        log ERROR "Download failed: Could not upload to relay"
        complete_transfer "$xfer_id" "false" "Failed to upload file to relay"
    fi
}

complete_transfer() {
    local xfer_id="$1"
    local success="$2"
    local error_msg="$3"

    local payload
    payload="{\"TransferId\":\"$xfer_id\",\"Success\":$success,\"ErrorMessage\":\"$error_msg\"}"

    http_post "/api/connector/transfer/${xfer_id}/complete" "$payload" "true" >/dev/null 2>&1
}

# ─── Disconnect ───
disconnect_agent() {
    if [[ "$REGISTERED" == "true" ]] && [[ -n "$AGENT_TOKEN" ]]; then
        log INFO "Disconnecting from relay..."
        http_post "/api/connector/disconnect" "{}" "true" >/dev/null 2>&1
        REGISTERED=false
        AGENT_TOKEN=""
    fi
}

# ─── Signal Handlers ───
cleanup() {
    RUNNING=false
    log INFO "Shutting down..."
    disconnect_agent
    rm -f "$PID_FILE"
    # Kill child processes
    jobs -p 2>/dev/null | xargs -r kill 2>/dev/null
    log INFO "Agent stopped."
    exit 0
}

trap cleanup SIGINT SIGTERM SIGHUP

# ─── Main Loop ───
main_loop() {
    local fail_count=0
    local max_fails=30

    while $RUNNING; do
        # Register if not registered
        if [[ "$REGISTERED" != "true" ]]; then
            if register_agent; then
                fail_count=0
            else
                fail_count=$((fail_count + 1))
                local wait_time=$((POLL_INTERVAL * (fail_count > 10 ? 5 : 1)))
                if [[ $fail_count -ge $max_fails ]]; then
                    log ERROR "Failed to register after $max_fails attempts. Retrying with backoff..."
                    wait_time=30
                fi
                sleep "$wait_time"
                continue
            fi
        fi

        # Poll for commands
        if ! poll_commands; then
            fail_count=$((fail_count + 1))
            if [[ $fail_count -ge 5 ]]; then
                log WARN "Lost connection to relay (${fail_count} failures). Re-registering..."
                REGISTERED=false
                AGENT_TOKEN=""
                fail_count=0
                sleep "$POLL_INTERVAL"
                continue
            fi
        else
            fail_count=0
        fi

        # Poll for file transfers
        poll_transfers 2>/dev/null

        # Rotate log if needed
        rotate_log

        sleep "$POLL_INTERVAL"
    done
}

# ─── Usage ───
usage() {
    echo -e "${CYAN}NebulaSSH Linux Agent v${VERSION}${NC}"
    echo ""
    echo "Usage: $0 [OPTIONS]"
    echo ""
    echo "Options:"
    echo "  --relay URL        Relay server URL (required on first run)"
    echo "  --shell SHELL      Default shell: bash, sh, zsh (default: bash)"
    echo "  --interval N       Poll interval in seconds (default: 2)"
    echo "  --daemon           Run as background daemon"
    echo "  --stop             Stop running agent"
    echo "  --status           Show agent status"
    echo "  --id               Show agent ID"
    echo "  --help             Show this help"
    echo ""
    echo "Examples:"
    echo "  $0 --relay https://app.nebulassh.com"
    echo "  $0 --relay https://app.nebulassh.com --daemon"
    echo "  $0 --stop"
}

show_status() {
    load_config
    echo -e "${CYAN}NebulaSSH Linux Agent v${VERSION}${NC}"
    echo -e "Agent ID:       ${GREEN}${AGENT_ID}${NC}"
    echo -e "Relay URL:      ${RELAY_URL:-${RED}not set${NC}}"
    echo -e "Shell:          $SHELL_TYPE"
    echo -e "Poll Interval:  ${POLL_INTERVAL}s"
    echo -e "Config:         $CONFIG_FILE"
    echo -e "Log:            $LOG_FILE"

    if [[ -f "$PID_FILE" ]]; then
        local pid
        pid=$(cat "$PID_FILE")
        if kill -0 "$pid" 2>/dev/null; then
            echo -e "Status:         ${GREEN}Running (PID $pid)${NC}"
        else
            echo -e "Status:         ${RED}Stopped (stale PID file)${NC}"
            rm -f "$PID_FILE"
        fi
    else
        echo -e "Status:         ${YELLOW}Not running${NC}"
    fi
}

stop_agent() {
    if [[ -f "$PID_FILE" ]]; then
        local pid
        pid=$(cat "$PID_FILE")
        if kill -0 "$pid" 2>/dev/null; then
            echo -e "${YELLOW}Stopping agent (PID $pid)...${NC}"
            kill "$pid" 2>/dev/null
            sleep 2
            if kill -0 "$pid" 2>/dev/null; then
                kill -9 "$pid" 2>/dev/null
            fi
            rm -f "$PID_FILE"
            echo -e "${GREEN}Agent stopped.${NC}"
        else
            echo -e "${YELLOW}Agent not running (stale PID file).${NC}"
            rm -f "$PID_FILE"
        fi
    else
        echo -e "${YELLOW}No agent running.${NC}"
    fi
}

# ─── Entry Point ───
DAEMON=false

while [[ $# -gt 0 ]]; do
    case "$1" in
        --relay)    RELAY_URL="$2"; shift 2 ;;
        --enroll-token) ENROLL_TOKEN="$2"; shift 2 ;;
        --shell)    SHELL_TYPE="$2"; shift 2 ;;
        --interval) POLL_INTERVAL="$2"; shift 2 ;;
        --daemon)   DAEMON=true; shift ;;
        --stop)     load_config; stop_agent; exit 0 ;;
        --status)   show_status; exit 0 ;;
        --id)       load_config; echo "$AGENT_ID"; exit 0 ;;
        --help|-h)  usage; exit 0 ;;
        *)          echo "Unknown option: $1"; usage; exit 1 ;;
    esac
done

load_config

# Default relay URL (NebulaSSH cloud) when none given via --relay or saved config
if [[ -z "$RELAY_URL" ]]; then
    RELAY_URL="https://app.nebulassh.com"
fi

save_config

# Check dependencies
for cmd in curl; do
    if ! command -v "$cmd" &>/dev/null; then
        echo -e "${RED}Error: '$cmd' is required but not installed.${NC}"
        exit 1
    fi
done

if ! command -v python3 &>/dev/null && ! command -v python &>/dev/null; then
    echo -e "${YELLOW}Warning: python3 not found. JSON handling may be limited.${NC}"
fi

# Check for existing instance (skip if we ARE the daemon child)
if [[ -f "$PID_FILE" ]]; then
    existing_pid=$(cat "$PID_FILE")
    if [[ "$existing_pid" != "$$" ]] && kill -0 "$existing_pid" 2>/dev/null; then
        echo -e "${YELLOW}Agent already running (PID $existing_pid). Use --stop first.${NC}"
        exit 1
    elif [[ "$existing_pid" != "$$" ]]; then
        rm -f "$PID_FILE"
    fi
fi

mkdir -p "$CONFIG_DIR"

echo -e "${CYAN}╔══════════════════════════════════════╗${NC}"
echo -e "${CYAN}║    NebulaSSH Linux Agent v${VERSION}     ║${NC}"
echo -e "${CYAN}╚══════════════════════════════════════╝${NC}"
echo -e "Agent ID:    ${GREEN}${AGENT_ID}${NC}"
echo -e "Relay:       ${RELAY_URL}"
echo -e "Shell:       ${SHELL_TYPE}"
echo -e "Interval:    ${POLL_INTERVAL}s"
echo ""

if [[ "$DAEMON" == "true" ]]; then
    log INFO "Starting agent in daemon mode..."
    # Remove stale PID so the child doesn't see it as conflict
    rm -f "$PID_FILE"
    nohup "$0" --relay "$RELAY_URL" --enroll-token "$ENROLL_TOKEN" --shell "$SHELL_TYPE" --interval "$POLL_INTERVAL" >> "$LOG_FILE" 2>&1 &
    local_pid=$!
    echo "$local_pid" > "$PID_FILE"
    echo -e "${GREEN}Agent started in background (PID $local_pid)${NC}"
    echo -e "Log: $LOG_FILE"
    echo -e "Stop: $0 --stop"
    exit 0
fi

# Save PID for foreground mode too
echo "$$" > "$PID_FILE"

log INFO "Agent starting..."
main_loop
