#!/usr/bin/env bash
#
# onx-fail2ban-banned-list — Tüm jail'lerde aktif banlı IP'leri konsolide listele.
#
# Tercih: fail2ban SQLite DB (timeofban+bantime > şu an). Yoksa fail2ban-client status.
# Output: {"bans":[{jail,ip,country_code,banned_at,expires_at,failed_attempts}],"total":N}

set -euo pipefail

readonly DB="/var/lib/fail2ban/fail2ban.sqlite3"

bans_json="[]"

# ── Strategy 1: SQLite DB (en güvenilir) ──────────────────────────────────
if [[ -r "$DB" ]] && command -v sqlite3 &>/dev/null; then
    tmp="$(mktemp)"
    trap 'rm -f "$tmp"' EXIT

    # Aktif banlar
    sqlite3 -separator '|' "$DB" \
        "SELECT jail, ip,
                datetime(timeofban,'unixepoch') AS banned_at,
                datetime(timeofban+bantime,'unixepoch') AS expires_at,
                COALESCE(json_extract(data,'$.matches.length()'),0) AS attempts
         FROM bans
         WHERE timeofban + bantime > strftime('%s','now')
         ORDER BY timeofban DESC" 2>/dev/null > "$tmp" || true

    bans_json="["
    first=1
    while IFS='|' read -r jail ip banned_at expires_at attempts; do
        [[ -z "$ip" ]] && continue

        cc=""
        if [[ -d /var/lib/onox/geoip/cidrs ]] && command -v grepcidr &>/dev/null && [[ "$ip" != *:* ]]; then
            for f in /var/lib/onox/geoip/cidrs/*.txt; do
                [[ -f "$f" ]] || continue
                if grepcidr "$ip" "$f" &>/dev/null; then
                    cc="$(basename "$f" .txt | tr '[:lower:]' '[:upper:]')"
                    break
                fi
            done
        fi

        [[ $first -eq 0 ]] && bans_json+=","
        first=0
        bans_json+=$(jq -nc \
            --arg jail "$jail" --arg ip "$ip" --arg cc "$cc" \
            --arg banned_at "$banned_at" --arg expires_at "$expires_at" \
            --argjson attempts "${attempts:-0}" \
            '{jail:$jail,ip:$ip,country_code:$cc,banned_at:$banned_at,expires_at:$expires_at,failed_attempts:$attempts}')
    done < "$tmp"
    bans_json+="]"
fi

# ── Strategy 2: fail2ban-client status fallback ───────────────────────────
if [[ "$bans_json" == "[]" ]] && command -v fail2ban-client &>/dev/null; then
    jails_raw="$(fail2ban-client status 2>/dev/null | grep "Jail list" | cut -d: -f2 || echo "")"
    bans_json="["
    first=1

    IFS=',' read -ra jails_arr <<<"$jails_raw"
    for jail in "${jails_arr[@]}"; do
        jail="$(echo "$jail" | tr -d ' \t')"
        [[ -z "$jail" ]] && continue

        ips_raw="$(fail2ban-client status "$jail" 2>/dev/null \
            | grep "Banned IP list" | cut -d: -f2 | tr -d ' \t' || echo "")"
        [[ -z "$ips_raw" ]] && continue

        bantime=$(fail2ban-client get "$jail" bantime 2>/dev/null || echo 3600)
        banned_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
        expires_at="$(date -u -d "+${bantime} seconds" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo "$banned_at")"

        IFS=',' read -ra ip_arr <<<"$ips_raw"
        for ip in "${ip_arr[@]}"; do
            [[ -z "$ip" ]] && continue

            cc=""
            if [[ -d /var/lib/onox/geoip/cidrs ]] && command -v grepcidr &>/dev/null && [[ "$ip" != *:* ]]; then
                for f in /var/lib/onox/geoip/cidrs/*.txt; do
                    [[ -f "$f" ]] || continue
                    if grepcidr "$ip" "$f" &>/dev/null; then
                        cc="$(basename "$f" .txt | tr '[:lower:]' '[:upper:]')"
                        break
                    fi
                done
            fi

            [[ $first -eq 0 ]] && bans_json+=","
            first=0
            bans_json+=$(jq -nc \
                --arg jail "$jail" --arg ip "$ip" --arg cc "$cc" \
                --arg banned_at "$banned_at" --arg expires_at "$expires_at" \
                '{jail:$jail,ip:$ip,country_code:$cc,banned_at:$banned_at,expires_at:$expires_at,failed_attempts:0}')
        done
    done
    bans_json+="]"
fi

total=$(echo "$bans_json" | jq 'length')

jq -nc --argjson bans "$bans_json" --argjson total "$total" \
    '{ok:true,bans:$bans,total:$total}'
