#!/usr/bin/env bash
# onx-clamav-scan — bir yol/dizini tara; bulguda on_infection politikasını uygula
source "$(dirname "$0")/_lib/common.sh"
require_root
require_cmd jq
onx_json_input

SCAN_PATH="$(onx_json_field path '')"
ACTION="$(onx_json_field action 'quarantine')"   # quarantine|delete|notify
QDIR="/var/lib/onoxsoft/quarantine"
[[ -n "$SCAN_PATH" ]] || onx_die 1 "path required"
# Güvenlik: yalnız izinli kökler
case "$SCAN_PATH" in
    /home/*|/var/www/*|/tmp/*) : ;;
    *) onx_die 1 "path not allowed: $SCAN_PATH" ;;
esac
SCAN_PATH="$(realpath -m "$SCAN_PATH" 2>/dev/null || printf '%s' "$SCAN_PATH")"
case "$SCAN_PATH" in /home/*|/var/www/*|/tmp/*) : ;; *) onx_die 1 "path not allowed (resolved): $SCAN_PATH" ;; esac
[[ -e "$SCAN_PATH" ]] || onx_die 2 "path not found: $SCAN_PATH"
mkdir -p "$QDIR"; chmod 700 "$QDIR"

# Tek-tarama kilidi: eşzamanlı tarama bellek/load baskısını KATLAR (sunucu RAM'i dar;
# sweep tüm hesapları aynı anda kuyruğa atabiliyor) → non-blocking flock ile engelle.
exec 9>/var/lock/onx-clamav-scan.lock
flock -n 9 || onx_die 3 "Başka bir tarama sürüyor — eşzamanlı tarama engellendi (kaynak koruması)"

MAX_SECONDS="$(onx_json_field max_seconds '7200')"
[[ "$MAX_SECONDS" =~ ^[0-9]+$ ]] || MAX_SECONDS=7200
IONICE=""
command -v ionice >/dev/null 2>&1 && IONICE="ionice -c 3"

START=$(date +%s.%N)
# clamdscan (resident clamd → hafif) tercih; yoksa clamscan (full sig DB → ağır) fallback.
# --multiscan KALDIRILDI: tüm çekirdeklere yayılıp load uçuruyordu (dar RAM/CPU sunucu).
# nice -19 + ionice -c3 (idle): tarama en düşük öncelikle → kutuyu devirmez. timeout: runaway kesilir.
SCANNER_CMD=(clamscan)
command -v clamdscan &>/dev/null && SCANNER_CMD=(clamdscan --fdpass)
# Çıktı: her bulaşık satır "FILE: SIG FOUND"
TMP="$(mktemp)"
trap 'rm -f "$TMP"' EXIT
set +e
nice -n 19 $IONICE timeout "${MAX_SECONDS}" "${SCANNER_CMD[@]}" -r --infected --no-summary "$SCAN_PATH" >"$TMP" 2>/dev/null
RC=$?
set -e
# Kısmi/iptal taramayı "temiz" SANMA: timeout (124) veya clamd/scan hatası (rc>=2) → fail.
[[ "$RC" == "124" ]] && onx_die 3 "Tarama zaman aşımı (${MAX_SECONDS}s) — kısmi sonuç temiz sayılmaz"
[[ "$RC" -ge 2 ]] && onx_die 3 "Tarama hatası (clamdscan rc=${RC})"
END=$(date +%s.%N)
DUR=$(awk "BEGIN{printf \"%.2f\", $END-$START}")
SCANNED=$(find -- "$SCAN_PATH" -type f 2>/dev/null | wc -l)

RAW_INFECTED="[]"
if [[ -s "$TMP" ]]; then
    RAW_INFECTED="$(jq -R -s '
        split("\n") | map(select(length>0) | capture("(?<path>.*): (?<virus>.*) FOUND$")) ' "$TMP" 2>/dev/null || echo "[]")"
fi
rm -f "$TMP"

INFECTED_JSON="[]"
if [[ "$(jq 'length' <<<"$RAW_INFECTED")" -gt 0 ]]; then
    while IFS= read -r entry; do
        P="$(jq -r '.path' <<<"$entry")"
        V="$(jq -r '.virus' <<<"$entry")"
        QP="null"
        if [[ -f "$P" ]]; then
            if [[ "$ACTION" == "delete" ]]; then
                rm -f -- "$P"
            elif [[ "$ACTION" == "quarantine" ]]; then
                DEST="$QDIR/$(date +%s%N)_$(basename "$P").quar"
                if mv -- "$P" "$DEST" 2>/dev/null; then
                    chmod 600 "$DEST"
                    QP="$(jq -n --arg d "$DEST" '$d')"
                fi
            fi
            # notify: dosyaya dokunma, QP null kalır
        fi
        INFECTED_JSON="$(jq --arg p "$P" --arg v "$V" --argjson qp "$QP" \
            '. + [{path:$p, virus:$v, quarantine_path:$qp}]' <<<"$INFECTED_JSON")"
    done < <(jq -c '.[]' <<<"$RAW_INFECTED")
fi

CLEAN=true; [[ "$(jq 'length' <<<"$INFECTED_JSON")" -gt 0 ]] && CLEAN=false
json_ok "$(jq -n --argjson clean "$CLEAN" --argjson infected "$INFECTED_JSON" \
    --argjson scanned_files "${SCANNED:-0}" --argjson duration_seconds "$DUR" \
    '{clean:$clean,infected:$infected,scanned_files:$scanned_files,duration_seconds:$duration_seconds}')"
