#!/usr/bin/env bash
set -euo pipefail

SCENARIO="${1:-all}"
COUNT="${2:-1}"
DELAY="${3:-0.3}"
FOREVER="false"

for arg in "${@:4}"; do
  case "${arg}" in
    --forever)
      FOREVER="true"
      ;;
    *)
      echo "error: unexpected argument '${arg}'"
      echo "usage: scripts/send-wazuh-test-events.sh [scenario] [count] [delay_seconds] [--forever]"
      exit 1
      ;;
  esac
done

WAZUH_SYSLOG_HOST="${WAZUH_SYSLOG_HOST:-127.0.0.1}"
WAZUH_SYSLOG_PORT="${WAZUH_SYSLOG_PORT:-514}"
WAZUH_TEST_SRC_IP="${WAZUH_TEST_SRC_IP:-203.0.113.10}"
WAZUH_TEST_DOMAIN="${WAZUH_TEST_DOMAIN:-malicious.example}"
WAZUH_TEST_USER="${WAZUH_TEST_USER:-guest.user}"

if ! [[ "${COUNT}" =~ ^[0-9]+$ ]] || [[ "${COUNT}" -lt 1 ]]; then
  echo "error: count must be a positive integer"
  exit 1
fi

if ! [[ "${DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
  echo "error: delay must be numeric (example: 0.5)"
  exit 1
fi

emit_syslog() {
  local msg="$1"
  local sent="false"

  if command -v nc >/dev/null 2>&1; then
    if printf "%s\n" "${msg}" | nc -u -w1 "${WAZUH_SYSLOG_HOST}" "${WAZUH_SYSLOG_PORT}"; then
      sent="true"
    fi
  fi

  if [[ "${sent}" != "true" ]]; then
    if printf "%s\n" "${msg}" >"/dev/udp/${WAZUH_SYSLOG_HOST}/${WAZUH_SYSLOG_PORT}" 2>/dev/null; then
      sent="true"
    fi
  fi

  if [[ "${sent}" != "true" ]]; then
    echo "error: failed to send syslog event to ${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
    echo "hint: install netcat or run with bash UDP support (/dev/udp)"
    return 1
  fi
  echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] sent: ${msg}"
}

random_id() {
  printf "%s" "evt-$(date +%s)-$RANDOM-$RANDOM"
}

send_ioc_dns() {
  local eid
  eid="$(random_id)"
  emit_syslog "<134>$(date '+%b %d %H:%M:%S') soc-test soc_mvp_test=true event_id=${eid} event_type=ioc_dns src_ip=${WAZUH_TEST_SRC_IP} query=${WAZUH_TEST_DOMAIN} action=blocked severity=medium"
}

send_ioc_ips() {
  local eid
  eid="$(random_id)"
  emit_syslog "<134>$(date '+%b %d %H:%M:%S') soc-test soc_mvp_test=true event_id=${eid} event_type=ioc_ips src_ip=${WAZUH_TEST_SRC_IP} dst_ip=198.51.100.55 signature='Known C2 Beacon' severity=high"
}

send_vpn_outside_th() {
  local eid
  eid="$(random_id)"
  emit_syslog "<134>$(date '+%b %d %H:%M:%S') soc-test soc_mvp_test=true event_id=${eid} event_type=vpn_geo_anomaly user=${WAZUH_TEST_USER} src_ip=${WAZUH_TEST_SRC_IP} country=US success=true severity=high"
}

send_windows_auth_fail() {
  local eid
  eid="$(random_id)"
  emit_syslog "<134>$(date '+%b %d %H:%M:%S') soc-test soc_mvp_test=true event_id=${eid} event_type=windows_auth_fail user=${WAZUH_TEST_USER} src_ip=${WAZUH_TEST_SRC_IP} attempts=7 severity=medium"
}

send_once() {
  case "${SCENARIO}" in
    ioc_dns)
      send_ioc_dns
      ;;
    ioc_ips)
      send_ioc_ips
      ;;
    vpn_outside_th)
      send_vpn_outside_th
      ;;
    windows_auth_fail)
      send_windows_auth_fail
      ;;
    all)
      send_ioc_dns
      send_ioc_ips
      send_vpn_outside_th
      send_windows_auth_fail
      ;;
    *)
      echo "error: unknown scenario '${SCENARIO}'"
      echo "valid: ioc_dns | ioc_ips | vpn_outside_th | windows_auth_fail | all"
      exit 1
      ;;
  esac
}

if [[ "${FOREVER}" == "true" ]]; then
  echo "running forever with interval ${DELAY}s (Ctrl+C to stop)"
  trap 'echo; echo "stopped"; exit 0' INT TERM
  while true; do
    send_once
    sleep "${DELAY}"
  done
else
  for ((i=1; i<=COUNT; i++)); do
    send_once
    if [[ "${i}" -lt "${COUNT}" ]]; then
      sleep "${DELAY}"
    fi
  done
fi
