#!/bin/bash
# Checkmk local checks for dotnews-paas — installed to
# /usr/lib/check_mk_agent/local/paas by bootstrap.sh.
#
# DYNAMIC: enumerates /srv/paas/apps.d/*.conf, so every `paas create`
# automatically yields new Checkmk services at the next service discovery —
# no monitoring-side configuration per project.
#
# Output format: "<state> <service_name> <perfdata|-> <status text>"

REG=/srv/paas/apps.d
DB=/srv/paas/paas.db
NOW=$(date +%s)

JL=$(sudo -u deploy -H bash -c 'cd /srv/paas && pm2 jlist' 2>/dev/null)
# platform flags (PHP_DEFAULT for laravel apps without an explicit version)
# shellcheck disable=SC1091
[ -f /srv/paas/paas.conf ] && . /srv/paas/paas.conf

for conf in "$REG"/*.conf; do
    [ -e "$conf" ] || continue
    APP=''; PORT=''; DOMAINS=''; HEALTH_PATH=''; SYSTEM_DOMAIN=''
    RUNTIME=node; PHP_VERSION=''; QUEUE_WORKER=off
    # shellcheck disable=SC1090
    . "$conf"
    [ -n "$APP" ] || continue

    # ---- app health (direct to the app port; works for cached + uncached) ----
    read -r code t < <(curl -s -o /dev/null -m 5 -w '%{http_code} %{time_total}' \
        "http://127.0.0.1:${PORT}${HEALTH_PATH:-/}" 2>/dev/null || echo "000 0")
    if [ "$code" = "200" ]; then st=0; else st=2; fi
    echo "$st paas_health_$APP time=${t}s HTTP $code from ${HEALTH_PATH:-/} on port $PORT"

    # ---- certificate expiry per domain (SNI against local Caddy) ----
    for d in ${DOMAINS//,/ } ${SYSTEM_DOMAIN:-}; do
        end=$(echo | timeout 5 openssl s_client -servername "$d" -connect 127.0.0.1:443 2>/dev/null \
              | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
        svc="paas_cert_${APP}_${d//[.-]/_}"
        if [ -z "$end" ]; then
            echo "3 $svc - could not read certificate for $d"
        else
            days=$(( ( $(date -d "$end" +%s) - NOW ) / 86400 ))
            st=0; [ "$days" -lt 21 ] && st=1; [ "$days" -lt 7 ] && st=2
            echo "$st $svc days=$days certificate for $d expires in $days days"
        fi
    done

    # ---- last deployment (CRIT on failed -> rides the existing alert chain) ----
    row=$(sqlite3 "$DB" "SELECT status||'|'||COALESCE(substr(commit_sha,1,8),'-')||'|'||COALESCE(commit_msg, COALESCE(step,''))||'|'||started_at FROM deployments WHERE app='$APP' ORDER BY id DESC LIMIT 1;" 2>/dev/null)
    if [ -z "$row" ]; then
        echo "0 paas_deploy_$APP - no deployments yet"
    else
        IFS='|' read -r dstatus dsha dmsg dstart <<<"$row"
        case "$dstatus" in
            live)   echo "0 paas_deploy_$APP - last deploy OK: $dsha ($dmsg) at $dstart UTC" ;;
            failed) echo "2 paas_deploy_$APP - LAST DEPLOY FAILED: $dsha ($dmsg) at $dstart UTC" ;;
            *)      echo "0 paas_deploy_$APP - deployment in progress: $dstatus" ;;
        esac
    fi

    # ---- process state: pm2 (node) / php-fpm pool (laravel, + optional queue worker) ----
    if [ "$RUNTIME" = "laravel" ]; then
        PV="${PHP_VERSION:-${PHP_DEFAULT:-8.3}}"
        if [ -S "/run/php/paas-$APP.sock" ] && systemctl is-active --quiet "php$PV-fpm"; then
            echo "0 paas_fpm_$APP - php$PV-fpm pool paas-$APP listening"
        elif systemctl is-active --quiet "php$PV-fpm"; then
            echo "2 paas_fpm_$APP - php$PV-fpm active but socket /run/php/paas-$APP.sock missing (pool not loaded?)"
        else
            echo "2 paas_fpm_$APP - php$PV-fpm NOT active"
        fi
        if [ "$QUEUE_WORKER" = "on" ]; then
            qst=$(echo "$JL" | jq -r --arg n "$APP-queue" '[.[]|select(.name==$n)][0].pm2_env.status // "absent"' 2>/dev/null)
            case "$qst" in
                online) echo "0 paas_queue_$APP - queue worker online" ;;
                absent) echo "1 paas_queue_$APP - queue worker enabled but no pm2 process" ;;
                *)      echo "2 paas_queue_$APP - queue worker pm2 status: $qst" ;;
            esac
        fi
    else
        pmst=$(echo "$JL" | jq -r --arg n "$APP" '[.[]|select(.name==$n)][0].pm2_env.status // "absent"' 2>/dev/null)
        case "$pmst" in
            online) echo "0 paas_pm2_$APP - process online" ;;
            absent) echo "1 paas_pm2_$APP - no pm2 process registered" ;;
            *)      echo "2 paas_pm2_$APP - pm2 status: $pmst" ;;
        esac
    fi

    # ---- 5xx today (from the traffic rollup) ----
    s5=$(sqlite3 "$DB" "SELECT COALESCE(SUM(s5xx),0) FROM traffic_daily WHERE app='$APP' AND day=date('now');" 2>/dev/null)
    s5=${s5:-0}
    st=0; [ "$s5" -gt 50 ] && st=1; [ "$s5" -gt 200 ] && st=2
    echo "$st paas_5xx_$APP errors=$s5 $s5 server errors today (rollup lag up to 5 min)"
done

# ---- platform-level ----
PLATFORM_SVCS="caddy varnish"
# WITH_LARAVEL servers: every installed fpm master + mariadb
for u in /etc/systemd/system/multi-user.target.wants/php*-fpm.service; do
    [ -e "$u" ] && PLATFORM_SVCS="$PLATFORM_SVCS $(basename "$u" .service)"
done
[ -f /srv/paas/db-admin.cnf ] && PLATFORM_SVCS="$PLATFORM_SVCS mariadb"
for svc in $PLATFORM_SVCS; do
    if systemctl is-active --quiet "$svc"; then
        echo "0 paas_svc_$svc - service active"
    else
        echo "2 paas_svc_$svc - service NOT active"
    fi
done

# ---- database backups (WITH_LARAVEL servers with at least one dump) ----
if [ -f /srv/paas/db-admin.cnf ]; then
    newest=$(sudo -u deploy -H bash -c 'ls -1t /srv/paas/backups/db/*.sql.gz 2>/dev/null | head -1')
    if [ -n "$newest" ]; then
        age=$(( NOW - $(sudo -u deploy -H stat -c %Y "$newest") ))
        st=0; [ "$age" -gt 108000 ] && st=1; [ "$age" -gt 194400 ] && st=2
        echo "$st paas_db_backup age=${age}s newest dump $(( age / 3600 ))h ago ($(basename "$newest"))"
    else
        echo "0 paas_db_backup - no app databases backed up yet"
    fi
fi

STATE_FILE=/srv/paas/logs/caddy/.rollup-state.json
if [ -f "$STATE_FILE" ]; then
    age=$(( NOW - $(stat -c %Y "$STATE_FILE") ))
    st=0; [ "$age" -gt 900 ] && st=1; [ "$age" -gt 3600 ] && st=2
    echo "$st paas_traffic_rollup age=${age}s last rollup ${age}s ago"
else
    echo "1 paas_traffic_rollup - no rollup state yet"
fi
