#!/bin/bash

# -------------------------------------
# Argumen: IP address yang ingin dilepas blokir
# Digunakan oleh client.js untuk eksekusi lokal
# -------------------------------------

IP="$1"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# Get the script's absolute directory path
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
LOG_DIR="${SCRIPT_DIR}/logs"
ACTIONS_LOG="${LOG_DIR}/actions.log"
BLOCK_LOG="${LOG_DIR}/block_log.csv"

# Ensure log directory exists
mkdir -p "$LOG_DIR"

# Validate IP format
function validate_ip() {
    local ip=$1
    local stat=1
    
    if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        OIFS=$IFS
        IFS='.'
        ip=($ip)
        IFS=$OIFS
        [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
        stat=$?
    fi
    return $stat
}

# Validate input
if [ -z "$IP" ]; then
  echo "[❌] IP kosong."
  echo "$TIMESTAMP,,UNBLOCK,ERROR,Empty IP provided" >> "$BLOCK_LOG"
  exit 1
fi

if ! validate_ip "$IP"; then
  echo "[❌] Invalid IP format: $IP"
  echo "$TIMESTAMP,$IP,UNBLOCK,ERROR,Invalid IP format" >> "$BLOCK_LOG"
  exit 1
fi

# Try to remove the DROP rule
UNBLOCKED=false

# Debug: Check if sudo works at all
if ! sudo -n true 2>/dev/null; then
    echo "[❌] Sudo access is not available without a password. Please configure sudoers."
    echo "$TIMESTAMP,$IP,UNBLOCK,ERROR,No sudo access" >> "$BLOCK_LOG"
    exit 1
fi

# Debug: Check if iptables is available
if ! command -v iptables &> /dev/null; then
    echo "[❌] iptables command not found. Please install iptables."
    echo "$TIMESTAMP,$IP,UNBLOCK,ERROR,iptables command not found" >> "$BLOCK_LOG"
    exit 1
fi

# Debug: Check if we can use iptables with sudo without a password
if ! sudo -n iptables -L INPUT -n > /dev/null 2>&1; then
    echo "[❌] Cannot run iptables commands with sudo. Check sudoers configuration."
    echo "[ℹ️] Current sudo permissions:"
    sudo -l 2>&1 | tee -a "$ACTIONS_LOG"
    echo "$TIMESTAMP,$IP,UNBLOCK,ERROR,No sudo access for iptables commands" >> "$BLOCK_LOG"
    exit 1
fi

# Debug: List all rules for this IP before attempting to remove
echo "[🔍] Current iptables rules for IP $IP:"
sudo iptables -L INPUT -n | grep "$IP" || echo "  None found"

# Check if there are any rules for this IP
if sudo iptables -L INPUT -n | grep -q "$IP"; then
    # First try to remove any DROP rules
    if sudo iptables -L INPUT -n | grep -q "$IP.*DROP"; then
        echo "[🔄] Executing: sudo iptables -D INPUT -s $IP -j DROP"
        if sudo iptables -D INPUT -s "$IP" -j DROP; then
            echo "[✅] Removed DROP rule for IP $IP from INPUT chain."
            UNBLOCKED=true
        else
            echo "[❌] Failed to remove DROP rule for IP $IP."
        fi
    else
        echo "[ℹ️] No DROP rule found for IP $IP in INPUT chain."
    fi
    
    # Then try to remove any REJECT rules
    if sudo iptables -L INPUT -n | grep -q "$IP.*REJECT"; then
        echo "[🔄] Executing: sudo iptables -D INPUT -s $IP -j REJECT"
        if sudo iptables -D INPUT -s "$IP" -j REJECT; then
            echo "[✅] Removed REJECT rule for IP $IP from INPUT chain."
            UNBLOCKED=true
        else
            echo "[❌] Failed to remove REJECT rule for IP $IP."
        fi
    fi
    
    # Check for any other rules with this IP and try to remove them
    while sudo iptables -L INPUT -n | grep -q "$IP"; do
        echo "[🔍] Found another rule for IP $IP, attempting to remove..."
        
        # Get the rule number for this IP
        RULE_NUM=$(sudo iptables -L INPUT -n --line-numbers | grep "$IP" | head -n 1 | awk '{print $1}')
        
        if [ -n "$RULE_NUM" ]; then
            echo "[🔄] Executing: sudo iptables -D INPUT $RULE_NUM"
            if sudo iptables -D INPUT "$RULE_NUM"; then
                echo "[✅] Removed rule #$RULE_NUM for IP $IP from INPUT chain."
                UNBLOCKED=true
            else
                echo "[❌] Failed to remove rule #$RULE_NUM for IP $IP."
                break  # Avoid infinite loop if removal fails
            fi
        else
            echo "[⚠️] Could not determine rule number for IP $IP."
            break
        fi
    done
else
    echo "[ℹ️] No rules found for IP $IP in INPUT chain."
fi

if [ "$UNBLOCKED" = true ]; then
    echo "[✅] IP $IP successfully unblocked."
    echo "$TIMESTAMP,$IP,UNBLOCK,SUCCESS,iptables" >> "$BLOCK_LOG"
    echo "[✅] IP $IP di-unban via iptables" >> "$ACTIONS_LOG"
    
    # Notify server about successful unblock
    # Get the server address from .env configuration or use default
    ENV_FILE="${SCRIPT_DIR}/.env"
    SERVER_URL="http://98.142.245.186:8080"
    SERVER_TOKEN=""
    CLIENT_ID=""
    
    if [ -f "$ENV_FILE" ]; then
        echo "[🔍] Reading server configuration from $ENV_FILE"
        
        # Read SERVER_IP and SERVER_PORT from .env
        SERVER_IP_VALUE=$(grep -E "^SERVER_IP=" "$ENV_FILE" 2>/dev/null | cut -d'=' -f2)
        SERVER_PORT_VALUE=$(grep -E "^SERVER_PORT=" "$ENV_FILE" 2>/dev/null | cut -d'=' -f2)
        
        # Construct SERVER_URL from IP and PORT if both are available
        if [ -n "$SERVER_IP_VALUE" ] && [ -n "$SERVER_PORT_VALUE" ]; then
            SERVER_URL="http://${SERVER_IP_VALUE}:${SERVER_PORT_VALUE}"
            echo "[✅] Constructed server URL: $SERVER_URL"
        else
            # Try direct SERVER_URL as fallback
            SERVER_URL_VALUE=$(grep -E "^SERVER_URL=" "$ENV_FILE" 2>/dev/null | cut -d'=' -f2)
            if [ -n "$SERVER_URL_VALUE" ]; then
                SERVER_URL="$SERVER_URL_VALUE"
                echo "[✅] Using explicit SERVER_URL: $SERVER_URL"
            else
                echo "[⚠️] Could not determine server URL from environment, using default: $SERVER_URL"
            fi
        fi
        
        # Read SECRET_TOKEN from .env
        TOKEN_VALUE=$(grep -E "^SECRET_TOKEN=" "$ENV_FILE" 2>/dev/null | cut -d'=' -f2)
        if [ -n "$TOKEN_VALUE" ]; then
            SERVER_TOKEN="$TOKEN_VALUE"
        fi
        
        # Read CLIENT_ID from .env
        CLIENT_ID_VALUE=$(grep -E "^CLIENT_ID=" "$ENV_FILE" 2>/dev/null | cut -d'=' -f2)
        if [ -n "$CLIENT_ID_VALUE" ]; then
            CLIENT_ID="$CLIENT_ID_VALUE"
            echo "[✅] Using CLIENT_ID from .env: $CLIENT_ID"
        else
            echo "[⚠️] CLIENT_ID not found in .env, will use 'script' as source identifier"
            CLIENT_ID="script"
        fi
    else
        echo "[⚠️] .env file not found at $ENV_FILE, using default server URL"
    fi
    
    # Notify server API about the unblock
    echo "[🔄] Notifying server at $SERVER_URL about unblock event for IP $IP"
    if command -v curl &> /dev/null; then
        if [ -n "$SERVER_TOKEN" ]; then
            echo "[🔄] Executing curl with authentication token"
            # Add verbose output to a temporary file for debugging
            TEMP_LOG=$(mktemp)
            CURL_RESULT=$(curl -s -v -X POST "${SERVER_URL}/api/notify-unblock" \
                -H "Content-Type: application/json" \
                -d "{\"ip\":\"$IP\",\"source\":\"$CLIENT_ID\",\"token\":\"$SERVER_TOKEN\"}" 2>"$TEMP_LOG" || echo "Failed")
        else
            echo "[⚠️] No authentication token found, attempting without token"
            TEMP_LOG=$(mktemp)
            CURL_RESULT=$(curl -s -v -X POST "${SERVER_URL}/api/notify-unblock" \
                -H "Content-Type: application/json" \
                -d "{\"ip\":\"$IP\",\"source\":\"$CLIENT_ID\"}" 2>"$TEMP_LOG" || echo "Failed")
        fi
        
        if [ "$CURL_RESULT" = "Failed" ] || [[ "$CURL_RESULT" == *"error"* ]]; then
            echo "[❌] Failed to notify server about unblock event"
            echo "[❌] Curl debug information:" 
            cat "$TEMP_LOG"
            echo "[❌] Server notification failed for IP $IP" >> "$ACTIONS_LOG"
            echo "[❌] Curl debug information saved to $ACTIONS_LOG" >> "$ACTIONS_LOG"
            cat "$TEMP_LOG" >> "$ACTIONS_LOG"
        else
            echo "[✅] Successfully notified server about unblock event"
            echo "[✅] Server response: $CURL_RESULT"
            echo "[✅] Server notified about unblock for IP $IP" >> "$ACTIONS_LOG"
        fi
        
        # Clean up temp file
        rm -f "$TEMP_LOG"
    else
        echo "[⚠️] curl command not found, unable to notify server"
        echo "[⚠️] curl command not found, server not notified about unblock for IP $IP" >> "$ACTIONS_LOG"
    fi
    
    exit 0
else
    echo "[⚠️] IP $IP was not found in iptables rules or could not be removed."
    echo "$TIMESTAMP,$IP,UNBLOCK,WARNING,IP not found in iptables" >> "$BLOCK_LOG"
    
    # No need to notify server if the IP wasn't actually blocked in iptables
    echo "[ℹ️] Not notifying server since IP wasn't blocked in iptables"
    echo "[ℹ️] No server notification needed for IP $IP (not blocked in iptables)" >> "$ACTIONS_LOG"
    
    # Not a failure if IP wasn't blocked to begin with
    exit 0
fi
