#!/usr/bin/env bash
#
# onx-fail2ban-bulk-ban — Bir liste IP'yi belirtilen jail'de banla.
#
# Input: {"jail": "sshd", "ips": ["1.2.3.4", "5.6.7.8"]}
# Output: {"ok":true,"requested":N,"banned":N,"failed":N,"errors":[{ip,error}]}

set -euo pipefail

input="$(cat)"
jail="$(echo "$input" | jq -r '.jail // empty')"
ips_count=$(echo "$input" | jq '.ips // [] | length')

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

if (( ips_count < 1 || ips_count > 500 )); then
    jq -nc '{ok:false,error:"ips array must have 1-500 entries"}' >&2
    exit 1
fi

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

# Check jail is active
if ! fail2ban-client status "$jail" &>/dev/null; then
    jq -nc --arg j "$jail" '{ok:false,error:"jail not active",jail:$j}' >&2
    exit 2
fi

banned=0
failed=0
errors_json="["
first=1

echo "$input" | jq -r '.ips[]' | while read -r ip; do
    [[ -z "$ip" ]] && continue

    # Quick IP validate
    if [[ "$ip" == *:* ]]; then
        if ! [[ "$ip" =~ ^[0-9a-fA-F:]+(/[0-9]{1,3})?$ ]]; then
            failed=$((failed+1))
            continue
        fi
    elif ! [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]{1,2})?$ ]]; then
        failed=$((failed+1))
        continue
    fi

    if fail2ban-client set "$jail" banip "$ip" &>/dev/null; then
        banned=$((banned+1))
        echo "$ip" >> /tmp/onox-bulk-ok-$$
    else
        failed=$((failed+1))
        echo "$ip" >> /tmp/onox-bulk-fail-$$
    fi
done

banned=$(wc -l < /tmp/onox-bulk-ok-$$ 2>/dev/null || echo 0)
failed=$(wc -l < /tmp/onox-bulk-fail-$$ 2>/dev/null || echo 0)
rm -f /tmp/onox-bulk-ok-$$ /tmp/onox-bulk-fail-$$

logger -t "onox-fail2ban" "Bulk ban: jail=$jail requested=$ips_count banned=$banned failed=$failed"

jq -nc \
    --arg jail "$jail" \
    --argjson requested "$ips_count" \
    --argjson banned "$banned" \
    --argjson failed "$failed" \
    '{ok:true,jail:$jail,requested:$requested,banned:$banned,failed:$failed}'
