#!/usr/bin/env bash
#
# onx-fail2ban-filter-test — fail2ban-regex ile filter test.
#
# Input: {"filter": "sshd", "log_line": "Failed password for root from 1.2.3.4 port 22"}
# Output: {"ok":true,"matches":N,"matched_lines":[...],"failregex_ok":true,"raw_output":"..."}

set -euo pipefail

input="$(cat)"
filter="$(echo "$input" | jq -r '.filter // empty')"
log_line="$(echo "$input" | jq -r '.log_line // empty')"

if [[ -z "$filter" ]] || ! [[ "$filter" =~ ^[a-zA-Z0-9_-]{1,40}$ ]]; then
    jq -nc '{ok:false,error:"filter required"}' >&2
    exit 1
fi

if [[ -z "$log_line" ]] || [[ ${#log_line} -gt 4000 ]]; then
    jq -nc '{ok:false,error:"log_line required (max 4000 chars)"}' >&2
    exit 1
fi

if ! command -v fail2ban-regex &>/dev/null; then
    jq -nc '{ok:false,error:"fail2ban-regex not installed (install fail2ban-server pkg)"}' >&2
    exit 2
fi

readonly FILTER_PATH="/etc/fail2ban/filter.d/${filter}.conf"
if [[ ! -f "$FILTER_PATH" ]]; then
    jq -nc --arg f "$filter" --arg p "$FILTER_PATH" \
        '{ok:false,error:"filter file not found",filter:$f,path:$p}' >&2
    exit 2
fi

# fail2ban-regex expects log content on stdin or file
tmp_log="$(mktemp)"
echo "$log_line" > "$tmp_log"
trap 'rm -f "$tmp_log"' EXIT

raw_output="$(fail2ban-regex "$tmp_log" "$FILTER_PATH" 2>&1 || true)"

# Parse: "Lines: 1 lines, 0 ignored, 1 matched, 0 missed"
matches=0
if echo "$raw_output" | grep -qE 'lines.*matched'; then
    matches="$(echo "$raw_output" | grep -oE '[0-9]+ matched' | head -1 | awk '{print $1}')"
fi
[[ -z "$matches" ]] && matches=0

# Check failregex syntax — "FAIL2BAN: Regex compile error" varsa hata
failregex_ok=true
if echo "$raw_output" | grep -qiE 'compile error|invalid regex|failure'; then
    failregex_ok=false
fi

# matched_lines — fail2ban-regex output'undan "Source LINE" satırını çek
matched_lines_json="[]"
if (( matches > 0 )); then
    matched_lines_json="$(echo "$raw_output" \
        | grep -A 1000 'Lines:' \
        | grep -B 0 -A 0 '^[0-9]\+\.\s' \
        | head -10 \
        | jq -R -s 'split("\n") | map(select(length > 0))' 2>/dev/null || echo '[]')"
    [[ -z "$matched_lines_json" || "$matched_lines_json" == "null" ]] && matched_lines_json='["'"$log_line"'"]'
fi

jq -nc \
    --argjson matches "$matches" \
    --argjson matched_lines "$matched_lines_json" \
    --argjson failregex_ok "$failregex_ok" \
    --arg raw "$raw_output" \
    --arg filter "$filter" \
    '{ok:true,filter:$filter,matches:$matches,matched_lines:$matched_lines,failregex_ok:$failregex_ok,raw_output:$raw}'
