#!/usr/bin/env bash
#
# onx-modsec-rule-detail — Tek bir rule_id için tam SecRule source + metadata.
#
# Tüm CRS rules klasörlerinde rule_id arar, awk ile continuation lines'ı collapse eder.
#
# Input: {"rule_id":"942100"}
# Output: {"rule_id":"...","source":"...","category":"...","severity":"...","tag":"...","description":"...","phase":N,"file_path":"..."}

set -euo pipefail

readonly RULES_DIRS=(
    "/etc/httpd/modsecurity.d/owasp-crs/rules"
    "/etc/modsecurity.d/owasp-crs/rules"
    "/etc/httpd/modsecurity.d"
    "/etc/nginx/modsec/coreruleset/rules"
)

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

if ! [[ "$rule_id" =~ ^[0-9]{6}$ ]]; then
    jq -nc '{ok:false,error:"valid 6-digit rule_id required"}' >&2
    exit 1
fi

# Hangi dosyada olduğunu bul
found_file=""
for dir in "${RULES_DIRS[@]}"; do
    [[ ! -d "$dir" ]] && continue
    matched=$(grep -rl "id:${rule_id}\b\|id:'${rule_id}'" "$dir"/ 2>/dev/null | head -1 || true)
    if [[ -n "$matched" ]]; then
        found_file="$matched"
        break
    fi
done

if [[ -z "$found_file" ]]; then
    jq -nc --arg rid "$rule_id" '{ok:false,error:"rule not found",rule_id:$rid}' >&2
    exit 2
fi

# Source code — id:NNNN içeren SecRule bloğunu çek
# Continuation line aware (backslash sonu)
source_block=$(awk -v rid="id:${rule_id}" '
    /^[[:space:]]*Sec(Rule|Action)/ {
        block = $0 "\n"
        cont = ($0 ~ /\\[[:space:]]*$/) ? 1 : 0
        while (cont) {
            if ((getline line) > 0) {
                block = block line "\n"
                cont = (line ~ /\\[[:space:]]*$/) ? 1 : 0
            } else { cont = 0 }
        }
        if (block ~ rid) print block
        block = ""
    }
' "$found_file" | head -100)

# Parse metadata
category=""
severity=""
tag=""
description=""
phase=2

if [[ -n "$source_block" ]]; then
    tag=$(echo "$source_block" | grep -oE "tag:'[^']+'" | head -1 | sed "s/tag:'//;s/'$//" || echo "")
    severity=$(echo "$source_block" | grep -oE "severity:'[A-Z]+'" | head -1 | sed "s/severity:'//;s/'$//" || echo "")
    description=$(echo "$source_block" | grep -oE "msg:'[^']+'" | head -1 | sed "s/msg:'//;s/'$//" || echo "")
    phase=$(echo "$source_block" | grep -oE "phase:[0-9]" | head -1 | cut -d: -f2 || echo "2")
fi

# Category from filename
category=$(basename "$found_file" .conf | sed 's/^REQUEST-[0-9]\+-//;s/^[0-9]\+-//;s/_/ /g')

jq -nc \
    --arg rule_id "$rule_id" \
    --arg source "$source_block" \
    --arg category "$category" \
    --arg severity "$severity" \
    --arg tag "$tag" \
    --arg description "$description" \
    --argjson phase "$phase" \
    --arg file_path "$found_file" \
    '{ok:true,rule_id:$rule_id,source:$source,category:$category,severity:$severity,tag:$tag,description:$description,phase:$phase,file_path:$file_path}'
