#!/usr/bin/env bash
# Per-domain circuit breaker at the Nginx layer.
# Blocks/unblocks a domain at Nginx level WITHOUT touching Apache config.
# A broken site is served a 503 maintenance page; all others are unaffected.
#
# Usage:
#   vhost-firewall block <domain> [reason]
#   vhost-firewall unblock <domain>
#   vhost-firewall status
#   vhost-firewall status <domain>

set -uo pipefail

BLOCK_DIR="/etc/nginx/conf.d/blocked"
NGINX_CONF_D="/etc/nginx/conf.d"
LOG_FILE="/opt/server-resilience/logs/vhost-firewall-$(date +%Y%m%d).log"
ALERT_SCRIPT="/opt/server-resilience/bin/send-alert"

mkdir -p "$BLOCK_DIR"

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

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"; }

usage() {
    echo "Usage: $0 block <domain> [reason]"
    echo "       $0 unblock <domain>"
    echo "       $0 status [domain]"
    exit 1
}

[[ $# -lt 1 ]] && usage
CMD="$1"

# ─── STATUS ───────────────────────────────────────────────────────────────────
if [[ "$CMD" == "status" ]]; then
    DOMAIN="${2:-}"
    if [[ -n "$DOMAIN" ]]; then
        BLOCK_FILE="$BLOCK_DIR/${DOMAIN}.conf"
        if [[ -f "$BLOCK_FILE" ]]; then
            echo -e "${RED}BLOCKED:${NC} $DOMAIN"
            grep "^# Reason:" "$BLOCK_FILE" 2>/dev/null || true
            grep "^# Blocked at:" "$BLOCK_FILE" 2>/dev/null || true
        else
            echo -e "${GREEN}ACTIVE:${NC} $DOMAIN (not blocked)"
        fi
    else
        echo -e "${BOLD}=== Blocked Domains ===${NC}"
        BLOCKED=0
        for f in "$BLOCK_DIR"/*.conf; do
            [[ ! -f "$f" ]] && continue
            domain=$(basename "$f" .conf)
            echo -e "  ${RED}BLOCKED:${NC} $domain"
            grep "^# Reason:\|^# Blocked at:" "$f" 2>/dev/null | sed 's/^# /    /' || true
            ((BLOCKED++))
        done
        [[ $BLOCKED -eq 0 ]] && echo "  No domains currently blocked."
        echo -e "\nTotal blocked: $BLOCKED"
    fi
    exit 0
fi

# ─── BLOCK ────────────────────────────────────────────────────────────────────
if [[ "$CMD" == "block" ]]; then
    DOMAIN="${2:-}"
    REASON="${3:-Manual block}"
    [[ -z "$DOMAIN" ]] && usage

    BLOCK_FILE="$BLOCK_DIR/${DOMAIN}.conf"
    TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

    log "Blocking domain: $DOMAIN (reason: $REASON)"

    cat > "$BLOCK_FILE" << EOF
# Reason: $REASON
# Blocked at: $TIMESTAMP
# Managed by: vhost-firewall
# To restore: vhost-firewall unblock $DOMAIN

server {
    listen 80;
    listen 443 ssl;
    server_name $DOMAIN www.$DOMAIN;

    # Minimal SSL stub to prevent Nginx errors on 443
    ssl_certificate     /etc/nginx/conf.d/blocked/stub.crt;
    ssl_certificate_key /etc/nginx/conf.d/blocked/stub.key;

    access_log /opt/server-resilience/logs/blocked-${DOMAIN}-access.log;
    error_log  /opt/server-resilience/logs/blocked-${DOMAIN}-error.log;

    location / {
        return 503;
    }

    error_page 503 /503.html;
    location = /503.html {
        root /opt/server-resilience/etc;
        internal;
    }
}
EOF

    # Generate stub SSL cert for the block server block (prevents Nginx startup errors)
    if [[ ! -f "$BLOCK_DIR/stub.crt" ]]; then
        openssl req -x509 -newkey rsa:2048 \
            -keyout "$BLOCK_DIR/stub.key" \
            -out "$BLOCK_DIR/stub.crt" \
            -days 3650 -nodes \
            -subj "/CN=blocked/O=ServerResilience/C=CA" 2>/dev/null
        chmod 600 "$BLOCK_DIR/stub.key"
        log "Generated stub SSL cert for blocked domain server block"
    fi

    # Test and reload Nginx
    if nginx -t 2>/dev/null; then
        nginx -s reload 2>/dev/null
        log "Nginx reloaded — $DOMAIN is now returning 503"
        echo -e "${GREEN}✓ $DOMAIN blocked at Nginx layer (503 response)${NC}"
        echo "  All other sites are unaffected."
        echo "  To restore: vhost-firewall unblock $DOMAIN"
        "$ALERT_SCRIPT" "WARN" "Domain $DOMAIN blocked at Nginx layer. Reason: $REASON" 2>/dev/null || true
    else
        rm -f "$BLOCK_FILE"
        log "Nginx config test FAILED — block not applied"
        echo -e "${RED}Nginx config test failed — block NOT applied. Check Nginx config.${NC}"
        exit 1
    fi
    exit 0
fi

# ─── UNBLOCK ──────────────────────────────────────────────────────────────────
if [[ "$CMD" == "unblock" ]]; then
    DOMAIN="${2:-}"
    [[ -z "$DOMAIN" ]] && usage

    BLOCK_FILE="$BLOCK_DIR/${DOMAIN}.conf"

    if [[ ! -f "$BLOCK_FILE" ]]; then
        echo "$DOMAIN is not currently blocked."
        exit 0
    fi

    log "Unblocking domain: $DOMAIN"
    rm -f "$BLOCK_FILE"

    if nginx -t 2>/dev/null; then
        nginx -s reload 2>/dev/null
        log "Nginx reloaded — $DOMAIN is now live"
        echo -e "${GREEN}✓ $DOMAIN unblocked — now live${NC}"
        "$ALERT_SCRIPT" "RECOVERED" "Domain $DOMAIN unblocked at Nginx layer — now serving traffic" 2>/dev/null || true
    else
        log "Nginx config test failed after unblock — restored block file"
        echo -e "${RED}Nginx config test failed after unblock. Investigating...${NC}"
        exit 1
    fi
    exit 0
fi

usage
