#!/bin/bash
set -euo pipefail

WATCHDOG_SCRIPT="/opt/terkom-ng/terkom/scripts/watchdog.sh"
SERVICE_FILE="/etc/systemd/system/terkom-watchdog.service"
TIMER_FILE="/etc/systemd/system/terkom-watchdog.timer"

echo "[INFO] Installing Terkom Watchdog..."

mkdir -p /opt/terkom-ng/terkom/scripts

cat > "$WATCHDOG_SCRIPT" <<'EOF'
#!/bin/bash

set -u

SERVICE="terkom-ng-server"
UI_URL="http://127.0.0.1:3000"
CONFIG_FILE="/opt/terkom-ng/terkom/config-local.yaml"

GRACE_SECONDS=5
MAX_RESTART_ATTEMPTS=5

DB_RECOVERY_GRACE_SECONDS=10
DB_RECOVERY_COOLDOWN_SECONDS=300

STATE_DIR="/run/terkom-watchdog"
ATTEMPTS_FILE="$STATE_DIR/restart_attempts"
LOCK_FILE="$STATE_DIR/watchdog.lock"
DB_STATE_FILE="$STATE_DIR/db_state"
LAST_RECOVERY_RESTART_FILE="$STATE_DIR/last_recovery_restart"

mkdir -p "$STATE_DIR"

log() {
    local msg="$1"
    logger -t terkom-watchdog "$msg"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $msg"
}

exec 9>"$LOCK_FILE"
if ! flock -n 9; then
    log "Jiná instance watchdogu už běží, končím."
    exit 0
fi

read_db_config() {
    if [ ! -f "$CONFIG_FILE" ]; then
        log "Config soubor neexistuje: $CONFIG_FILE"
        return 1
    fi

    DB_HOST=$(awk '
        /^[[:space:]]*connection:[[:space:]]*$/ { in_connection=1; next }
        in_connection && /^[^[:space:]]/ { in_connection=0 }
        in_connection && /^[[:space:]]*host:[[:space:]]*/ {
            sub(/^[[:space:]]*host:[[:space:]]*/, "", $0)
            print $0
            exit
        }
    ' "$CONFIG_FILE")

    DB_PORT=$(awk '
        /^[[:space:]]*connection:[[:space:]]*$/ { in_connection=1; next }
        in_connection && /^[^[:space:]]/ { in_connection=0 }
        in_connection && /^[[:space:]]*port:[[:space:]]*/ {
            sub(/^[[:space:]]*port:[[:space:]]*/, "", $0)
            print $0
            exit
        }
    ' "$CONFIG_FILE")

    DB_HOST=$(echo "${DB_HOST:-}" | tr -d '"' | xargs)
    DB_PORT=$(echo "${DB_PORT:-}" | tr -d '"' | xargs)

    if [ -z "${DB_HOST:-}" ] || [ -z "${DB_PORT:-}" ]; then
        log "Nepodařilo se načíst DB host/port z $CONFIG_FILE"
        return 1
    fi

    log "Načten DB config: host=$DB_HOST port=$DB_PORT"
    return 0
}

db_available() {
    if ! ping -c 1 -W 1 "$DB_HOST" > /dev/null 2>&1; then
        log "DB host $DB_HOST neodpovídá na ping."
        return 1
    fi

    if ! timeout 2 bash -c "echo > /dev/tcp/$DB_HOST/$DB_PORT" > /dev/null 2>&1; then
        log "DB host $DB_HOST je dostupný, ale port $DB_PORT neodpovídá."
        return 1
    fi

    return 0
}

get_attempts() {
    if [ -f "$ATTEMPTS_FILE" ]; then
        cat "$ATTEMPTS_FILE"
    else
        echo 0
    fi
}

set_attempts() {
    echo "$1" > "$ATTEMPTS_FILE"
}

reset_attempts() {
    set_attempts 0
}

increment_attempts() {
    local current
    current=$(get_attempts)
    current=$((current + 1))
    set_attempts "$current"
    echo "$current"
}

get_db_state() {
    if [ -f "$DB_STATE_FILE" ]; then
        cat "$DB_STATE_FILE"
    else
        echo "unknown"
    fi
}

set_db_state() {
    echo "$1" > "$DB_STATE_FILE"
}

get_now_ts() {
    date +%s
}

get_last_recovery_restart_ts() {
    if [ -f "$LAST_RECOVERY_RESTART_FILE" ]; then
        cat "$LAST_RECOVERY_RESTART_FILE"
    else
        echo 0
    fi
}

set_last_recovery_restart_ts() {
    echo "$1" > "$LAST_RECOVERY_RESTART_FILE"
}

service_ok() {
    systemctl is-active --quiet "$SERVICE"
}

node_ok() {
    pgrep -af "node run.js" > /dev/null
}

browser_ok() {
    pgrep -af "chromium|chromium-browser" > /dev/null
}

ui_ok() {
    curl -fsS --max-time 3 "$UI_URL" > /dev/null 2>&1
}

all_ok() {
    service_ok && node_ok && browser_ok && ui_ok
}

restart_terkom() {
    if ! read_db_config; then
        log "DB config nelze načíst, restart neprovádím."
        exit 0
    fi

    if ! db_available; then
        log "DB není dostupná, restart neprovádím."
        exit 0
    fi

    local attempts
    attempts=$(get_attempts)

    if [ "$attempts" -ge "$MAX_RESTART_ATTEMPTS" ]; then
        log "Dosažen max. počet restartů: $MAX_RESTART_ATTEMPTS. Další restart neprovádím."
        exit 0
    fi

    attempts=$(increment_attempts)
    log "Provádím restart Terkomu... pokus $attempts/$MAX_RESTART_ATTEMPTS"

    systemctl stop "$SERVICE"
    pkill -f "node run.js" || true
    sleep 2
    systemctl start "$SERVICE"
}

restart_after_db_recovery() {
    local now_ts last_ts diff
    now_ts=$(get_now_ts)
    last_ts=$(get_last_recovery_restart_ts)
    diff=$((now_ts - last_ts))

    if [ "$diff" -lt "$DB_RECOVERY_COOLDOWN_SECONDS" ]; then
        log "DB se vrátila, ale recovery restart je v cooldownu (${diff}s < ${DB_RECOVERY_COOLDOWN_SECONDS}s)."
        return 0
    fi

    log "DB přešla ze stavu DOWN do UP. Čekám ${DB_RECOVERY_GRACE_SECONDS}s pro stabilizaci DB."
    sleep "$DB_RECOVERY_GRACE_SECONDS"

    if ! db_available; then
        log "DB po grace period není stabilně dostupná, recovery restart neprovádím."
        set_db_state "down"
        return 0
    fi

    log "DB je po výpadku znovu dostupná. Provádím recovery restart Terkomu."
    systemctl stop "$SERVICE"
    pkill -f "node run.js" || true
    sleep 2
    systemctl start "$SERVICE"

    set_last_recovery_restart_ts "$now_ts"
    set_db_state "up"
    reset_attempts
}

if read_db_config; then
    PREV_DB_STATE=$(get_db_state)

    if db_available; then
        CURRENT_DB_STATE="up"
    else
        CURRENT_DB_STATE="down"
    fi

    if [ "$CURRENT_DB_STATE" = "down" ]; then
        if [ "$PREV_DB_STATE" != "down" ]; then
            log "DB je nově nedostupná."
        fi
        set_db_state "down"
    fi

    if [ "$PREV_DB_STATE" = "down" ] && [ "$CURRENT_DB_STATE" = "up" ]; then
        log "Detekován návrat DB (down -> up)."
        restart_after_db_recovery
        exit 0
    fi

    if [ "$CURRENT_DB_STATE" = "up" ]; then
        set_db_state "up"
    fi
else
    log "DB config nelze načíst pro DB-state monitoring."
fi

if all_ok; then
    if [ "$(get_attempts)" != "0" ]; then
        log "Systém je OK, resetuji počítadlo restartů."
    else
        log "OK - vše běží."
    fi
    reset_attempts
    exit 0
fi

log "Detekován problém. Čekám ${GRACE_SECONDS}s kvůli odfiltrování krátkého výpadku."
sleep "$GRACE_SECONDS"

if all_ok; then
    log "Systém se během grace period vzpamatoval, restart není potřeba."
    reset_attempts
    exit 0
fi

log "Problém trvá déle než ${GRACE_SECONDS}s, zvažuji restart."
restart_terkom
exit 0
EOF

chown root:root "$WATCHDOG_SCRIPT"
chmod 755 "$WATCHDOG_SCRIPT"

cat > "$SERVICE_FILE" <<'EOF'
[Unit]
Description=Terkom watchdog
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/bin/bash /opt/terkom-ng/terkom/scripts/watchdog.sh
User=root
Group=root
StandardOutput=journal
StandardError=journal
EOF

cat > "$TIMER_FILE" <<'EOF'
[Unit]
Description=Run Terkom watchdog every minute

[Timer]
OnBootSec=45
OnUnitActiveSec=60
AccuracySec=5
Unit=terkom-watchdog.service

[Install]
WantedBy=timers.target
EOF

chown root:root "$SERVICE_FILE" "$TIMER_FILE"
chmod 644 "$SERVICE_FILE" "$TIMER_FILE"

systemctl daemon-reload
systemctl enable --now terkom-watchdog.timer
systemctl restart terkom-watchdog.timer
systemctl start terkom-watchdog.service || true

echo "[OK] Installation complete"
echo "[INFO] Timer status:"
systemctl status terkom-watchdog.timer --no-pager || true
echo "[INFO] Recent logs:"
journalctl -u terkom-watchdog.service -n 20 --no-pager || true
