#!/usr/bin/env bash
#
# onx-modsec-audit-event-detail — tek event_id için full request/response.
# DRIVER-AWARE + format-agnostic (v3.41): aktif driver'ın log yolunu kullanır,
# JSON-lines ve native serial (2/3-tire boundary) formatlarını destekler.
#
# Input:  {"event_id":"...", "driver":"auto|apache|nginx|ols|caddy"}
# Output: {request_headers, request_body, response_headers, all_matched_rules:[...]}

set -uo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=_lib/common.sh
source "${SCRIPT_DIR}/_lib/common.sh"
set +e   # common.sh'in set -e'sini geri al — grep no-match (boş section) abort etmesin

input="$(cat 2>/dev/null || echo '{}')"
echo "$input" | jq -e 'type == "object"' >/dev/null 2>&1 || input='{}'
event_id="$(echo "$input" | jq -r '.event_id // empty')"
req_driver="$(echo "$input" | jq -r '.driver // "auto"')"

[[ -z "$event_id" ]] && { jq -nc '{ok:false,error:"event_id required"}' >&2; exit 1; }
[[ "$event_id" =~ ^[A-Za-z0-9_-]{6,80}$ ]] || { jq -nc '{ok:false,error:"invalid event_id format"}' >&2; exit 1; }

DRIVER=$(onx_ws_resolve_driver "$req_driver")
LOG_FILE=$(onx_modsec_audit_log "$DRIVER")
[[ -z "$LOG_FILE" || ! -r "$LOG_FILE" ]] && { jq -nc --arg p "${LOG_FILE:-}" '{ok:false,error:"audit log not readable",path:$p}' >&2; exit 2; }

first_line=$(grep -m1 -v '^[[:space:]]*$' "$LOG_FILE" 2>/dev/null | head -c 8192 || true)
LOG_FORMAT="native"
echo "$first_line" | jq -e 'type == "object"' >/dev/null 2>&1 && LOG_FORMAT="json"

# ── JSON-lines ───────────────────────────────────────────────────────────────
if [[ "$LOG_FORMAT" == "json" ]]; then
    rec=$(grep -F "$event_id" "$LOG_FILE" 2>/dev/null | tail -1)
    [[ -z "$rec" ]] && { jq -nc --arg eid "$event_id" '{ok:false,error:"event not found",event_id:$eid}' >&2; exit 2; }
    echo "$rec" | jq -c --arg eid "$event_id" --arg driver "$DRIVER" '
        def sevword($s): ($s|tostring|ascii_upcase) as $u |
          {"0":"EMERGENCY","1":"ALERT","2":"CRITICAL","3":"ERROR","4":"WARNING","5":"NOTICE","6":"INFO","7":"DEBUG"}[$u] // $u;
        (.transaction // {}) as $tx |
        {
          ok:true, event_id:$eid, driver:$driver,
          request_headers: (($tx.request.headers // {}) | to_entries | map("\(.key): \(.value)") | join("\n")),
          request_body:    (($tx.request.body // "") | tostring),
          response_headers:(($tx.response.headers // {}) | to_entries | map("\(.key): \(.value)") | join("\n")),
          all_matched_rules: [ ($tx.messages // [])[] | {rule_id:((.details.ruleId // "")|tostring), severity:sevword(.details.severity // ""), msg:(.message // "")} ]
        }' 2>/dev/null || jq -nc --arg eid "$event_id" '{ok:false,error:"json parse failed",event_id:$eid}' >&2
    exit 0
fi

# ── native serial — tolerant boundaries ──────────────────────────────────────
block=$(awk -v eid="$event_id" '
    function is_boundary(line) { return (line ~ /^-+[A-Za-z0-9]+-+[A-Z]-+$/) }
    function sect_letter(line) { if (match(line, /[A-Z]-+$/)) return substr(line, RSTART, 1); return "" }
    {
        if (is_boundary($0)) {
            L = sect_letter($0)
            if (L == "A") { capture = 0; buf = $0 "\n"; next }
            if (L == "Z") { buf = buf $0 "\n"; if (capture) { print buf; exit } buf = ""; next }
        }
        buf = buf $0 "\n"
        if (index($0, eid) > 0) capture = 1
    }
' "$LOG_FILE" 2>/dev/null)
[[ -z "$block" ]] && { jq -nc --arg eid "$event_id" '{ok:false,error:"event not found in log",event_id:$eid}' >&2; exit 2; }

extract_section() {  # $1 = section letter
    printf '%s\n' "$block" | awk -v want="$1" '
        function is_boundary(line) { return (line ~ /^-+[A-Za-z0-9]+-+[A-Z]-+$/) }
        function sect_letter(line) { if (match(line, /[A-Z]-+$/)) return substr(line, RSTART, 1); return "" }
        { if (is_boundary($0)) { sect = sect_letter($0); next } if (sect == want) print }
    '
}

request_headers=$(extract_section B | head -c 8000)
request_body=$(extract_section I | head -c 5000)
response_headers=$(extract_section F | head -c 8000)

matched_rules_json=$(extract_section H \
    | grep -oE '\[id "[0-9]+"\][^[]*\[msg "[^"]*"\][^[]*\[severity "[A-Za-z0-9]+"\]' \
    | while IFS= read -r m; do
        rid=$(echo "$m" | grep -oE 'id "[0-9]+"' | grep -oE '[0-9]+')
        msg=$(echo "$m" | grep -oE 'msg "[^"]+"' | sed 's/msg "//;s/"$//')
        sev=$(echo "$m" | grep -oE 'severity "[A-Za-z0-9]+"' | sed 's/severity "//;s/"$//')
        [[ -z "$rid" ]] && continue
        sev=$(onx_modsec_sev_word "$sev")
        jq -nc --arg rid "$rid" --arg msg "$msg" --arg sev "$sev" '{rule_id:$rid,severity:$sev,msg:$msg}'
    done | jq -cs '.' 2>/dev/null || echo "[]")
[[ -z "$matched_rules_json" ]] && matched_rules_json="[]"

jq -nc \
    --arg event_id "$event_id" --arg req_headers "$request_headers" --arg req_body "$request_body" \
    --arg resp_headers "$response_headers" --argjson all_matched_rules "$matched_rules_json" --arg driver "$DRIVER" \
    '{ok:true, event_id:$event_id, request_headers:$req_headers, request_body:$req_body, response_headers:$resp_headers, all_matched_rules:$all_matched_rules, driver:$driver}'
