#!/usr/bin/env python3
"""
checkmk local check: ARIA Geoblocking

Wertet die Log-Datei von aria_geoblock.py aus und meldet an checkmk, ob
der letzte Lauf (systemd-Timer: beim Boot + taeglich) erfolgreich und
aktuell war.

INSTALLATION:
  1. LOG_FILE unten auf den Pfad anpassen, der in der aria_geoblock.ini
     unter [geoblock] log_file konfiguriert ist (Default passt zum
     mitgelieferten install_aria_geoblock.sh).
  2. Datei ausfuehrbar machen und ins checkmk-Agent local-Verzeichnis legen:
       cp aria_geoblock_checkmk /usr/lib/check_mk_agent/local/
       chmod 755 /usr/lib/check_mk_agent/local/aria_geoblock_checkmk
     (Pfad haengt von Distro/Checkmk-Setup ab - ueblich sind
      /usr/lib/check_mk_agent/local/ oder bei OMD-Sites
      ~/local/lib/check_mk_agent/local/. Bei Bedarf: 'check_mk_agent' Pfad
      des jeweiligen Hosts pruefen.)
  3. Naechster Agent-Abruf zeigt den Service "ARIA_Geoblock" in checkmk.

AUSGABE-LOGIK:
  - Keine Log-Datei / keine RESULT-Zeile gefunden -> UNKNOWN (3)
  - Letzter Lauf hatte status=ERROR                -> CRIT (2)
  - Letzter erfolgreicher Lauf zu alt (> CRIT_AGE)  -> CRIT (2)
  - Letzter erfolgreicher Lauf etwas alt (> WARN)   -> WARN (1)
  - Sonst                                           -> OK (0)
"""

import datetime
import os
import re
import time

# --- Anpassen: muss zum log_file-Pfad aus der aria_geoblock.ini passen ---
LOG_FILE = "/var/log/aria_geoblock/aria_geoblock.log"

# Timer laeuft taeglich -> grosszuegig bemessen, damit ein einzelner
# verpasster Lauf (Host kurz aus) nicht sofort CRIT ausloest.
WARN_AGE_SEC = 36 * 3600   # 36h
CRIT_AGE_SEC = 72 * 3600   # 72h

SERVICE_NAME = "ARIA_Geoblock"

# Beispiel-Zeile in der Log-Datei (von aria_geoblock.py log_result() geschrieben):
# 2026-07-21T10:00:00+02:00 [geoblock] RESULT ts=2026-07-21T10:00:00+02:00
#   status=OK action=apply countries=4 entries=123456 msg="Geoblock aktualisiert (..)"
RESULT_RE = re.compile(
    r'RESULT ts=(?P<ts>\S+) status=(?P<status>\S+) action=(?P<action>\S+)'
    r'(?: countries=(?P<countries>\d+))?(?: entries=(?P<entries>\d+))? '
    r'msg="(?P<msg>.*)"\s*$'
)


def emit(status, perfdata, text):
    perf = perfdata if perfdata else "-"
    print(f"{status} {SERVICE_NAME} {perf} {text}")


def main():
    if not os.path.isfile(LOG_FILE):
        emit(3, "-", f"Log-Datei nicht gefunden ({LOG_FILE}) - lief aria_geoblock.py schon einmal mit --apply?")
        return

    last_match = None
    try:
        with open(LOG_FILE, "r", encoding="utf-8", errors="ignore") as f:
            for line in f:
                m = RESULT_RE.search(line.strip())
                if m:
                    last_match = m  # letzte Übereinstimmung gewinnt (Datei waechst append-only)
    except OSError as e:
        emit(3, "-", f"Log-Datei nicht lesbar: {e}")
        return

    if not last_match:
        emit(3, "-", f"Keine RESULT-Zeile in {LOG_FILE} gefunden - lief aria_geoblock.py schon mit --apply?")
        return

    ts_raw = last_match.group("ts")
    action = last_match.group("action")
    status_str = last_match.group("status")
    countries = last_match.group("countries")
    entries = last_match.group("entries")
    msg = last_match.group("msg")

    try:
        last_dt = datetime.datetime.fromisoformat(ts_raw)
        age = time.time() - last_dt.timestamp()
    except ValueError:
        emit(3, "-", f"Konnte Zeitstempel nicht parsen: {ts_raw}")
        return

    perf = f"age={int(age)}s;{WARN_AGE_SEC};{CRIT_AGE_SEC}"
    if entries is not None:
        perf += f"|entries={entries}"

    if status_str != "OK":
        emit(2, perf, f"Letzter Lauf ({action}) fehlgeschlagen: {msg}")
        return

    if age > CRIT_AGE_SEC:
        emit(2, perf, f"Letzter erfolgreicher Lauf ist {int(age / 3600)}h alt "
                       f"(Schwelle {CRIT_AGE_SEC // 3600}h) - Timer laeuft nicht mehr? Letzte msg: {msg}")
        return
    if age > WARN_AGE_SEC:
        emit(1, perf, f"Letzter erfolgreicher Lauf ist {int(age / 3600)}h alt "
                       f"(Schwelle {WARN_AGE_SEC // 3600}h) - Letzte msg: {msg}")
        return

    extra = f", {countries} Laender" if countries else ""
    emit(0, perf, f"OK - letzter Lauf vor {int(age / 60)}min{extra}: {msg}")


if __name__ == "__main__":
    main()
