#!/bin/bash
# TSID Idle Monitor - 사용자 자리비움 감지 및 자동 로그아웃
# Usage: tsid-idle-monitor <user> <idle_timeout_seconds>

USER="$1"
IDLE_TIMEOUT="${2:-300}"  # 기본 5분 (300초)
LOG_FILE="/var/log/tsid/idle_monitor.log"

if [ -z "$USER" ]; then
    echo "[TSID] Error: No user specified" >&2
    exit 1
fi

# 로그 디렉토리 생성
mkdir -p "$(dirname "$LOG_FILE")"
touch "$LOG_FILE"

log_message() {
    local level="$1"
    local message="$2"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}

# X11 디스플레이 찾기
find_display() {
    local user="$1"
    # 사용자의 X11 디스플레이 찾기
    local display=$(ps aux | grep -E "^$user.*X.*:" | head -1 | grep -o ":[0-9]*" | head -1)
    if [ -z "$display" ]; then
        display=":0"  # 기본값
    fi
    echo "$display"
}

# OS 감지 (config 파일에서 읽기)
detect_os() {
    local config_file="/etc/tsid/os-config"
    
    # 1. Config 파일에서 읽기
    if [ -f "$config_file" ]; then
        local dm=$(grep "^TSID_DISPLAY_MANAGER=" "$config_file" | cut -d= -f2)
        if [ "$dm" = "gdm" ]; then
            echo "rocky10"
            return
        elif [ "$dm" = "lightdm" ]; then
            # Rocky 8/9 또는 Ubuntu/Debian
            local os_version=$(grep "^TSID_OS_VERSION=" "$config_file" | cut -d= -f2)
            if [ "$os_version" = "debian" ]; then
                echo "ubuntu"
            else
                echo "rocky89"
            fi
            return
        fi
    fi
    
    # 2. Fallback: OS 버전 파일 감지
    if [ -f /etc/rocky-release ]; then
        local rocky_version=$(grep -oE '[0-9]+' /etc/rocky-release | head -1)
        if [ "$rocky_version" -ge 10 ] 2>/dev/null; then
            echo "rocky10"
        else
            echo "rocky89"
        fi
    elif [ -f /etc/debian_version ]; then
        echo "ubuntu"
    else
        echo "unknown"
    fi
}

# Rocky 10 Wayland: LockedHint 상태 확인
get_locked_hint() {
    local session_id="$1"
    if command -v loginctl >/dev/null 2>&1; then
        loginctl show-session "$session_id" -p LockedHint --value 2>/dev/null
    fi
}

# X11 환경: xprintidle 또는 xscreensaver 사용
get_x11_idle_time() {
    local user="$1"
    local display="$2"
    
    # 방법 1: xprintidle 사용 (가장 정확)
    if command -v xprintidle >/dev/null 2>&1; then
        local idle_ms=$(sudo -u "$user" DISPLAY="$display" xprintidle 2>/dev/null || echo "0")
        if [ "$idle_ms" -gt 0 ]; then
            echo $((idle_ms / 1000))
            return
        fi
    fi
    
    # 방법 2: xscreensaver-command 사용
    if command -v xscreensaver-command >/dev/null 2>&1; then
        local idle_time=$(sudo -u "$user" DISPLAY="$display" xscreensaver-command -time 2>/dev/null | grep "screen saver" | grep -o '[0-9]*' | head -1)
        if [ -n "$idle_time" ]; then
            echo "$idle_time"
            return
        fi
    fi
    
    # 방법 3: /dev/input에서 입력 활동 감지 (Fallback)
    local current_time=$(date +%s)
    local last_input=$(find /dev/input -name "event*" -type f -exec stat -c %Y {} \; 2>/dev/null | sort -n | tail -1)
    if [ -n "$last_input" ] && [ "$last_input" -gt 0 ]; then
        echo $((current_time - last_input))
        return
    fi
    
    echo "0"
}

# Wayland 환경: /dev/input 입력 활동 감지
get_wayland_idle_time() {
    local current_time=$(date +%s)
    local last_input=$(find /dev/input -name "event*" -type f -exec stat -c %Y {} \; 2>/dev/null | sort -n | tail -1)
    if [ -n "$last_input" ] && [ "$last_input" -gt 0 ]; then
        echo $((current_time - last_input))
        return
    fi
    
    echo "0"
}

# 사용자 idle 시간 확인 (초 단위)
get_idle_time() {
    local user="$1"
    local display="$2"
    local os=$(detect_os)
    
    case "$os" in
        rocky10)
            # Rocky 10 Wayland: /dev/input 입력 활동 감지만 사용
            # (LockedHint는 별도로 모니터링)
            get_wayland_idle_time
            ;;
        rocky89|ubuntu)
            # Rocky 8/9, Ubuntu: X11 환경
            get_x11_idle_time "$user" "$display"
            ;;
        *)
            # Unknown OS: /dev/input 입력 활동 감지
            get_wayland_idle_time
            ;;
    esac
}

# 사용자 세션 확인
is_user_logged_in() {
    local user="$1"
    who | grep -q "^$user "
}

# 자동 로그아웃 실행
auto_logout() {
    local user="$1"
    log_message "INFO" "Auto-logging out user: $user (idle timeout reached)"
    
    # 사용자 프로세스 종료
    pkill -u "$user" 2>/dev/null || true
    
    # 로그인 세션 종료
    loginctl terminate-user "$user" 2>/dev/null || true
    
    # Display Manager 감지 및 QR 화면 복원
    /usr/bin/tsid-restore-greeter 2>/dev/null || true
    
    # Rocky 버전 감지
    local rocky_ver=0
    if [ -f /etc/rocky-release ]; then
        rocky_ver=$(grep -oE '[0-9]+' /etc/rocky-release | head -1)
    fi
    
    if [ "$rocky_ver" -ge 10 ] 2>/dev/null; then
        # Rocky 10: GDM 사용
        log_message "INFO" "Detected Rocky 10 - restarting GDM"
        systemctl restart gdm 2>/dev/null || true
    elif [ "$rocky_ver" -gt 0 ] 2>/dev/null; then
        # Rocky 8/9: LightDM 사용
        log_message "INFO" "Detected Rocky 8/9 - restarting LightDM"
        systemctl restart lightdm 2>/dev/null || true
    elif [ -f /etc/debian_version ]; then
        # Ubuntu/Debian: LightDM 사용
        log_message "INFO" "Detected Ubuntu/Debian - restarting LightDM"
        systemctl restart lightdm 2>/dev/null || true
    else
        # Fallback: 둘 다 시도
        log_message "INFO" "Unknown OS - attempting to restart both GDM and LightDM"
        systemctl restart gdm 2>/dev/null || true
        systemctl restart lightdm 2>/dev/null || true
    fi
    
    log_message "INFO" "User $user logged out, QR screen restored"
}

# 메인 모니터링 루프
main() {
    local user="$USER"
    local idle_timeout="$IDLE_TIMEOUT"
    local os=$(detect_os)
    
    log_message "INFO" "Starting idle monitor for user: $user (timeout: ${idle_timeout}s, OS: $os)"
    
    local prev_locked=""
    
    while true; do
        # 사용자가 로그인되어 있는지 확인
        if is_user_logged_in "$user"; then
            local display=$(find_display "$user")
            
            # Rocky 10: LockedHint 상태 변화 감지
            if [ "$os" = "rocky10" ]; then
                local session_id=$(loginctl list-sessions --no-pager | grep "$user" | awk '{print $1}' | head -1)
                if [ -n "$session_id" ]; then
                    local cur_locked=$(get_locked_hint "$session_id")
                    
                    # LockedHint 상태 변화 감지
                    if [ "$cur_locked" != "$prev_locked" ]; then
                        log_message "DEBUG" "User: $user, LockedHint changed: $prev_locked → $cur_locked"
                        
                        if [ "$cur_locked" = "yes" ]; then
                            # Lock Screen 활성화 → 자동 로그아웃
                            log_message "INFO" "Lock Screen detected, auto-logging out user: $user"
                            auto_logout "$user"
                            break
                        fi
                        prev_locked=$cur_locked
                    fi
                fi
            else
                # Rocky 8/9, Ubuntu: idle 시간 기반 감지
                local idle_time=$(get_idle_time "$user" "$display")
                
                log_message "DEBUG" "User: $user, Display: $display, Idle: ${idle_time}s, Timeout: ${idle_timeout}s"
                
                if [ "$idle_time" -ge "$idle_timeout" ]; then
                    auto_logout "$user"
                    break
                fi
            fi
        else
            log_message "DEBUG" "User $user not logged in, waiting..."
        fi
        
        # 30초마다 확인
        sleep 30
    done
    
    log_message "INFO" "Idle monitor stopped for user: $user"
}

# 신호 처리
cleanup() {
    log_message "INFO" "Idle monitor interrupted, exiting..."
    exit 0
}

trap cleanup SIGTERM SIGINT

# 메인 함수 실행
main

exit 0
