#!/usr/bin/env bash
set -euo pipefail

tty="${1:-$(tmux display-message -p '#{pane_tty}' 2>/dev/null)}"
user="${2:-$(whoami)}"
activity="${3:-}"
client_pid="${4:-}"

LOG_DIR="/var/log/harresi/audit/security/tmux-status"
[[ -d "$LOG_DIR" ]] || exit 0
LOG_FILE="$LOG_DIR/${user}.log"
touch "$LOG_FILE" 2>/dev/null || exit 0
exec 2>>"$LOG_FILE"
exec 3>>"$LOG_FILE"
log() { echo "[$(date '+%F %T')] $*" >&3; }

log "Usuario=$user, tty=$tty, actividad=${activity:-n/a}, client_pid=${client_pid:-n/a}, TMUX iniciado"

if [[ -z "$tty" ]]; then
    log "Usuario=$user no tiene TTY"
    exit 0
fi

if [[ -f /etc/environment ]]; then
    source /etc/environment
fi

timeout_min="${SESSION_TIMEOUT:-15}"
if ! [[ "$timeout_min" =~ ^[0-9]+$ ]] || (( timeout_min <= 0 )); then
    timeout_min=15
fi
timeout_sec=$((timeout_min * 60))

tty_name="${tty#/dev/}"
tty_short="${tty_name#pts/}"

find_ssh_parent() {
    local pid="$1"
    local ppid cmd

    [[ "$pid" =~ ^[0-9]+$ ]] || return 1

    while [[ -r "/proc/$pid/stat" ]]; do
        cmd="$(tr '\0' ' ' <"/proc/$pid/cmdline" 2>/dev/null || true)"
        if [[ "$cmd" == sshd:\ * ]]; then
            printf '%s\n' "$pid"
            return 0
        fi

        ppid="$(awk '{print $4}' "/proc/$pid/stat" 2>/dev/null || true)"
        [[ "$ppid" =~ ^[0-9]+$ ]] || return 1
        (( ppid > 1 && ppid != pid )) || return 1
        pid="$ppid"
    done

    return 1
}

find_who_session() {
    local line who_user who_tty who_pid host pid session_time

    while IFS= read -r line; do
        read -r who_user who_tty _ <<< "$line"
        [[ "$who_user" == "$user" && "$who_tty" == "$tty_name" ]] || continue

        who_pid="$(awk '{for (i = 3; i <= NF; i++) if ($i ~ /^[0-9]+$/) {print $i; exit}}' <<< "$line")"
        host="$(awk '{print $NF}' <<< "$line")"
        [[ "$who_pid" =~ ^[0-9]+$ ]] || continue

        if pid="$(find_ssh_parent "$who_pid" 2>/dev/null)"; then
            :
        elif [[ "$host" == \(*\) ]]; then
            pid="$who_pid"
        else
            continue
        fi

        session_time="$(ps -o etimes= -p "$pid" 2>/dev/null | awk 'NF {print $1; exit}')"
        [[ "$session_time" =~ ^[0-9]+$ ]] || continue
        printf '%s %s\n' "$session_time" "$pid"
        return 0
    done < <(who -u 2>/dev/null)

    return 1
}

ses_array=()
if ssh_pid="$(find_ssh_parent "$client_pid" 2>/dev/null)"; then
    if ssh_time="$(ps -o etimes= -p "$ssh_pid" 2>/dev/null | awk 'NF {print $1; exit}')"; then
        if [[ "$ssh_time" =~ ^[0-9]+$ ]]; then
            ses_array+=("$ssh_time $ssh_pid")
        fi
    fi
fi

if [[ ${#ses_array[@]} -eq 0 ]]; then
    mapfile -t ses_array < <(find_who_session)
fi

if [[ ${#ses_array[@]} -eq 0 ]]; then
    mapfile -t ses_array < <(
        ps -eo etimes,pid,cmd --sort=etimes \
        | awk -v u="$user" -v tty="$tty_name" -v short="$tty_short" '
            index($0, "sshd: " u "@") {
                if ($0 ~ ("sshd: " u "@" tty "([[:space:]]|$)")) {
                    print $1, $2
                } else if (tty ~ /^pts\// && $0 ~ ("sshd: " u "@" short "([[:space:]]|$)")) {
                    print $1, $2
                }
            }
        '
    )
fi

if [[ ${#ses_array[@]} -eq 0 ]]; then
    log "Usuario=$user, tty=$tty no esta conectado mediante SSH"
    exit 0
fi

log "ses_array=${ses_array[*]}"

now=$(date +%s)
for entry in "${ses_array[@]}"; do
    read -r ses_time ses_pid <<< "$entry"
    elapsed="$ses_time"
    mode="session"

    if [[ "$activity" =~ ^[0-9]+$ ]] && (( activity > 0 && now >= activity )); then
        elapsed=$((now - activity))
        mode="idle"
    fi

    remain=$((timeout_sec - elapsed))
    ((remain < 0)) && remain=0
    kill_pid="$ses_pid"
    if [[ "$client_pid" =~ ^[0-9]+$ ]] && [[ -d "/proc/$client_pid" ]]; then
        kill_pid="$client_pid"
    fi

    log "Usuario=$user TTY=$tty PID=$ses_pid kill_pid=$kill_pid modo=$mode transcurrido=$elapsed restante=$remain"

    if   (( remain <= 30 ));  then seg='#[fg=colour231,bg=colour1,bold]'
    elif (( remain <= 60 ));  then seg='#[fg=colour231,bg=colour202,bold]'
    elif (( remain <= 300 )); then seg='#[fg=colour16,bg=colour226,bold]'
    else                          seg='#[fg=colour238,bg=colour148]'
    fi

    printf '%s timeout: %ss #[default]' "$seg" "$remain"
    if (( remain == 0 )); then
        log "Usuario=$user TTY=$tty cerrando sesion por timeout con PID=$kill_pid"
        kill -TERM "$kill_pid" 2>/dev/null || true
        sleep 0.2
        kill -0 "$kill_pid" 2>/dev/null && kill -KILL "$kill_pid" 2>/dev/null || true
    fi
done
