#!/usr/bin/env bash
# onx-rspamd-whitelist — Rspamd multimap.conf üzerinden whitelist/blacklist yönetimi.
#
# Multimap modülü Rspamd'da pattern-based list eşleme yapar. Onoxsoft 4 liste tutar:
#   /etc/rspamd/local.d/maps.d/onx-whitelist-from.map  → SYMBOL: WHITELIST_FROM (skor -10)
#   /etc/rspamd/local.d/maps.d/onx-blacklist-from.map  → SYMBOL: BLACKLIST_FROM (skor +20)
#   /etc/rspamd/local.d/maps.d/onx-whitelist-ip.map    → SYMBOL: WHITELIST_IP   (skor -10)
#   /etc/rspamd/local.d/maps.d/onx-blacklist-ip.map    → SYMBOL: BLACKLIST_IP   (skor +20)
#
# stdin: {
#   "op": "list|add|remove",
#   "type": "whitelist_from|blacklist_from|whitelist_ip|blacklist_ip",
#   "value": "@example.com | foo@bar.com | 1.2.3.4 | 10.0.0.0/8"
# }
# stdout (op=list):   {"type":"...","entries":["@a.com","b@c.com",...]}
# stdout (add/remove):{"type":"...","op":"...","value":"...","ok":true,"count":N}

set -euo pipefail
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=/dev/null
source "${SCRIPT_DIR}/_lib/common.sh"

require_root
require_cmd rspamadm

onx_json_input

OP=$(onx_json_field "op" "list")
TYPE=$(onx_json_field "type" "")
VALUE=$(onx_json_field "value" "")

if ! [[ "$OP" =~ ^(list|add|remove)$ ]]; then
    onx_die 1 "Geçersiz op: list|add|remove olmalı"
fi

if ! [[ "$TYPE" =~ ^(whitelist_from|blacklist_from|whitelist_ip|blacklist_ip)$ ]]; then
    onx_die 1 "Geçersiz type: whitelist_from|blacklist_from|whitelist_ip|blacklist_ip olmalı"
fi

MAPS_DIR="/etc/rspamd/local.d/maps.d"
mkdir -p "$MAPS_DIR"

case "$TYPE" in
    whitelist_from) MAP_FILE="${MAPS_DIR}/onx-whitelist-from.map" ;;
    blacklist_from) MAP_FILE="${MAPS_DIR}/onx-blacklist-from.map" ;;
    whitelist_ip)   MAP_FILE="${MAPS_DIR}/onx-whitelist-ip.map" ;;
    blacklist_ip)   MAP_FILE="${MAPS_DIR}/onx-blacklist-ip.map" ;;
esac

touch "$MAP_FILE"
chmod 644 "$MAP_FILE"

# ─── add/remove için value validasyonu ─────────────────────────────────────
if [[ "$OP" == "add" || "$OP" == "remove" ]]; then
    if [[ -z "$VALUE" ]]; then
        onx_die 1 "value boş olamaz"
    fi
    # Lowercase
    VALUE="$(printf '%s' "$VALUE" | tr '[:upper:]' '[:lower:]')"

    # FROM listeleri: e-mail (foo@bar.com) veya @domain
    if [[ "$TYPE" =~ _from$ ]]; then
        if ! [[ "$VALUE" =~ ^@[a-z0-9.-]+\.[a-z]{2,}$ ]] && \
           ! [[ "$VALUE" =~ ^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$ ]]; then
            onx_die 1 "Geçersiz from değeri: 'foo@bar.com' veya '@bar.com' formatında olmalı"
        fi
    fi

    # IP listeleri: IPv4 (a.b.c.d), IPv4 CIDR (a.b.c.d/n), IPv6 (lite)
    if [[ "$TYPE" =~ _ip$ ]]; then
        if ! [[ "$VALUE" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}(/[0-9]{1,2})?$ ]] && \
           ! [[ "$VALUE" =~ ^[0-9a-f:]+(/[0-9]{1,3})?$ ]]; then
            onx_die 1 "Geçersiz IP değeri: '1.2.3.4' veya '10.0.0.0/8' formatında olmalı"
        fi
    fi
fi

# ─── list ───────────────────────────────────────────────────────────────────
if [[ "$OP" == "list" ]]; then
    ENTRIES_JSON='[]'
    if [[ -s "$MAP_FILE" ]]; then
        ENTRIES_JSON=$(grep -v '^#' "$MAP_FILE" | grep -v '^[[:space:]]*$' | jq -R '.' | jq -s '.')
    fi
    jq -n --arg t "$TYPE" --argjson entries "$ENTRIES_JSON" \
        '{type:$t, entries:$entries, count:($entries|length)}'
    exit 0
fi

# ─── add ────────────────────────────────────────────────────────────────────
if [[ "$OP" == "add" ]]; then
    if grep -Fxq "$VALUE" "$MAP_FILE" 2>/dev/null; then
        # Zaten var — idempotent başarı
        COUNT=$(grep -cv -E '^#|^[[:space:]]*$' "$MAP_FILE" || echo 0)
        jq -n --arg t "$TYPE" --arg v "$VALUE" --argjson c "$COUNT" \
            '{type:$t, op:"add", value:$v, ok:true, count:$c, already_existed:true}'
        exit 0
    fi
    printf '%s\n' "$VALUE" >> "$MAP_FILE"
    COUNT=$(grep -cv -E '^#|^[[:space:]]*$' "$MAP_FILE" || echo 0)
    onx_audit "rspamd-whitelist" "ADD type=${TYPE} value=${VALUE}"
    jq -n --arg t "$TYPE" --arg v "$VALUE" --argjson c "$COUNT" \
        '{type:$t, op:"add", value:$v, ok:true, count:$c}'
    exit 0
fi

# ─── remove ─────────────────────────────────────────────────────────────────
if [[ "$OP" == "remove" ]]; then
    TMP_FILE=$(mktemp -t onx-map.XXXXXX)
    grep -Fxv "$VALUE" "$MAP_FILE" > "$TMP_FILE" || true
    mv "$TMP_FILE" "$MAP_FILE"
    chmod 644 "$MAP_FILE"
    COUNT=$(grep -cv -E '^#|^[[:space:]]*$' "$MAP_FILE" 2>/dev/null || echo 0)
    onx_audit "rspamd-whitelist" "REMOVE type=${TYPE} value=${VALUE}"
    jq -n --arg t "$TYPE" --arg v "$VALUE" --argjson c "$COUNT" \
        '{type:$t, op:"remove", value:$v, ok:true, count:$c}'
    exit 0
fi
