#!/bin/bash

. ./ajax_agent_common

# Ȩ޼ - ȷֻйԱԲ鿴״̬
action_check

# ȷĿ¼
if [ ! -d "$RAM_TMP_DIR" ]; then
    mkdir -p "$RAM_TMP_DIR"
    chown -R nobody: "$RAM_TMP_DIR"
fi

# ============================================================================
# ƽ̨ʱʵ
# ============================================================================

# ־ѡϳʱ⣩
# $1=־ $2=־Ϣ
debug_log() {
    local level="$1"
    local message="$2"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

    # ֻDEBUGʱϢ
    if [ "${DEBUG:-0}" = "1" ]; then
        echo "[$timestamp] [$level] $message" >&2
    fi
}

# ϵͳǷ֧ timeout 
# أ0 ʾ֧֣1 ʾ֧
has_timeout_command() {
    #  timeout Ƿҿִ
    if command -v timeout >/dev/null 2>&1; then
        # һ timeout Ƿ
        # ʹһ򵥵Ĳ֤
        if timeout 1 true >/dev/null 2>&1; then
            debug_log "INFO" "System timeout command is available and working"
            return 0
        else
            debug_log "WARN" "System timeout command exists but not working properly"
        fi
    else
        debug_log "INFO" "System timeout command not found, will use fallback mechanism"
    fi
    return 1
}

# óʱƣʹų́ + sleep + kill ʵֳʱ
# $1=ʱ $2Ժ=Ҫִе
# أ˳룬ʱʱ124GNU timeoutһ£
run_with_fallback_timeout() {
    local timeout_seconds="$1"
    shift

    # ʱļ洢˳
    local output_file="${RAM_TMP_DIR}/timeout_output_$$"
    local exit_code_file="${RAM_TMP_DIR}/timeout_exit_$$"
    local pid_file="${RAM_TMP_DIR}/timeout_pid_$$"

    # 
    cleanup_timeout_files() {
        rm -f "$output_file" "$exit_code_file" "$pid_file" 2>/dev/null
    }

    # ȷʱļ
    trap cleanup_timeout_files EXIT

    # ںִ̨˳뱣浽ļ
    (
        "$@" > "$output_file"
        echo $? > "$exit_code_file"
    ) &

    local cmd_pid=$!
    echo "$cmd_pid" > "$pid_file"

    # ʱؽ
    (
        sleep "$timeout_seconds"
        if [ -f "$pid_file" ] && kill -0 "$cmd_pid" 2>/dev/null; then
            # Уɱ
            kill -TERM "$cmd_pid" 2>/dev/null
            sleep 1
            # TERMźЧʹKILLź
            if kill -0 "$cmd_pid" 2>/dev/null; then
                kill -KILL "$cmd_pid" 2>/dev/null
            fi
            # Ϊʱ
            echo "124" > "$exit_code_file"
        fi
    ) &

    local timeout_pid=$!

    # ȴ
    wait "$cmd_pid" 2>/dev/null
    local wait_result=$?

    # ɱʱؽ
    kill "$timeout_pid" 2>/dev/null
    wait "$timeout_pid" 2>/dev/null

    # Ľ
    if [ -f "$output_file" ]; then
        cat "$output_file"
    fi

    # ˳
    if [ -f "$exit_code_file" ]; then
        local saved_exit_code
        saved_exit_code=$(cat "$exit_code_file" 2>/dev/null)
        if [ -n "$saved_exit_code" ] && [ "$saved_exit_code" -ge 0 ] 2>/dev/null; then
            cleanup_timeout_files
            return "$saved_exit_code"
        fi
    fi

    # ޷ȡ˳룬waitĽ
    cleanup_timeout_files
    return "$wait_result"
}

# ͨóʱִк
# $1=ʱ $2Ժ=Ҫִе
# أ˳룬ʱʱ124
run_with_timeout() {
    local timeout_seconds="$1"
    shift

    # ֤
    if [ -z "$timeout_seconds" ] || [ "$timeout_seconds" -le 0 ] 2>/dev/null; then
        debug_log "ERROR" "Invalid timeout value: $timeout_seconds"
        echo "Error: Invalid timeout value: $timeout_seconds" >&2
        return 1
    fi

    if [ $# -eq 0 ]; then
        debug_log "ERROR" "No command specified for timeout execution"
        echo "Error: No command specified" >&2
        return 1
    fi

    debug_log "INFO" "Executing command with ${timeout_seconds}s timeout: $*"

    # Ⲣѡѳʱ
    if has_timeout_command; then
        # ʹϵͳ timeout 
        debug_log "INFO" "Using system timeout command"
        timeout "$timeout_seconds" "$@"
        local exit_code=$?
        debug_log "INFO" "System timeout command completed with exit code: $exit_code"
        return $exit_code
    else
        # ʹñóʱ
        debug_log "INFO" "Using fallback timeout mechanism"
        run_with_fallback_timeout "$timeout_seconds" "$@"
        local exit_code=$?
        debug_log "INFO" "Fallback timeout mechanism completed with exit code: $exit_code"
        return $exit_code
    fi
}

# ȡļ״̬
get_config_status() {
    if [ -f "$AGENT_CONF_FILE" ]; then
        echo ""
    else
        echo "ļ"
    fi
}

# ȡļ޸ʱ
get_config_mtime() {
    if [ -f "$AGENT_CONF_FILE" ]; then
        # ϵͳܹ
        arch=$(uname -m)
        if [ "${arch}" == "x86_64" ] || [ "${arch}" == "aarch64" ]; then
            stat -c %Y "$AGENT_CONF_FILE" | xargs -I {} date -d @{} "+%Y-%m-%d %H:%M:%S"
        else
            stat -f %m "$AGENT_CONF_FILE" | xargs -I {} date -r {} "+%Y-%m-%d %H:%M:%S"
        fi
    else
        echo "δ֪"
    fi
}

# ȡ־ļС
get_log_size() {
    # ̬ȡõ־ļ·
    local log_file_path=$(get_log_file_path)

    if [ -f "$log_file_path" ]; then
        # ƽ̨ݵļСȡ
        local size_bytes
        if command -v stat >/dev/null 2>&1; then
            # Linux/Unixϵͳ
            size_bytes=$(stat -c %s "$log_file_path" 2>/dev/null || stat -f %z "$log_file_path" 2>/dev/null || echo 0)
        else
            # ÷
            size_bytes=$(wc -c < "$log_file_path" 2>/dev/null || echo 0)
        fi

        # ܵλת
        local size_mb=$((size_bytes / 1024 / 1024))
        local size_kb=$((size_bytes / 1024))

        if [ $size_mb -gt 0 ]; then
            echo "${size_mb}MB"
        elif [ $size_kb -gt 0 ]; then
            echo "${size_kb}KB"
        else
            echo "${size_bytes}B"
        fi
    else
        echo "־ļ ($log_file_path)"
    fi
}



# Get count of archive log files
# Returns the number of agent-*.log.gz files in archive directory
get_archive_log_count() {
    local archive_dir=$(get_archive_log_dir)

    # Check if archive directory exists
    if [ ! -d "$archive_dir" ]; then
        echo "0"
        return 0
    fi

    # Count agent-*.log.gz files (exclude agent.log snapshot)
    # Use -H to follow symbolic links on command line only (more secure than -L)
    local count=$(find -H "$archive_dir" -maxdepth 1 -type f -name 'agent-*.log.gz' 2>/dev/null | wc -l)
    echo "$count"
}

# ȡAgent״̬JSONݣ汾
get_agent_status_json() {
    # AgentļǷҾпִȨ
    if [ ! -f "${AGENT_BIN}" ] || [ ! -x "${AGENT_BIN}" ]; then
        echo '{"error": "agent_not_found", "message": "AgentļڻִȨ"}'
        return 1
    fi

    # ʹÿƽ̨ʱִstatus
    # unisase-agent status --json Զжϲ ActiveProcessStatus  InactiveProcessStatus
    local status_output
    status_output=$(run_with_timeout 10 "${AGENT_BIN}" status --json 2>/dev/null)
    local exit_code=$?

    # ִн
    if [ $exit_code -eq 124 ]; then
        # ʱ
        echo '{"error": "command_timeout", "message": "statusִгʱ"}'
        return 1
    elif [ $exit_code -ne 0 ] || [ -z "$status_output" ]; then
        # 
        echo '{"error": "command_failed", "message": "statusִʧ"}'
        return 1
    fi

    echo "$status_output"
    return 0
}

# ȡϵͳ汾Ϣ
get_system_version() {
    local app_inf_file="${APP_ROOT_DIR}/app.inf"
    local version="δ֪"

    # 汾ļǷ
    if [ -f "$app_inf_file" ]; then
        # ȡ app_version ֶ
        local full_app_version=$(grep '^app_version=' "$app_inf_file" 2>/dev/null | cut -d'=' -f2 | tr -d '"')

        if [ -n "$full_app_version" ]; then
            # ȡһ»֮ǰĲ
            local friendly_version=${full_app_version%%_*}
            version="$friendly_version"
        fi
    fi

    echo "$version"
}

# ȡ豸к
get_device_serial_number() {
    local device_id=""

    # Ҫ floweye 
    if ! command -v floweye >/dev/null 2>&1; then
        echo ""
        return 1
    fi

    # ȡü
    device_id=$(floweye key getcookie2 2>/dev/null)
    if [ $? -ne 0 ] || [ -z "$device_id" ]; then
        echo ""
        return 1
    fi

    device_id=$(echo "$device_id" | tr -d '\n\r\t ' | head -c 200)

    # Уʽĸ//ַ>=20
    if echo "$device_id" | grep -qE '^[a-fA-F0-9-]{20,}$'; then
        echo "$device_id"
        return 0
    else
        echo ""
        return 1
    fi
}

# ȡAgent״̬ϢָǰҪĺ
get_agent_status() {
    local appctl_path="${RAM_APP_CTRL}"
    local status=""

    # appctlűǷ
    if [ -f "$appctl_path" ] && [ -x "$appctl_path" ]; then
        # ִstatusȡ
        local output=$("$appctl_path" status 2>/dev/null)
        local exit_code=$?

        if [ $exit_code -eq 0 ]; then
            # ж״̬
            if echo "$output" | grep -q "enable"; then
                status=""
            elif echo "$output" | grep -q "disable"; then
                status="δ"
            else
                status="δ֪"
            fi
        else
            status="δ"
        fi
    fi

    echo "$status"
}

# ȡAgentԭʼݣJSON
get_agent_status_data() {
    local agent_status_json
    agent_status_json=$(get_agent_status_json)

    # Agent״̬JSONǷ
    if echo "$agent_status_json" | grep -q '"error"'; then
        # Agentδлֱӷget_agent_status_jsonĴϢ
        # ִϢһԣظ
        echo "$agent_status_json"
    else
        # AgentУֱӷԭʼJSON
        echo "$agent_status_json"
    fi
}

# ȡϵͳ״̬Ϣ
system_get_status() {
    local config_status=$(get_config_status)
    local config_mtime=$(get_config_mtime)
    local log_size=$(get_log_size)
    local archive_log_count=$(get_archive_log_count)
    local system_version=$(get_system_version)
    local device_id=$(get_device_serial_number)
    local agent_status=$(get_agent_status)

    # ȡAgentԭʼ
    local agent_status_data=$(get_agent_status_data)

    # ȷЧֵ
    [ -z "$agent_status_data" ] && agent_status_data='{"error": "empty_data", "message": "Agentݻȡʧ"}'

    # תJSONַеַ
    config_status=$(echo "$config_status" | sed 's/"/\\"/g')
    config_mtime=$(echo "$config_mtime" | sed 's/"/\\"/g')
    log_size=$(echo "$log_size" | sed 's/"/\\"/g')
    system_version=$(echo "$system_version" | sed 's/"/\\"/g')
    agent_status=$(echo "$agent_status" | sed 's/"/\\"/g')

    # 豸к - ΪΪnull
    local device_id_json
    if [ -n "$device_id" ]; then
        # ת豸кеַ
        device_id=$(echo "$device_id" | sed 's/"/\\"/g')
        device_id_json="\"$device_id\""
    else
        device_id_json="null"
    fi

    # JSONӦ
    printf '{\n'
    printf '    "config_status": "%s",\n' "$config_status"
    printf '    "config_mtime": "%s",\n' "$config_mtime"
    printf '    "log_size": "%s",\n' "$log_size"
    printf '    "archive_log_count": %s,\n' "$archive_log_count"
    printf '    "system_version": "%s",\n' "$system_version"
    printf '    "device_id": %s,\n' "$device_id_json"
    printf '    "agent_status": "%s",\n' "$agent_status"
    printf '    "agent_status_data": %s\n' "$agent_status_data"
    printf '}\n'
}

# ·ɷַ
case "${CGI_action}" in
    "get_status")
        retjson 0 "OK" "`system_get_status`"
        ;;
    *)
        retjson 1 "UNKNOWN_ACTION!"
        ;;
esac
