#!/usr/bin/env bash
#
# onx-firewall-ip-lookup — IP araştırma aracı.
#
# Sources:
#   - reverse DNS (dig -x)
#   - whois (whois.iana.org → regional RIR)
#   - GeoIP (local cidrs/ cache from RIR delegated files)
#   - Reputation: Team Cymru DNS lookup (origin-as.cymru.com)
#   - nftables ruleset scan (current block sets'te var mı)
#
# Input (stdin JSON): {"ip": "8.8.8.8"}
# Output: çoklu alan içeren JSON

set -euo pipefail

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

if [[ -z "$ip" ]]; then
    jq -nc '{ok:false,error:"ip required"}' >&2
    exit 1
fi

# Validate IP
if [[ "$ip" == *:* ]]; then
    # IPv6
    if command -v python3 &>/dev/null && ! python3 -c "import ipaddress; ipaddress.ip_address('$ip')" &>/dev/null; then
        jq -nc --arg ip "$ip" '{ok:false,error:"invalid ipv6",ip:$ip}' >&2
        exit 1
    fi
    family="v6"
else
    if ! [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
        jq -nc --arg ip "$ip" '{ok:false,error:"invalid ipv4",ip:$ip}' >&2
        exit 1
    fi
    family="v4"
fi

# ── Reverse DNS ───────────────────────────────────────────────────────────
reverse_dns=""
if command -v dig &>/dev/null; then
    reverse_dns="$(dig +short +time=3 +tries=1 -x "$ip" 2>/dev/null | head -1 | sed 's/\.$//' || echo "")"
fi

# ── Whois (limit 80 line) ─────────────────────────────────────────────────
whois_out=""
asn=""
org=""
country=""
if command -v whois &>/dev/null; then
    whois_out="$(timeout 8 whois "$ip" 2>/dev/null | head -80 || true)"

    # Try multiple field names — ARIN vs RIPE vs APNIC differ
    asn="$(echo "$whois_out" | grep -iE '^(origin(as)?|aut-num|originas)[[:space:]]*:' | head -1 | sed -E 's/^[^:]+:[[:space:]]*//' | tr -d '\r' | awk '{print $1}')"
    org="$(echo "$whois_out" | grep -iE '^(org-name|orgname|netname|descr|owner|organisation|organization)[[:space:]]*:' | head -1 | sed -E 's/^[^:]+:[[:space:]]*//' | tr -d '\r')"
    country="$(echo "$whois_out" | grep -iE '^country[[:space:]]*:' | head -1 | sed -E 's/^[^:]+:[[:space:]]*//' | tr -d '\r' | awk '{print toupper($1)}')"
fi

# ── Team Cymru DNS lookup (fallback for ASN) ──────────────────────────────
# Format: reverse IP + .origin.asn.cymru.com → "AS | CIDR | country | RIR | date"
if [[ -z "$asn" ]] && [[ "$family" == "v4" ]] && command -v dig &>/dev/null; then
    rev_ip="$(echo "$ip" | awk -F. '{print $4"."$3"."$2"."$1}')"
    cymru_result="$(dig +short +time=3 TXT "${rev_ip}.origin.asn.cymru.com" 2>/dev/null | tr -d '"' || echo "")"
    if [[ -n "$cymru_result" ]]; then
        IFS='|' read -ra parts <<<"$cymru_result"
        asn="$(echo "${parts[0]:-}" | tr -d ' ')"
        [[ -z "$country" ]] && country="$(echo "${parts[2]:-}" | tr -d ' ')"
    fi
fi

# ── Local GeoIP override (RIR cache daha güncel olabilir) ─────────────────
country_code=""
if [[ -d /var/lib/onox/geoip/cidrs ]] && command -v grepcidr &>/dev/null && [[ "$family" == "v4" ]]; then
    for f in /var/lib/onox/geoip/cidrs/*.txt; do
        [[ -f "$f" ]] || continue
        if grepcidr "$ip" "$f" &>/dev/null; then
            country_code="$(basename "$f" .txt | tr '[:lower:]' '[:upper:]')"
            break
        fi
    done
fi
[[ -z "$country_code" ]] && country_code="$country"

# ── Check if blocked in current ruleset ───────────────────────────────────
is_blocked=false
block_reason=""

if command -v nft &>/dev/null && nft list table inet onox &>/dev/null; then
    # Search each set for this IP
    # nft list set ... gibi komutlar büyük set'lerde yavaş; sayıyı sınırla
    # Strategy: -j JSON output → search elements
    nft_json="$(nft -j list table inet onox 2>/dev/null || echo '{}')"

    if command -v jq &>/dev/null && [[ -n "$nft_json" ]]; then
        # Look in IPv4 country/threat/drop sets
        blocked_in_set="$(echo "$nft_json" | jq -r --arg ip "$ip" '
            .nftables[]?.set? // empty
            | select(.elem? // [] | map(if type == "object" then (.elem // .) else . end) | flatten | any(. == $ip))
            | .name' 2>/dev/null | head -1)"

        if [[ -n "$blocked_in_set" ]]; then
            is_blocked=true
            block_reason="Found in set: $blocked_in_set"
        fi
    fi

    # Trusted set check (positive: explicit allow)
    if [[ "$is_blocked" == "false" ]]; then
        if echo "$nft_json" | jq -e --arg ip "$ip" \
            '.nftables[]?.set? | select(.name == "onox-trusted") | .elem? // [] | map(if type == "object" then (.elem // .) else . end) | any(. == $ip)' \
            &>/dev/null; then
            block_reason="Whitelisted (onox-trusted set)"
        fi
    fi
fi

# ── Check fail2ban DB ──────────────────────────────────────────────────────
banned_in_jails=""
if [[ -r /var/lib/fail2ban/fail2ban.sqlite3 ]] && command -v sqlite3 &>/dev/null; then
    banned_in_jails="$(sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 \
        "SELECT GROUP_CONCAT(jail) FROM bans WHERE ip='$ip' AND timeofban + bantime > strftime('%s','now')" \
        2>/dev/null || echo "")"
    if [[ -n "$banned_in_jails" ]]; then
        is_blocked=true
        block_reason="Banned in fail2ban: $banned_in_jails"
    fi
fi

# Country name (Türkçe)
country_name=""
case "$country_code" in
    TR) country_name="Türkiye" ;; US) country_name="ABD" ;; GB) country_name="İngiltere" ;;
    DE) country_name="Almanya" ;; FR) country_name="Fransa" ;; RU) country_name="Rusya" ;;
    CN) country_name="Çin" ;; KP) country_name="Kuzey Kore" ;; IR) country_name="İran" ;;
    NL) country_name="Hollanda" ;; JP) country_name="Japonya" ;; KR) country_name="Güney Kore" ;;
    BR) country_name="Brezilya" ;; IN) country_name="Hindistan" ;; *) country_name="$country_code" ;;
esac

jq -nc \
    --arg ip "$ip" \
    --arg family "$family" \
    --arg reverse_dns "$reverse_dns" \
    --arg country "$country_name" \
    --arg country_code "$country_code" \
    --arg asn "$asn" \
    --arg org "$org" \
    --arg whois "$whois_out" \
    --argjson is_blocked "$is_blocked" \
    --arg block_reason "$block_reason" \
    --arg banned_in_jails "$banned_in_jails" \
    '{
        ok: true,
        ip: $ip,
        family: $family,
        reverse_dns: $reverse_dns,
        country: $country,
        country_code: $country_code,
        asn: $asn,
        org: $org,
        whois: $whois,
        is_blocked: $is_blocked,
        block_reason: $block_reason,
        banned_in_jails: $banned_in_jails
    }'
