#!/bin/bash
# BDUSP DDoS Guard CLI v3

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; NC='\033[0m'; BOLD='\033[1m'

BASE="/var/lib/ddos-guard"
BLOCKED_FILE="$BASE/blocked_ips.json"
QUARANTINE_FILE="$BASE/quarantine.json"
WHITELIST_FILE="$BASE/whitelist.json"
BLOCKLIST_FILE="$BASE/blocklist.json"
CONFIG_FILE="$BASE/config.json"
LOG_FILE="/var/log/ddos-guard.log"

header() {
    echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo -e "${CYAN}  🛡️  BDUSP DDoS Guard v3${NC}"
    echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}

py() { python3 -c "$1"; }

cfg_get() {
    py "
import json
try: d=json.load(open('$CONFIG_FILE'))
except: d={}
defaults={'window_seconds':30,'block_threshold':100,'perm_threshold':500,
'domain_threshold':300,'quarantine_release_at':50,'quarantine_cooldown':120,
'check_interval':5,'quarantine_enabled':True,'server_wide_enabled':False,
'server_wide_threshold':30000}
defaults.update(d)
v=defaults.get('$1','')
print(str(v))
"
}

cfg_set() {
    py "
import json,os
os.makedirs('$BASE',exist_ok=True)
try: d=json.load(open('$CONFIG_FILE'))
except: d={}
v='$2'
try: v=int(v)
except:
    try: v=float(v)
    except:
        if v.lower()=='true': v=True
        elif v.lower()=='false': v=False
d['$1']=v
json.dump(d,open('$CONFIG_FILE','w'),indent=2)
print('  Updated: $1 =',v)
"
}

# ── status ────────────────────────────────────────────────────────────────────
cmd_status() {
    header; echo ""
    if systemctl is-active --quiet ddos-guard; then
        echo -e "  Service:    ${GREEN}● Running${NC}"
    else
        echo -e "  Service:    ${RED}● Stopped${NC}"
    fi
    total=$(py "import json
try: d=json.load(open('$BLOCKED_FILE')); print(len(d))
except: print(0)")
    perm=$(py "import json
try: d=json.load(open('$BLOCKED_FILE')); print(sum(1 for v in d.values() if v.get('permanent')))
except: print(0)")
    qcount=$(py "import json
try: d=json.load(open('$QUARANTINE_FILE')); print(len(d))
except: print(0)")
    wcount=$(py "import json
try: d=json.load(open('$WHITELIST_FILE')); print(len(d))
except: print(0)")
    bcount=$(py "import json
try: d=json.load(open('$BLOCKLIST_FILE')); print(len(d))
except: print(0)")
    echo -e "  Blocked:    ${RED}${total} IP(s)${NC} (${perm} permanent)"
    echo -e "  Quarantine: ${YELLOW}${qcount} domain(s)${NC}"
    echo -e "  Whitelist:  ${GREEN}${wcount} IP(s)${NC}"
    echo -e "  Blocklist:  ${RED}${bcount} IP(s)${NC}"
    echo ""
    q_enabled=$(cfg_get quarantine_enabled)
    sw_enabled=$(cfg_get server_wide_enabled)
    echo -e "  ${BOLD}Config:${NC}"
    echo -e "  Window            : $(cfg_get window_seconds)s"
    echo -e "  Block threshold   : $(cfg_get block_threshold) req → 7d block"
    echo -e "  Perm threshold    : $(cfg_get perm_threshold) req → permanent"
    echo -e "  Domain threshold  : $(cfg_get domain_threshold) req → quarantine"
    echo -e "  Quarantine off at : < $(cfg_get quarantine_release_at) req + $(cfg_get quarantine_cooldown)s"
    if [ "$q_enabled" = "True" ]; then
        echo -e "  Quarantine mode   : ${GREEN}ENABLED${NC}"
    else
        echo -e "  Quarantine mode   : ${RED}DISABLED${NC} (only IP block)"
    fi
    if [ "$sw_enabled" = "True" ]; then
        echo -e "  Server-wide       : ${GREEN}ON${NC} ($(cfg_get server_wide_threshold) req/window)"
    else
        echo -e "  Server-wide       : ${RED}OFF${NC}"
    fi
    echo ""
}

# ── config ────────────────────────────────────────────────────────────────────
cmd_config() {
    local key="$1" val="$2"
    if [ -z "$key" ]; then
        header; echo ""
        echo -e "  ${BOLD}Usage:${NC} vg config <key> <value>"; echo ""
        echo -e "  ${GREEN}window_seconds${NC}          $(cfg_get window_seconds)"
        echo -e "  ${GREEN}block_threshold${NC}         $(cfg_get block_threshold)   req/window → 7d block"
        echo -e "  ${GREEN}perm_threshold${NC}          $(cfg_get perm_threshold)   req/window → permanent"
        echo -e "  ${GREEN}domain_threshold${NC}        $(cfg_get domain_threshold)   req/window → quarantine"
        echo -e "  ${GREEN}quarantine_release_at${NC}   $(cfg_get quarantine_release_at)    traffic below this → off"
        echo -e "  ${GREEN}quarantine_cooldown${NC}     $(cfg_get quarantine_cooldown)   seconds before release"
        echo -e "  ${GREEN}quarantine_enabled${NC}      $(cfg_get quarantine_enabled)   true/false"
        echo -e "  ${GREEN}server_wide_enabled${NC}     $(cfg_get server_wide_enabled)  true/false"
        echo -e "  ${GREEN}server_wide_threshold${NC}   $(cfg_get server_wide_threshold)"
        echo ""
        return
    fi
    [ -z "$val" ] && echo -e "${RED}Usage: vg config <key> <value>${NC}" && exit 1
    cfg_set "$key" "$val"
    systemctl restart ddos-guard 2>/dev/null
    echo -e "${GREEN}✅ Config updated. Service restarted.${NC}"
}

# ── quarantine on/off ─────────────────────────────────────────────────────────
cmd_quarantine_on() {
    cfg_set "quarantine_enabled" "true"
    systemctl restart ddos-guard 2>/dev/null
    echo -e "${GREEN}✅ Quarantine mode ENABLED.${NC}"
}

cmd_quarantine_off() {
    cfg_set "quarantine_enabled" "false"
    systemctl restart ddos-guard 2>/dev/null
    echo -e "${YELLOW}⚠ Quarantine mode DISABLED. Only IP block will happen.${NC}"
}

# ── blocked ───────────────────────────────────────────────────────────────────
cmd_blocked() {
    header
    echo -e "\n  ${BOLD}Auto-Blocked IPs:${NC}\n"
    py "
import json,time
try: data=json.load(open('$BLOCKED_FILE'))
except: data={}
if not data: print('  No blocked IPs.'); exit()
print(f\"  {'IP':<20} {'Type':<12} {'Blocked At':<22} {'Expires'}\")
print(f\"  {'─'*20} {'─'*12} {'─'*22} {'─'*20}\")
for ip,i in data.items():
    perm=i.get('permanent',False)
    bt=time.strftime('%Y-%m-%d %H:%M',time.localtime(i.get('time',0)))
    ex='Never' if perm else time.strftime('%Y-%m-%d %H:%M',time.localtime(i.get('time',0)+i.get('duration',0)))
    print(f\"  {ip:<20} {'PERMANENT' if perm else '7 Days':<12} {bt:<22} {ex}\")
print()
"
}

# ── clear blocked ─────────────────────────────────────────────────────────────
cmd_clear_blocked_7d() {
    echo -e "${YELLOW}Clearing all 7-day blocked IPs...${NC}"
    py "
import json,subprocess
try: data=json.load(open('$BLOCKED_FILE'))
except: data={}
to_del=[ip for ip,i in data.items() if not i.get('permanent')]
for ip in to_del:
    subprocess.run('iptables -D INPUT -s {} -j DROP 2>/dev/null'.format(ip),shell=True)
    subprocess.run('iptables -D OUTPUT -d {} -j DROP 2>/dev/null'.format(ip),shell=True)
    del data[ip]
json.dump(data,open('$BLOCKED_FILE','w'),indent=2)
print('  Removed {} IP(s).'.format(len(to_del)))
"
    echo -e "${GREEN}✅ Done.${NC}"
}

cmd_clear_blocked_perm() {
    echo -e "${YELLOW}Clearing all permanent blocked IPs...${NC}"
    py "
import json,subprocess
try: data=json.load(open('$BLOCKED_FILE'))
except: data={}
to_del=[ip for ip,i in data.items() if i.get('permanent')]
for ip in to_del:
    subprocess.run('iptables -D INPUT -s {} -j DROP 2>/dev/null'.format(ip),shell=True)
    subprocess.run('iptables -D OUTPUT -d {} -j DROP 2>/dev/null'.format(ip),shell=True)
    del data[ip]
json.dump(data,open('$BLOCKED_FILE','w'),indent=2)
print('  Removed {} IP(s).'.format(len(to_del)))
"
    echo -e "${GREEN}✅ Done.${NC}"
}

cmd_clear_blocked_all() {
    echo -e "${YELLOW}Clearing ALL blocked IPs...${NC}"
    py "
import json,subprocess
try: data=json.load(open('$BLOCKED_FILE'))
except: data={}
for ip in data:
    subprocess.run('iptables -D INPUT -s {} -j DROP 2>/dev/null'.format(ip),shell=True)
    subprocess.run('iptables -D OUTPUT -d {} -j DROP 2>/dev/null'.format(ip),shell=True)
json.dump({},open('$BLOCKED_FILE','w'),indent=2)
print('  Removed {} IP(s).'.format(len(data)))
"
    echo -e "${GREEN}✅ Done.${NC}"
}

# ── whitelist ─────────────────────────────────────────────────────────────────
cmd_whitelist_add() {
    [ -z "$1" ] && echo -e "${RED}Usage: vg whitelist-add <ip> [note]${NC}" && exit 1
    py "
import json,time,os
os.makedirs('$BASE',exist_ok=True)
try: d=json.load(open('$WHITELIST_FILE'))
except: d={}
d['$1']={'added':time.time(),'note':'${2:-manual}'}
json.dump(d,open('$WHITELIST_FILE','w'),indent=2)
print('  Added.')
"
    echo -e "${GREEN}✅ $1 added to whitelist.${NC}"
}

cmd_whitelist_remove() {
    [ -z "$1" ] && echo -e "${RED}Usage: vg whitelist-remove <ip>${NC}" && exit 1
    py "
import json
try: d=json.load(open('$WHITELIST_FILE')); d.pop('$1',None); json.dump(d,open('$WHITELIST_FILE','w'),indent=2); print('  Removed.')
except: print('  Not found.')
"
    echo -e "${GREEN}✅ Done.${NC}"
}

cmd_whitelist_clear() {
    py "
import json
json.dump({},open('$WHITELIST_FILE','w'),indent=2)
print('  Whitelist cleared.')
"
    echo -e "${GREEN}✅ Done.${NC}"
}

cmd_whitelist() {
    header
    echo -e "\n  ${BOLD}Whitelist:${NC}\n"
    py "
import json,time
defaults={'127.0.0.1':{'added':0,'note':'system'},'::1':{'added':0,'note':'system'}}
try: u=json.load(open('$WHITELIST_FILE')); defaults.update(u)
except: pass
print(f\"  {'IP':<22} {'Added':<22} {'Note'}\")
print(f\"  {'─'*22} {'─'*22} {'─'*20}\")
for ip,i in defaults.items():
    added=time.strftime('%Y-%m-%d %H:%M',time.localtime(i.get('added',0))) if i.get('added') else 'system'
    print(f\"  {ip:<22} {added:<22} {i.get('note','')}\")
print()
"
}

# ── blocklist ─────────────────────────────────────────────────────────────────
cmd_blocklist_add() {
    [ -z "$1" ] && echo -e "${RED}Usage: vg blocklist-add <ip> [note]${NC}" && exit 1
    iptables -I INPUT -s "$1" -j DROP 2>/dev/null
    iptables -I OUTPUT -d "$1" -j DROP 2>/dev/null
    py "
import json,time,os
os.makedirs('$BASE',exist_ok=True)
try: d=json.load(open('$BLOCKLIST_FILE'))
except: d={}
d['$1']={'added':time.time(),'note':'${2:-manual}','permanent':True}
json.dump(d,open('$BLOCKLIST_FILE','w'),indent=2)
print('  Added.')
"
    echo -e "${GREEN}✅ $1 permanently blocked.${NC}"
}

cmd_blocklist_remove() {
    [ -z "$1" ] && echo -e "${RED}Usage: vg blocklist-remove <ip>${NC}" && exit 1
    iptables -D INPUT -s "$1" -j DROP 2>/dev/null
    iptables -D OUTPUT -d "$1" -j DROP 2>/dev/null
    py "
import json
try: d=json.load(open('$BLOCKLIST_FILE')); d.pop('$1',None); json.dump(d,open('$BLOCKLIST_FILE','w'),indent=2); print('  Removed.')
except: print('  Not found.')
"
    echo -e "${GREEN}✅ Done.${NC}"
}

cmd_blocklist_clear() {
    echo -e "${YELLOW}Clearing permanent blocklist...${NC}"
    py "
import json,subprocess
try: data=json.load(open('$BLOCKLIST_FILE'))
except: data={}
for ip in data:
    subprocess.run('iptables -D INPUT -s {} -j DROP 2>/dev/null'.format(ip),shell=True)
    subprocess.run('iptables -D OUTPUT -d {} -j DROP 2>/dev/null'.format(ip),shell=True)
json.dump({},open('$BLOCKLIST_FILE','w'),indent=2)
print('  Cleared {} IP(s).'.format(len(data)))
"
    echo -e "${GREEN}✅ Done.${NC}"
}

cmd_blocklist() {
    header
    echo -e "\n  ${BOLD}Permanent Blocklist:${NC}\n"
    py "
import json,time
try: data=json.load(open('$BLOCKLIST_FILE'))
except: data={}
if not data: print('  No IPs in blocklist.'); exit()
print(f\"  {'IP':<22} {'Added':<22} {'Note'}\")
print(f\"  {'─'*22} {'─'*22} {'─'*20}\")
for ip,i in data.items():
    added=time.strftime('%Y-%m-%d %H:%M',time.localtime(i.get('added',0)))
    print(f\"  {ip:<22} {added:<22} {i.get('note','')}\")
print()
"
}

# ── quarantine list/release ───────────────────────────────────────────────────
cmd_quarantine_list() {
    header
    echo -e "\n  ${BOLD}Quarantined Domains:${NC}\n"
    py "
import json,time
try: data=json.load(open('$QUARANTINE_FILE'))
except: data={}
if not data: print('  No quarantined domains.'); exit()
print(f\"  {'Domain':<35} {'Since':<22} {'Docroot'}\")
print(f\"  {'─'*35} {'─'*22} {'─'*30}\")
for d,i in data.items():
    since=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(i.get('since',0)))
    print(f\"  {d:<35} {since:<22} {i.get('docroot','?')}\")
print()
"
}

cmd_release() {
    [ -z "$1" ] && echo -e "${RED}Usage: vg release <domain>${NC}" && exit 1
    echo -e "${YELLOW}Releasing $1...${NC}"
    py "
import json,os,shutil
try: data=json.load(open('$QUARANTINE_FILE'))
except: print('  No quarantine data.'); exit()
if '$1' not in data: print('  Not in quarantine.'); exit()
i=data['$1']; dr=i.get('docroot')
if not dr: print('  Docroot unknown.'); exit()
ht=os.path.join(dr,'.htaccess')
bk=os.path.join(dr,'.htaccess.bdusp_bak')
gd=os.path.join(dr,'.bdusp-guard')
if os.path.exists(bk): shutil.move(bk,ht)
elif os.path.exists(ht):
    with open(ht) as f:
        if 'BDUSP-GUARD' in f.read(): os.remove(ht)
if os.path.isdir(gd): shutil.rmtree(gd)
del data['$1']
json.dump(data,open('$QUARANTINE_FILE','w'),indent=2)
print('  Done.')
"
    echo -e "${GREEN}✅ $1 released.${NC}"
}

# ── block/unblock ─────────────────────────────────────────────────────────────
cmd_block() {
    [ -z "$1" ] && echo -e "${RED}Usage: vg block <ip>${NC}" && exit 1
    iptables -I INPUT -s "$1" -j DROP 2>/dev/null
    iptables -I OUTPUT -d "$1" -j DROP 2>/dev/null
    py "
import json,time,os
os.makedirs('$BASE',exist_ok=True)
try: d=json.load(open('$BLOCKED_FILE'))
except: d={}
d['$1']={'time':time.time(),'duration':604800,'permanent':False,'label':'7d-manual'}
json.dump(d,open('$BLOCKED_FILE','w'),indent=2)
"
    echo -e "${GREEN}✅ $1 blocked (7 days).${NC}"
}

cmd_unblock() {
    [ -z "$1" ] && echo -e "${RED}Usage: vg unblock <ip>${NC}" && exit 1
    iptables -D INPUT -s "$1" -j DROP 2>/dev/null
    iptables -D OUTPUT -d "$1" -j DROP 2>/dev/null
    py "
import json
try: d=json.load(open('$BLOCKED_FILE')); d.pop('$1',None); json.dump(d,open('$BLOCKED_FILE','w'),indent=2)
except: pass
"
    echo -e "${GREEN}✅ $1 unblocked.${NC}"
}

# ── log/service ───────────────────────────────────────────────────────────────
cmd_log()     { echo -e "${CYAN}━━━━ Live Log (Ctrl+C) ━━━━${NC}"; tail -f "$LOG_FILE"; }
cmd_start()   { systemctl start ddos-guard;   echo -e "${GREEN}▶ Started.${NC}"; }
cmd_stop()    { systemctl stop ddos-guard;    echo -e "${YELLOW}⏹ Stopped.${NC}"; }
cmd_restart() { systemctl restart ddos-guard; echo -e "${GREEN}↺ Restarted.${NC}"; }

# ── help ──────────────────────────────────────────────────────────────────────
cmd_help() {
    header; echo ""
    echo -e "  ${BOLD}Usage:${NC} vg <command> [args]"; echo ""
    echo -e "  ${CYAN}Overview:${NC}"
    echo -e "    ${GREEN}status${NC}                       Full status + config"
    echo -e "    ${GREEN}log${NC}                          Live log"; echo ""
    echo -e "  ${CYAN}Config:${NC}"
    echo -e "    ${GREEN}config${NC}                       Show all config values"
    echo -e "    ${GREEN}config${NC} <key> <value>         Update config"; echo ""
    echo -e "  ${CYAN}Quarantine:${NC}"
    echo -e "    ${GREEN}quarantine${NC}                   List quarantined domains"
    echo -e "    ${GREEN}quarantine-on${NC}                Enable quarantine mode"
    echo -e "    ${GREEN}quarantine-off${NC}               Disable (only IP block)"
    echo -e "    ${GREEN}release${NC} <domain>             Release a domain"; echo ""
    echo -e "  ${CYAN}Blocked IPs:${NC}"
    echo -e "    ${GREEN}blocked${NC}                      List auto-blocked IPs"
    echo -e "    ${GREEN}block${NC} <ip>                   Manually block (7d)"
    echo -e "    ${GREEN}unblock${NC} <ip>                 Unblock"
    echo -e "    ${GREEN}clear-blocked-7d${NC}             Remove all 7-day blocks"
    echo -e "    ${GREEN}clear-blocked-perm${NC}           Remove all permanent blocks"
    echo -e "    ${GREEN}clear-blocked-all${NC}            Remove ALL blocks"; echo ""
    echo -e "  ${CYAN}Whitelist:${NC}"
    echo -e "    ${GREEN}whitelist${NC}                    Show whitelist"
    echo -e "    ${GREEN}whitelist-add${NC} <ip> [note]"
    echo -e "    ${GREEN}whitelist-remove${NC} <ip>"
    echo -e "    ${GREEN}whitelist-clear${NC}              Clear all whitelist IPs"; echo ""
    echo -e "  ${CYAN}Blocklist (permanent):${NC}"
    echo -e "    ${GREEN}blocklist${NC}                    Show blocklist"
    echo -e "    ${GREEN}blocklist-add${NC} <ip> [note]"
    echo -e "    ${GREEN}blocklist-remove${NC} <ip>"
    echo -e "    ${GREEN}blocklist-clear${NC}              Clear all blocklist IPs"; echo ""
    echo -e "  ${CYAN}Service:${NC}"
    echo -e "    ${GREEN}start${NC} / ${GREEN}stop${NC} / ${GREEN}restart${NC}"; echo ""
}

# ── router ────────────────────────────────────────────────────────────────────
case "$1" in
    status)            cmd_status ;;
    config)            cmd_config "$2" "$3" ;;
    quarantine)        cmd_quarantine_list ;;
    quarantine-on)     cmd_quarantine_on ;;
    quarantine-off)    cmd_quarantine_off ;;
    release)           cmd_release "$2" ;;
    blocked)           cmd_blocked ;;
    block)             cmd_block "$2" ;;
    unblock)           cmd_unblock "$2" ;;
    clear-blocked-7d)  cmd_clear_blocked_7d ;;
    clear-blocked-perm)cmd_clear_blocked_perm ;;
    clear-blocked-all) cmd_clear_blocked_all ;;
    whitelist)         cmd_whitelist ;;
    whitelist-add)     cmd_whitelist_add "$2" "$3" ;;
    whitelist-remove)  cmd_whitelist_remove "$2" ;;
    whitelist-clear)   cmd_whitelist_clear ;;
    blocklist)         cmd_blocklist ;;
    blocklist-add)     cmd_blocklist_add "$2" "$3" ;;
    blocklist-remove)  cmd_blocklist_remove "$2" ;;
    blocklist-clear)   cmd_blocklist_clear ;;
    log)               cmd_log ;;
    start)             cmd_start ;;
    stop)              cmd_stop ;;
    restart)           cmd_restart ;;
    help|--help|-h)    cmd_help ;;
    *)                 cmd_help ;;
esac
