#!/bin/bash

# ============================================================
#   UNIVERSAL ACTIVE DEFENSE MONITORING SCRIPT
#   Cover : WHM/cPanel, CyberPanel, Minecraft, VPS Kosong
#   OS    : AlmaLinux 9 / Ubuntu 22 / Ubuntu 24
#   Fitur : Auto Ban, DDoS Protection, Cloudflare API,
#           AbuseIPDB Report, Telegram Bot Control
#   Author: IKYY x CLAUDE
#   Version: 2.0 (Fixed)
# ============================================================

# --- WARNA ---
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
PURPLE='\033[0;35m'
BOLD='\033[1m'
NC='\033[0m'

# --- BANNER ---
clear
echo -e "${CYAN}${BOLD}"
echo "  ██╗██╗  ██╗██╗   ██╗██╗   ██╗    ██╗  ██╗    ███╗   ███╗ ██████╗ ███╗   ██╗"
echo "  ██║██║ ██╔╝╚██╗ ██╔╝╚██╗ ██╔╝    ╚██╗██╔╝    ████╗ ████║██╔═══██╗████╗  ██║"
echo "  ██║█████╔╝  ╚████╔╝  ╚████╔╝      ╚███╔╝     ██╔████╔██║██║   ██║██╔██╗ ██║"
echo "  ██║██╔═██╗   ╚██╔╝    ╚██╔╝       ██╔██╗     ██║╚██╔╝██║██║   ██║██║╚██╗██║"
echo "  ██║██║  ██╗   ██║      ██║       ██╔╝ ██╗    ██║ ╚═╝ ██║╚██████╔╝██║ ╚████║"
echo "  ╚═╝╚═╝  ╚═╝   ╚═╝      ╚═╝       ╚═╝  ╚═╝    ╚═╝     ╚═╝ ╚═════╝ ╚═╝  ╚═══╝"
echo -e "${NC}"
echo -e "${YELLOW}  Active Defense Monitoring + Telegram Bot | by IKYY x CLAUDE${NC}"
echo -e "${CYAN}  ================================================================${NC}"
echo ""

# --- CEK ROOT ---
if [[ $EUID -ne 0 ]]; then
  echo -e "${RED}[ERROR] Script ini harus dijalankan sebagai root!${NC}"
  exit 1
fi

# --- DETEKSI OS ---
if grep -qi "almalinux" /etc/os-release; then
  OS="almalinux"
  OS_NAME="AlmaLinux"
  PKG="dnf"
elif grep -qi "ubuntu" /etc/os-release; then
  OS="ubuntu"
  OS_NAME="Ubuntu"
  PKG="apt"
else
  echo -e "${RED}[ERROR] OS tidak didukung!${NC}"
  exit 1
fi

echo -e "${GREEN}[OK] OS Terdeteksi: ${OS_NAME}${NC}"
echo ""

# ============================================================
# INPUT KONFIGURASI API
# ============================================================
echo -e "${CYAN}${BOLD}[ KONFIGURASI API & BOT ]${NC}"
echo ""

read -p "  Cloudflare API Token      : " CF_TOKEN
read -p "  Cloudflare Zone ID        : " CF_ZONE_ID
read -p "  AbuseIPDB API Key         : " ABUSE_KEY

# FIX M22: Telegram Token & Chat ID wajib diisi
while [[ -z "$TG_TOKEN" ]]; do
  read -p "  Telegram Bot Token (wajib): " TG_TOKEN
done
while [[ -z "$TG_CHAT_ID" ]]; do
  read -p "  Telegram Chat ID   (wajib): " TG_CHAT_ID
done

echo ""
echo -e "  ${YELLOW}IP kamu sendiri akan otomatis di-whitelist supaya tidak ke-ban.${NC}"
echo -e "  ${YELLOW}Cek IP kamu di myip.com kalau belum tau.${NC}"
read -p "  IP HP/PC kamu (boleh kosong): " ADMIN_IP

echo ""
echo -e "  Panel yang terinstall:"
echo -e "  ${YELLOW}1${NC} = WHM/cPanel"
echo -e "  ${YELLOW}2${NC} = CyberPanel"
echo -e "  ${YELLOW}3${NC} = Minecraft"
echo -e "  ${YELLOW}4${NC} = Tanpa Panel"
read -p "  Pilih (1-4): " PANEL_TYPE
PANEL_TYPE=${PANEL_TYPE:-4}

echo ""
read -p "  Lanjutkan? (y/n): " CONFIRM
if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then
  echo -e "${RED}  Dibatalkan.${NC}"
  exit 0
fi

# ============================================================
# STEP 1: INSTALL DEPENDENSI
# ============================================================
echo ""
echo -e "${CYAN}${BOLD}[STEP 1/6] Install dependensi...${NC}"

if [[ "$OS" == "almalinux" ]]; then
  # FIX M5: Hapus python-telegram-bot yang tidak dipakai
  # FIX M16: Tambah net-tools untuk netstat
  dnf install -y -q curl wget jq iptables-services net-tools
else
  apt update -qq
  apt install -y -qq curl wget jq iptables-persistent net-tools
fi

echo -e "${GREEN}  [OK] Dependensi terinstall${NC}"

# ============================================================
# STEP 2: SETUP DIREKTORI & KONFIGURASI
# ============================================================
echo -e "${CYAN}${BOLD}[STEP 2/6] Setup direktori & konfigurasi...${NC}"

MON_DIR="/opt/ikyy_monitor"
LOG_DIR="/var/log/ikyy_monitor"
CONFIG_FILE="${MON_DIR}/config.conf"
WHITELIST_FILE="${MON_DIR}/whitelist.txt"
BLACKLIST_FILE="${MON_DIR}/blacklist.txt"
BANNED_FILE="${MON_DIR}/banned.txt"
LAST_UPDATE_FILE="${MON_DIR}/last_update_id"

mkdir -p $MON_DIR $LOG_DIR

# Deteksi IP publik VPS
SERVER_PUBLIC_IP=$(curl -s -4 --max-time 5 ifconfig.me 2>/dev/null || curl -s -4 --max-time 5 icanhazip.com 2>/dev/null)

# Deteksi firewall yang aktif
if command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -qi "Status: active"; then
  FIREWALL_TYPE="ufw"
elif command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state 2>/dev/null | grep -qi "running"; then
  FIREWALL_TYPE="firewalld"
else
  FIREWALL_TYPE="iptables"
fi
echo -e "${CYAN}  Firewall terdeteksi: ${FIREWALL_TYPE}${NC}"

# Simpan konfigurasi
cat > $CONFIG_FILE <<EOF
# === IKYY x CLAUDE Monitor Config ===
CF_TOKEN="${CF_TOKEN}"
CF_ZONE_ID="${CF_ZONE_ID}"
ABUSE_KEY="${ABUSE_KEY}"
TG_TOKEN="${TG_TOKEN}"
TG_CHAT_ID="${TG_CHAT_ID}"
PANEL_TYPE="${PANEL_TYPE}"
OS="${OS}"
SERVER_PUBLIC_IP="${SERVER_PUBLIC_IP}"
FIREWALL_TYPE="${FIREWALL_TYPE}"
LOG_DIR="${LOG_DIR}"

# Threshold
SSH_MAX_ATTEMPTS=8
HTTP_MAX_REQUESTS=500
DDOS_THRESHOLD=1000
BAN_DURATION=86400
MONITOR_INTERVAL=30
EOF

# FIX M9: Amankan config file
chmod 600 $CONFIG_FILE
chown root:root $CONFIG_FILE

touch $WHITELIST_FILE $BLACKLIST_FILE $BANNED_FILE

# AUTO-WHITELIST IP PENTING
{
  echo "127.0.0.1"
  echo "::1"
  [[ -n "$SERVER_PUBLIC_IP" ]] && echo "$SERVER_PUBLIC_IP"
  [[ -n "$ADMIN_IP" ]] && echo "$ADMIN_IP"
} | sort -u >> "$WHITELIST_FILE"

echo -e "${GREEN}  [OK] Direktori & konfigurasi siap${NC}"
[[ -n "$SERVER_PUBLIC_IP" ]] && echo -e "${GREEN}  [OK] IP VPS (${SERVER_PUBLIC_IP}) otomatis di-whitelist${NC}"
[[ -n "$ADMIN_IP" ]] && echo -e "${GREEN}  [OK] IP admin (${ADMIN_IP}) otomatis di-whitelist${NC}"

# ============================================================
# STEP 3: BUAT SCRIPT MONITORING UTAMA
# ============================================================
echo -e "${CYAN}${BOLD}[STEP 3/6] Buat script monitoring...${NC}"

cat > ${MON_DIR}/monitor.sh <<'MONEOF'
#!/bin/bash

source /opt/ikyy_monitor/config.conf

LOG="${LOG_DIR}/monitor.log"
WHITELIST="/opt/ikyy_monitor/whitelist.txt"
BLACKLIST="/opt/ikyy_monitor/blacklist.txt"
BANNED="/opt/ikyy_monitor/banned.txt"
PAUSE_FLAG="/opt/ikyy_monitor/reassert_paused"
# FIX M11: Track posisi baca log SSH
SSH_LOG_POS_FILE="/opt/ikyy_monitor/ssh_log_pos"

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG"; }

# ============================================================
# FUNGSI TELEGRAM — FIX M17: URL encode pesan
# ============================================================
send_telegram() {
  local MSG="$1"
  curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
    --data-urlencode "chat_id=${TG_CHAT_ID}" \
    --data-urlencode "text=${MSG}" \
    --data-urlencode "parse_mode=HTML" > /dev/null 2>&1
}

# ============================================================
# FUNGSI CEK WHITELIST
# ============================================================
is_whitelisted() {
  local IP="$1"
  grep -q "^${IP}$" "$WHITELIST" 2>/dev/null
  return $?
}

# ============================================================
# FUNGSI CEK IP PRIVAT / LOOPBACK / IP SERVER SENDIRI
# FIX M14: Tambah handle IPv6
# ============================================================
is_private_or_self() {
  local IP="$1"
  # IPv4 private ranges
  case "$IP" in
    127.*|10.*|192.168.*) return 0 ;;
    172.1[6-9].*|172.2[0-9].*|172.3[0-1].*) return 0 ;;
    169.254.*) return 0 ;;
  esac
  # IPv6 loopback dan private ranges
  case "$IP" in
    ::1|fe80:*|fc00:*|fd00:*) return 0 ;;
  esac
  if [[ -n "$SERVER_PUBLIC_IP" && "$IP" == "$SERVER_PUBLIC_IP" ]]; then
    return 0
  fi
  return 1
}

# ============================================================
# WRAPPER FIREWALL
# ============================================================
fw_ban_ip() {
  local IP="$1"
  case "$FIREWALL_TYPE" in
    ufw)
      ufw insert 1 deny from "$IP" to any 2>/dev/null
      ;;
    firewalld)
      firewall-cmd --add-rich-rule="rule family='ipv4' source address='${IP}' reject" 2>/dev/null
      firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='${IP}' reject" 2>/dev/null
      ;;
    *)
      iptables -I INPUT -s "$IP" -j DROP 2>/dev/null
      iptables -I FORWARD -s "$IP" -j DROP 2>/dev/null
      ;;
  esac
}

fw_unban_ip() {
  local IP="$1"
  case "$FIREWALL_TYPE" in
    ufw)
      ufw delete deny from "$IP" to any 2>/dev/null
      ;;
    firewalld)
      firewall-cmd --remove-rich-rule="rule family='ipv4' source address='${IP}' reject" 2>/dev/null
      firewall-cmd --permanent --remove-rich-rule="rule family='ipv4' source address='${IP}' reject" 2>/dev/null
      ;;
    *)
      iptables -D INPUT -s "$IP" -j DROP 2>/dev/null
      iptables -D FORWARD -s "$IP" -j DROP 2>/dev/null
      ;;
  esac
}

is_fw_rule_active() {
  local IP="$1"
  case "$FIREWALL_TYPE" in
    ufw)
      ufw status 2>/dev/null | grep -qE "DENY.*[[:space:]]${IP//./\\.}([[:space:]]|$)"
      ;;
    firewalld)
      firewall-cmd --query-rich-rule="rule family='ipv4' source address='${IP}' reject" 2>/dev/null
      ;;
    *)
      iptables -C INPUT -s "$IP" -j DROP 2>/dev/null
      ;;
  esac
}

# ============================================================
# FUNGSI REASSERT BAN
# FIX M19: Skip IP yang sudah expired saat reassert
# ============================================================
reassert_bans() {
  if [[ -f "$PAUSE_FLAG" ]]; then
    local PAUSED_AT NOW_TS
    PAUSED_AT=$(cat "$PAUSE_FLAG" 2>/dev/null)
    NOW_TS=$(date +%s)
    if [[ -n "$PAUSED_AT" && $((NOW_TS - PAUSED_AT)) -lt 7200 ]]; then
      log "Reassert sedang di-pause — skip"
      return
    else
      rm -f "$PAUSE_FLAG"
      log "Pause reassert sudah lewat 2 jam — otomatis diaktifkan lagi"
      send_telegram "▶️ <b>AUTO-RESUME</b>
Pause auto-reassert sudah lebih dari 2 jam, sekarang diaktifkan lagi otomatis."
    fi
  fi

  [[ ! -f "$BANNED" ]] && return
  local REAPPLIED=0
  local ENTRIES
  ENTRIES=$(cat "$BANNED" 2>/dev/null)
  local NOW=$(date +%s)
  local DURATION="${BAN_DURATION:-86400}"

  while IFS='|' read -r IP TS; do
    [[ -z "$IP" ]] && continue
    # FIX M19: Skip IP expired, biarkan check_expired_bans yang handle
    if [[ -n "$TS" && $((NOW - TS)) -ge $DURATION ]]; then
      continue
    fi
    if ! is_fw_rule_active "$IP"; then
      fw_ban_ip "$IP"
      REAPPLIED=$((REAPPLIED+1))
      log "Rule untuk $IP hilang dari firewall — dipasang ulang otomatis"
    fi
  done <<< "$ENTRIES"

  if [[ $REAPPLIED -gt 0 ]]; then
    send_telegram "🔁 <b>REASSERT BAN</b>
⚠️ Terdeteksi firewall ke-reset dari luar.
✅ ${REAPPLIED} IP yang harusnya masih banned sudah dipasang ulang otomatis."
  fi
}

# ============================================================
# FUNGSI UNBAN IP
# FIX M1: Cloudflare WAF Custom Rules API (bukan deprecated firewall/rules)
# ============================================================
unban_ip() {
  local IP="$1"

  fw_unban_ip "$IP"
  ip route del blackhole "$IP" 2>/dev/null || true
  sed -i "/^${IP}|/d" "$BANNED" 2>/dev/null

  if [[ -n "$CF_TOKEN" && -n "$CF_ZONE_ID" ]]; then
    # Gunakan WAF Custom Rules API yang baru
    RULE_ID=$(curl -s "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/rulesets/phases/http_request_firewall_custom/entrypoint/rules" \
      -H "Authorization: Bearer ${CF_TOKEN}" | \
      jq -r ".result[] | select(.description | contains(\"${IP}\")) | .id" 2>/dev/null | head -1)
    if [[ -n "$RULE_ID" && "$RULE_ID" != "null" ]]; then
      curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/rulesets/phases/http_request_firewall_custom/entrypoint/rules/${RULE_ID}" \
        -H "Authorization: Bearer ${CF_TOKEN}" > /dev/null 2>&1
    fi
  fi

  log "IP $IP di-unban"
}

# ============================================================
# FUNGSI CEK BAN EXPIRED
# ============================================================
check_expired_bans() {
  [[ ! -f "$BANNED" ]] && return
  local NOW=$(date +%s)
  local DURATION="${BAN_DURATION:-86400}"
  local ENTRIES
  ENTRIES=$(cat "$BANNED" 2>/dev/null)

  while IFS='|' read -r IP TS; do
    [[ -z "$IP" || -z "$TS" ]] && continue
    if [[ $((NOW - TS)) -ge $DURATION ]]; then
      log "Ban IP $IP sudah expired — auto-unban"
      unban_ip "$IP"
      send_telegram "⏰ <b>AUTO-UNBAN</b>
IP <code>${IP}</code> sudah lewat masa ban dan otomatis di-unban."
    fi
  done <<< "$ENTRIES"
}

# ============================================================
# FUNGSI BAN IP
# FIX M1: Cloudflare WAF Custom Rules API baru
# FIX M12: Notif sesuai kondisi CF/AbuseIPDB aktif atau tidak
# FIX M13: ipapi.co dipanggil 1x saja
# ============================================================
ban_ip() {
  local IP="$1"
  local REASON="$2"

  if is_whitelisted "$IP"; then
    log "IP $IP di whitelist — skip ban"
    return
  fi

  if is_private_or_self "$IP"; then
    log "IP $IP adalah IP privat/server sendiri — skip ban"
    return
  fi

  if grep -q "^${IP}|" "$BANNED" 2>/dev/null; then
    return
  fi

  log "BANNING IP: $IP | Alasan: $REASON"

  fw_ban_ip "$IP"
  ip route add blackhole "$IP" 2>/dev/null || true
  echo "${IP}|$(date +%s)" >> "$BANNED"

  local CF_STATUS="❌ Tidak aktif"
  local ABUSE_STATUS="❌ Tidak aktif"

  # FIX M1: Cloudflare WAF Custom Rules API yang baru
  if [[ -n "$CF_TOKEN" && -n "$CF_ZONE_ID" ]]; then
    curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/rulesets/phases/http_request_firewall_custom/entrypoint/rules" \
      -H "Authorization: Bearer ${CF_TOKEN}" \
      -H "Content-Type: application/json" \
      -d "{
        \"action\": \"block\",
        \"expression\": \"ip.src eq ${IP}\",
        \"description\": \"IKYY Monitor Auto-Block: ${REASON}\",
        \"enabled\": true
      }" > /dev/null 2>&1
    CF_STATUS="✅ Dibanned"
  fi

  if [[ -n "$ABUSE_KEY" ]]; then
    curl -s -X POST "https://api.abuseipdb.com/api/v2/report" \
      -H "Key: ${ABUSE_KEY}" \
      -H "Accept: application/json" \
      -d "ip=${IP}&categories=18,22&comment=Auto-reported by IKYY Monitor: ${REASON}" > /dev/null 2>&1
    ABUSE_STATUS="✅ Dilaporkan"
  fi

  # FIX M13: 1 request untuk geo info
  local GEO
  GEO=$(curl -s --max-time 5 "https://ipapi.co/${IP}/json/" 2>/dev/null)
  local COUNTRY FLAG
  COUNTRY=$(echo "$GEO" | jq -r '.country_name // "Unknown"' 2>/dev/null || echo "Unknown")
  FLAG=$(echo "$GEO" | jq -r '.country_code // "??"' 2>/dev/null || echo "??")

  # FIX M12: Notif sesuai kondisi aktual
  send_telegram "🚨 <b>SERANGAN DIBLOK!</b>

🌐 IP: <code>${IP}</code>
🏳 Negara: ${COUNTRY} ${FLAG}
⚔️ Jenis: ${REASON}
🛡 Tindakan:
  ✅ Banned di server (firewall)
  ✅ Null routing aktif
  Cloudflare   : ${CF_STATUS}
  AbuseIPDB    : ${ABUSE_STATUS}

⏰ Waktu: $(date '+%Y-%m-%d %H:%M:%S')
🖥 Server: $(hostname)"

  log "IP $IP berhasil dibanned | Negara: $COUNTRY | Alasan: $REASON"
}

# ============================================================
# MONITOR SSH BRUTE FORCE
# FIX M11: Track posisi log agar tidak hitung ulang dari awal
# ============================================================
monitor_ssh() {
  if [[ "$OS" == "almalinux" ]]; then
    LOG_FILE="/var/log/secure"
  else
    LOG_FILE="/var/log/auth.log"
  fi

  [[ ! -f "$LOG_FILE" ]] && return

  local CURRENT_SIZE
  CURRENT_SIZE=$(wc -c < "$LOG_FILE" 2>/dev/null || echo 0)
  local LAST_POS
  LAST_POS=$(cat "$SSH_LOG_POS_FILE" 2>/dev/null || echo 0)

  # Jika log di-rotate (ukuran mengecil), reset posisi
  if [[ $CURRENT_SIZE -lt $LAST_POS ]]; then
    LAST_POS=0
  fi

  # Baca hanya bagian baru
  tail -c +$((LAST_POS + 1)) "$LOG_FILE" 2>/dev/null | \
    grep "Failed password" | \
    grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | \
    sort | uniq -c | sort -rn | \
    while read COUNT IP; do
      if [[ $COUNT -ge ${SSH_MAX_ATTEMPTS:-8} ]]; then
        ban_ip "$IP" "SSH Brute Force (${COUNT}x percobaan)"
      fi
    done

  echo "$CURRENT_SIZE" > "$SSH_LOG_POS_FILE"
}

# ============================================================
# MONITOR HTTP FLOOD / DDOS
# FIX M2: SYN flood rules tidak numpuk
# FIX M16: Ganti netstat ke ss
# ============================================================
monitor_http() {
  ss -ntu 2>/dev/null | \
    grep -E ':80|:443|:8090|:2087|:2083' | \
    grep ESTAB | \
    awk '{print $6}' | \
    grep -oE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | \
    sort | uniq -c | sort -rn | \
    while read COUNT IP; do
      if [[ $COUNT -ge ${HTTP_MAX_REQUESTS:-500} ]]; then
        ban_ip "$IP" "HTTP Flood/DDoS (${COUNT} koneksi aktif)"
      fi
    done

  # FIX M2: Cek SYN flood dan hindari duplikasi rules
  local SYN_COUNT
  SYN_COUNT=$(ss -ntu 2>/dev/null | grep -c SYN-RECV || echo 0)
  if [[ $SYN_COUNT -ge ${DDOS_THRESHOLD:-1000} ]]; then
    log "SYN FLOOD DETECTED! Count: $SYN_COUNT"
    echo 1 > /proc/sys/net/ipv4/tcp_syncookies
    # Cek dulu sebelum tambah rule agar tidak numpuk
    if ! iptables -C INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT 2>/dev/null; then
      iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
      iptables -A INPUT -p tcp --syn -j DROP
    fi
    send_telegram "⚠️ <b>SYN FLOOD TERDETEKSI!</b>
Count: ${SYN_COUNT} SYN packets
✅ SYN Cookies diaktifkan
✅ Rate limiting diterapkan"
  fi
}

# ============================================================
# MONITOR PORT SCANNING
# FIX M16: Ganti netstat ke ss
# ============================================================
monitor_portscan() {
  ss -ntu 2>/dev/null | \
    grep -v LISTEN | \
    awk '{print $5, $6}' | \
    while read LOCAL REMOTE; do
      LOCAL_PORT=$(echo "$LOCAL" | awk -F: '{print $NF}')
      REMOTE_IP=$(echo "$REMOTE" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
      [[ -n "$REMOTE_IP" ]] && echo "$REMOTE_IP $LOCAL_PORT"
    done | sort -u | \
    awk '{print $1}' | sort | uniq -c | sort -rn | \
    while read PORT_COUNT IP; do
      if [[ $PORT_COUNT -ge 15 ]]; then
        ban_ip "$IP" "Port Scanning (${PORT_COUNT} port berbeda)"
      fi
    done
}

# ============================================================
# MONITOR LOGIN PANEL
# FIX M18: CyberPanel log path yang benar
# ============================================================
monitor_panel() {
  case $PANEL_TYPE in
    1) # WHM/cPanel
      if [[ -f "/usr/local/cpanel/logs/login_log" ]]; then
        tail -500 /usr/local/cpanel/logs/login_log 2>/dev/null | \
          grep "FAILED" | \
          grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | \
          sort | uniq -c | sort -rn | \
          while read COUNT IP; do
            if [[ $COUNT -ge 3 ]]; then
              ban_ip "$IP" "WHM/cPanel Login Attack (${COUNT}x)"
            fi
          done
      fi
      ;;
    2) # CyberPanel — FIX M18: log path yang benar
      local CP_LOG=""
      if [[ -f "/usr/local/CyberCP/logs/error.log" ]]; then
        CP_LOG="/usr/local/CyberCP/logs/error.log"
      elif [[ -f "/var/log/cyberpanel.log" ]]; then
        CP_LOG="/var/log/cyberpanel.log"
      fi
      if [[ -n "$CP_LOG" ]]; then
        tail -500 "$CP_LOG" 2>/dev/null | \
          grep -i "fail\|invalid\|unauthorized" | \
          grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | \
          sort | uniq -c | sort -rn | \
          while read COUNT IP; do
            if [[ $COUNT -ge 3 ]]; then
              ban_ip "$IP" "CyberPanel Login Attack (${COUNT}x)"
            fi
          done
      fi
      ;;
    3) # Minecraft
      if [[ -f "/home/minecraft/server/logs/latest.log" ]]; then
        tail -200 /home/minecraft/server/logs/latest.log 2>/dev/null | \
          grep "lost connection\|Disconnecting" | \
          grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | \
          sort | uniq -c | sort -rn | \
          while read COUNT IP; do
            if [[ $COUNT -ge 10 ]]; then
              ban_ip "$IP" "Minecraft Connection Flood (${COUNT}x)"
            fi
          done
      fi
      ;;
  esac
}

# ============================================================
# AUTO UPDATE BLACKLIST IP HARIAN
# FIX M3: Handler untuk argument update_blacklist dari cron
# ============================================================
update_blacklist() {
  log "Update IP blacklist..."

  SOURCES=(
    "https://raw.githubusercontent.com/stamparm/ipsum/master/levels/3.txt"
    "https://lists.blocklist.de/lists/ssh.txt"
    "https://lists.blocklist.de/lists/bruteforcelogin.txt"
  )

  > /tmp/new_blacklist.txt

  for URL in "${SOURCES[@]}"; do
    curl -s --max-time 30 "$URL" 2>/dev/null | \
      grep -oE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' >> /tmp/new_blacklist.txt
  done

  NEW_IPS=0
  while read IP; do
    if is_private_or_self "$IP"; then
      continue
    fi
    if ! is_whitelisted "$IP" && ! grep -q "^${IP}|" "$BANNED" 2>/dev/null; then
      fw_ban_ip "$IP"
      echo "${IP}|$(date +%s)" >> "$BANNED"
      NEW_IPS=$((NEW_IPS+1))
    fi
  done < /tmp/new_blacklist.txt

  rm -f /tmp/new_blacklist.txt
  log "Blacklist updated: ${NEW_IPS} IP baru diblok"

  send_telegram "🔄 <b>UPDATE BLACKLIST SELESAI</b>
✅ ${NEW_IPS} IP berbahaya baru diblok
📋 Total banned: $(wc -l < $BANNED) IP
⏰ $(date '+%Y-%m-%d %H:%M:%S')"
}

# FIX M3: Handle argument dari cron
if [[ "$1" == "update_blacklist" ]]; then
  update_blacklist
  exit 0
fi

# ============================================================
# KIRIM LAPORAN HARIAN
# ============================================================
send_daily_report() {
  local TOTAL_BANNED RAM_USED RAM_TOTAL DISK_FREE CPU_LOAD
  TOTAL_BANNED=$(wc -l < "$BANNED" 2>/dev/null || echo 0)
  RAM_USED=$(free -m | awk '/^Mem:/{print $3}')
  RAM_TOTAL=$(free -m | awk '/^Mem:/{print $2}')
  DISK_FREE=$(df -h / | awk 'NR==2{print $4}')
  CPU_LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk -F',' '{print $1}' | tr -d ' ')

  send_telegram "📊 <b>LAPORAN HARIAN SERVER</b>

🖥 Server: $(hostname)
🌐 IP: $(hostname -I | awk '{print $1}')
⏰ $(date '+%Y-%m-%d %H:%M:%S')

💻 Status:
  CPU Load: ${CPU_LOAD}
  RAM: ${RAM_USED}MB / ${RAM_TOTAL}MB
  Disk: ${DISK_FREE} tersisa

🛡 Keamanan:
  Total IP Banned: ${TOTAL_BANNED}
  Monitoring: ✅ Aktif

Selamat pagi! Server lo aman. 🙏"
}

# ============================================================
# LOOP MONITORING UTAMA
# ============================================================
log "=== Monitoring dimulai: $(date) ==="
send_telegram "🟢 <b>MONITORING AKTIF</b>

🖥 Server: $(hostname)
🌐 IP: $(hostname -I | awk '{print $1}')
🔒 Panel: Panel Type ${PANEL_TYPE}
⏰ $(date '+%Y-%m-%d %H:%M:%S')

Semua sistem dalam pengawasan aktif. 🛡"

LAST_BLACKLIST_UPDATE=0
LAST_DAILY_REPORT=0

while true; do
  monitor_ssh
  monitor_http
  monitor_portscan
  monitor_panel
  check_expired_bans
  reassert_bans

  NOW=$(date +%s)
  if [[ $((NOW - LAST_BLACKLIST_UPDATE)) -ge 86400 ]]; then
    update_blacklist
    LAST_BLACKLIST_UPDATE=$NOW
  fi

  HOUR=$(date +%H)
  if [[ "$HOUR" == "07" && $((NOW - LAST_DAILY_REPORT)) -ge 86400 ]]; then
    send_daily_report
    LAST_DAILY_REPORT=$NOW
  fi

  sleep ${MONITOR_INTERVAL:-30}
done
MONEOF

chmod +x ${MON_DIR}/monitor.sh
echo -e "${GREEN}  [OK] Script monitoring dibuat${NC}"

# ============================================================
# STEP 4: BUAT TELEGRAM BOT HANDLER
# ============================================================
echo -e "${CYAN}${BOLD}[STEP 4/6] Buat Telegram Bot Handler...${NC}"

cat > ${MON_DIR}/bot.sh <<'BOTEOF'
#!/bin/bash

source /opt/ikyy_monitor/config.conf

LOG="/var/log/ikyy_monitor/bot.log"
WHITELIST="/opt/ikyy_monitor/whitelist.txt"
BANNED="/opt/ikyy_monitor/banned.txt"
PAUSE_FLAG="/opt/ikyy_monitor/reassert_paused"
# FIX M15: Persist LAST_UPDATE ke file agar tidak reset saat restart
LAST_UPDATE_FILE="/opt/ikyy_monitor/last_update_id"

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG"; }

fw_unban_ip() {
  local IP="$1"
  case "$FIREWALL_TYPE" in
    ufw)
      ufw delete deny from "$IP" to any 2>/dev/null
      ;;
    firewalld)
      firewall-cmd --remove-rich-rule="rule family='ipv4' source address='${IP}' reject" 2>/dev/null
      firewall-cmd --permanent --remove-rich-rule="rule family='ipv4' source address='${IP}' reject" 2>/dev/null
      ;;
    *)
      iptables -D INPUT -s "$IP" -j DROP 2>/dev/null
      iptables -D FORWARD -s "$IP" -j DROP 2>/dev/null
      ;;
  esac
}

# FIX M1: Cloudflare WAF Custom Rules API yang baru
unban_ip() {
  local IP="$1"

  fw_unban_ip "$IP"
  ip route del blackhole "$IP" 2>/dev/null || true
  sed -i "/^${IP}|/d" "$BANNED" 2>/dev/null

  if [[ -n "$CF_TOKEN" && -n "$CF_ZONE_ID" ]]; then
    RULE_ID=$(curl -s "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/rulesets/phases/http_request_firewall_custom/entrypoint/rules" \
      -H "Authorization: Bearer ${CF_TOKEN}" | \
      jq -r ".result[] | select(.description | contains(\"${IP}\")) | .id" 2>/dev/null | head -1)
    if [[ -n "$RULE_ID" && "$RULE_ID" != "null" ]]; then
      curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/rulesets/phases/http_request_firewall_custom/entrypoint/rules/${RULE_ID}" \
        -H "Authorization: Bearer ${CF_TOKEN}" > /dev/null 2>&1
    fi
  fi

  log "IP $IP di-unban (via Telegram)"
}

# FIX M17: URL encode pesan
send_msg() {
  local CHAT="$1"
  local MSG="$2"
  curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
    --data-urlencode "chat_id=${CHAT}" \
    --data-urlencode "text=${MSG}" \
    --data-urlencode "parse_mode=HTML" > /dev/null 2>&1
}

# FIX M7 & M8: Validasi format IP
validate_ip() {
  local IP="$1"
  if [[ "$IP" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    return 0
  fi
  return 1
}

# FIX M15: Load LAST_UPDATE dari file
LAST_UPDATE=$(cat "$LAST_UPDATE_FILE" 2>/dev/null || echo 0)

while true; do
  UPDATES=$(curl -s --max-time 35 "https://api.telegram.org/bot${TG_TOKEN}/getUpdates?offset=$((LAST_UPDATE+1))&timeout=30")

  while read -r UPDATE; do
    UPDATE_ID=$(echo "$UPDATE" | jq -r '.update_id')
    CHAT_ID=$(echo "$UPDATE" | jq -r '.message.chat.id')
    TEXT=$(echo "$UPDATE" | jq -r '.message.text // ""')

    LAST_UPDATE=$UPDATE_ID
    # FIX M15: Simpan ke file setiap update
    echo "$LAST_UPDATE" > "$LAST_UPDATE_FILE"

    if [[ "$CHAT_ID" != "$TG_CHAT_ID" ]]; then
      log "Perintah dari Chat ID tidak dikenal: $CHAT_ID — diabaikan"
      continue
    fi

    log "Perintah diterima: $TEXT"

    case "$TEXT" in

      /start|/help)
        send_msg "$CHAT_ID" "🤖 <b>IKYY Monitor Bot</b>

Perintah yang tersedia:

🟢 /start_monitor — Mulai monitoring
🔴 /stop_monitor — Stop monitoring
📊 /status — Status server
🚫 /banned_list — Daftar IP banned
✅ /unban [IP] — Unban IP
🛡 /whitelist_add [IP] — Whitelist IP lo
📋 /log — Log serangan terakhir
🔄 /restart_server — Restart service
⏸ /pause_reassert — Jeda auto-pasang-ulang ban
▶️ /resume_reassert — Aktifkan lagi auto-pasang-ulang ban
❓ /help — Tampilkan menu ini"
        ;;

      /start_monitor)
        systemctl start ikyy_monitor 2>/dev/null
        sleep 2
        if systemctl is-active --quiet ikyy_monitor; then
          send_msg "$CHAT_ID" "🟢 <b>Monitoring AKTIF!</b>
Server lo sekarang dalam pengawasan penuh 24/7. 🛡"
        else
          send_msg "$CHAT_ID" "❌ Gagal start monitoring. Cek: systemctl status ikyy_monitor"
        fi
        ;;

      /stop_monitor)
        systemctl stop ikyy_monitor 2>/dev/null
        send_msg "$CHAT_ID" "🔴 <b>Monitoring DIHENTIKAN</b>
Server tidak dalam pengawasan aktif.
Ketik /start_monitor untuk aktifkan kembali."
        ;;

      /status)
        RAM_USED=$(free -m | awk '/^Mem:/{print $3}')
        RAM_TOTAL=$(free -m | awk '/^Mem:/{print $2}')
        RAM_PCT=$((RAM_USED * 100 / RAM_TOTAL))
        DISK_FREE=$(df -h / | awk 'NR==2{print $4}')
        DISK_PCT=$(df / | awk 'NR==2{print $5}')
        CPU_LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk -F',' '{print $1}' | tr -d ' ')
        UPTIME=$(uptime -p)
        BANNED_COUNT=$(wc -l < "$BANNED" 2>/dev/null || echo 0)
        MON_STATUS=$(systemctl is-active ikyy_monitor 2>/dev/null || echo "inactive")

        send_msg "$CHAT_ID" "📊 <b>STATUS SERVER</b>

🖥 Host: $(hostname)
🌐 IP: $(hostname -I | awk '{print $1}')
⏱ Uptime: ${UPTIME}

💻 Resource:
  CPU Load: ${CPU_LOAD}
  RAM: ${RAM_USED}MB / ${RAM_TOTAL}MB (${RAM_PCT}%)
  Disk: ${DISK_FREE} tersisa (${DISK_PCT} used)

🛡 Keamanan:
  Monitoring: ${MON_STATUS}
  Total IP Banned: ${BANNED_COUNT}

⏰ $(date '+%Y-%m-%d %H:%M:%S')"
        ;;

      /banned_list)
        BANNED_COUNT=$(wc -l < "$BANNED" 2>/dev/null || echo 0)
        if [[ $BANNED_COUNT -eq 0 ]]; then
          send_msg "$CHAT_ID" "✅ Tidak ada IP yang dibanned saat ini."
        else
          # FIX M20: date -d kompatibel dengan fallback
          LAST_10=$(tail -10 "$BANNED" 2>/dev/null | awk -F'|' '{
            cmd = "date -d @" $2 " \"+%Y-%m-%d %H:%M\" 2>/dev/null || date -r " $2 " \"+%Y-%m-%d %H:%M\" 2>/dev/null"
            cmd | getline waktu
            close(cmd)
            print $1 " (banned: " (waktu != "" ? waktu : "tidak diketahui") ")"
          }')
          send_msg "$CHAT_ID" "🚫 <b>IP BANNED (${BANNED_COUNT} total)</b>

10 terbaru:
<code>${LAST_10}</code>

Ban otomatis lepas setelah ${BAN_DURATION:-86400} detik.
Gunakan /unban [IP] untuk unban manual sekarang."
        fi
        ;;

      /unban\ *)
        UNBAN_IP=$(echo "$TEXT" | awk '{print $2}')
        if [[ -z "$UNBAN_IP" ]]; then
          send_msg "$CHAT_ID" "❌ Format salah. Gunakan: /unban 1.2.3.4"
        # FIX M8: Validasi format IP
        elif ! validate_ip "$UNBAN_IP"; then
          send_msg "$CHAT_ID" "❌ Format IP tidak valid: ${UNBAN_IP}"
        else
          unban_ip "$UNBAN_IP"
          CF_NOTE=""
          [[ -n "$CF_TOKEN" ]] && CF_NOTE="  ✅ Dihapus dari Cloudflare" || CF_NOTE="  ⚠️ Cloudflare tidak aktif"
          send_msg "$CHAT_ID" "✅ <b>IP ${UNBAN_IP} berhasil di-unban!</b>
  ✅ Dihapus dari firewall
  ✅ Null route dihapus
${CF_NOTE}
  ✅ Dihapus dari banned list"
        fi
        ;;

      /whitelist_add\ *)
        WL_IP=$(echo "$TEXT" | awk '{print $2}')
        if [[ -z "$WL_IP" ]]; then
          send_msg "$CHAT_ID" "❌ Format salah. Gunakan: /whitelist_add 1.2.3.4"
        # FIX M7: Validasi format IP
        elif ! validate_ip "$WL_IP"; then
          send_msg "$CHAT_ID" "❌ Format IP tidak valid: ${WL_IP}"
        else
          grep -q "^${WL_IP}$" "$WHITELIST" 2>/dev/null || echo "$WL_IP" >> "$WHITELIST"
          sed -i "/^${WL_IP}|/d" "$BANNED" 2>/dev/null
          fw_unban_ip "$WL_IP"
          ip route del blackhole "$WL_IP" 2>/dev/null || true
          send_msg "$CHAT_ID" "✅ <b>IP ${WL_IP} berhasil diwhitelist!</b>
IP ini tidak akan pernah dibanned di server ini. 🛡"
        fi
        ;;

      /log)
        LOG_FILE="/var/log/ikyy_monitor/monitor.log"
        if [[ -f "$LOG_FILE" ]]; then
          LAST_LOG=$(tail -15 "$LOG_FILE" 2>/dev/null)
          send_msg "$CHAT_ID" "📋 <b>LOG TERAKHIR</b>

<code>${LAST_LOG}</code>"
        else
          send_msg "$CHAT_ID" "📋 Log belum ada."
        fi
        ;;

      /restart_server)
        send_msg "$CHAT_ID" "🔄 Merestart service server..."
        case $PANEL_TYPE in
          1) systemctl restart httpd 2>/dev/null; systemctl restart mysql 2>/dev/null
             send_msg "$CHAT_ID" "✅ Apache & MySQL direstart!" ;;
          2) systemctl restart lscpd 2>/dev/null; systemctl restart lsws 2>/dev/null
             send_msg "$CHAT_ID" "✅ CyberPanel & LiteSpeed direstart!" ;;
          3) systemctl restart minecraft 2>/dev/null
             send_msg "$CHAT_ID" "✅ Minecraft Server direstart!" ;;
          *) send_msg "$CHAT_ID" "ℹ Tidak ada panel terdeteksi untuk direstart." ;;
        esac
        ;;

      /pause_reassert)
        date +%s > "$PAUSE_FLAG"
        send_msg "$CHAT_ID" "⏸ <b>Auto-reassert ban DIJEDA.</b>
Aman buat re-run hardening.sh manual sekarang.

⏰ Otomatis aktif lagi dalam 2 jam.
Jangan lupa /resume_reassert kalau udah selesai lebih cepat!"
        ;;

      /resume_reassert)
        rm -f "$PAUSE_FLAG"
        send_msg "$CHAT_ID" "▶️ <b>Auto-reassert ban AKTIF lagi.</b>
Kalau firewall ke-reset dari luar, ban lama bakal otomatis dipasang ulang seperti biasa."
        ;;

      *)
        if [[ -n "$TEXT" && "$TEXT" == /* ]]; then
          send_msg "$CHAT_ID" "❓ Perintah tidak dikenal: ${TEXT}
Ketik /help untuk melihat semua perintah."
        fi
        ;;
    esac
  done < <(echo "$UPDATES" | jq -c '.result[]' 2>/dev/null)

  sleep 2
done
BOTEOF

chmod +x ${MON_DIR}/bot.sh
echo -e "${GREEN}  [OK] Telegram Bot Handler dibuat${NC}"

# ============================================================
# STEP 5: SETUP SYSTEMD SERVICE
# ============================================================
echo -e "${CYAN}${BOLD}[STEP 5/6] Setup systemd service...${NC}"

cat > /etc/systemd/system/ikyy_monitor.service <<EOF
[Unit]
Description=IKYY x CLAUDE Active Defense Monitor
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash /opt/ikyy_monitor/monitor.sh
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

cat > /etc/systemd/system/ikyy_bot.service <<EOF
[Unit]
Description=IKYY x CLAUDE Telegram Bot
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash /opt/ikyy_monitor/bot.sh
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable ikyy_monitor ikyy_bot
systemctl start ikyy_monitor ikyy_bot

echo -e "${GREEN}  [OK] Service monitoring & bot aktif${NC}"

# ============================================================
# STEP 6: SETUP CRON
# ============================================================
echo -e "${CYAN}${BOLD}[STEP 6/6] Setup cron...${NC}"

# FIX M3: Panggil monitor.sh dengan argument update_blacklist
(crontab -l 2>/dev/null; echo "0 2 * * * /bin/bash /opt/ikyy_monitor/monitor.sh update_blacklist >> /var/log/ikyy_monitor/blacklist_update.log 2>&1") | crontab -

echo -e "${GREEN}  [OK] Cron setup selesai${NC}"

# ============================================================
# RINGKASAN
# ============================================================
SERVER_IP=$(hostname -I | awk '{print $1}')

echo ""
echo -e "${CYAN}${BOLD}"
echo "  ================================================================"
echo "   MONITORING AKTIF! ALHAMDULILLAH — SERVER LO TERLINDUNGI 24/7"
echo "  ================================================================"
echo -e "${NC}"
echo -e "${BOLD}  YANG AKTIF SEKARANG:${NC}"
echo ""
echo -e "  🛡  Auto Ban SSH Brute Force   : ${GREEN}AKTIF${NC}"
echo -e "  🛡  Auto Ban HTTP Flood/DDoS   : ${GREEN}AKTIF${NC}"
echo -e "  🛡  Auto Ban Port Scanner      : ${GREEN}AKTIF${NC}"
# FIX M10: Tampilkan status CF dan AbuseIPDB sesuai kondisi aktual
if [[ -n "$CF_TOKEN" && -n "$CF_ZONE_ID" ]]; then
  echo -e "  🛡  Cloudflare Auto Ban        : ${GREEN}AKTIF${NC}"
else
  echo -e "  🛡  Cloudflare Auto Ban        : ${YELLOW}TIDAK DIKONFIGURASI${NC}"
fi
if [[ -n "$ABUSE_KEY" ]]; then
  echo -e "  🛡  AbuseIPDB Auto Report      : ${GREEN}AKTIF${NC}"
else
  echo -e "  🛡  AbuseIPDB Auto Report      : ${YELLOW}TIDAK DIKONFIGURASI${NC}"
fi
echo -e "  🛡  IP Blacklist Harian        : ${GREEN}AKTIF${NC}"
echo -e "  🤖  Telegram Bot Control       : ${GREEN}AKTIF${NC}"
echo -e "  🔔  Notifikasi Telegram        : ${GREEN}AKTIF${NC}"
echo ""
echo -e "${BOLD}  COMMAND TELEGRAM BOT:${NC}"
echo -e "  /start_monitor    — Mulai monitoring"
echo -e "  /stop_monitor     — Stop monitoring"
echo -e "  /status           — Status server"
echo -e "  /banned_list      — Daftar IP banned"
echo -e "  /unban IP         — Unban IP"
echo -e "  /whitelist_add IP — Whitelist IP lo"
echo -e "  /log              — Log serangan"
echo -e "  /restart_server   — Restart service"
echo -e "  /pause_reassert   — Jeda auto-reassert (untuk re-run hardening)"
echo -e "  /resume_reassert  — Aktifkan lagi auto-reassert"
echo -e "  /help             — Semua command"
echo ""
echo -e "${YELLOW}  LANGKAH SELANJUTNYA:${NC}"
echo -e "  1. Buka Telegram → cari bot lo"
echo -e "  2. Ketik /whitelist_add IP_LO supaya tidak kena ban"
echo -e "  3. Ketik /status untuk verifikasi"
echo ""
echo -e "  📋 Log monitor : ${CYAN}/var/log/ikyy_monitor/monitor.log${NC}"
echo -e "  📋 Log bot     : ${CYAN}/var/log/ikyy_monitor/bot.log${NC}"
echo -e "${CYAN}  ================================================================${NC}"
echo ""
