#!/bin/bash
# /opt/UnlimitedShield/shield

set -e
source /opt/UnlimitedShield/config.sh

generate_nft() {
    echo "Generating nftables configuration..."

    # Форматируем порты для nftables { 443, 2053 }
    join_ports() { local arr=("${!1}"); local IFS=", "; echo "${arr[*]}"; }
    local tcp_list=$(join_ports TCP_PORTS[@])
    local udp_list=$(join_ports UDP_PORTS[@])

    cat << EOF > "$NFT_CONF"
# Generated by UnlimitedShield. Do not edit manually!

# Удаляем старую таблицу, чтобы не плодить дубли при перезагрузке
table inet unlimited_shield
delete table inet unlimited_shield

table inet unlimited_shield {
    # Сет для заблокированных IPv4
    set blocked_v4 {
        type ipv4_addr
        flags interval
        elements = {
EOF

    # Вставляем IPv4 адреса стран
    for country in "${BLOCK_COUNTRIES[@]}"; do
        if [ -f "$GEOIP_DIR/${country}_v4.zone" ]; then
            while read -r line; do
                [ -n "$line" ] && echo "            $line," >> "$NFT_CONF"
            done < "$GEOIP_DIR/${country}_v4.zone"
        fi
    done
    # Добавляем заглушку, чтобы сет не был пустым
    echo "            127.0.0.199," >> "$NFT_CONF"
    echo "        }" >> "$NFT_CONF"
    echo "    }" >> "$NFT_CONF"

    if [ "$ENABLE_IPV6" = true ]; then
        cat << EOF >> "$NFT_CONF"
    set blocked_v6 {
        type ipv6_addr
        flags interval
        elements = {
EOF
        for country in "${BLOCK_COUNTRIES[@]}"; do
            if [ -f "$GEOIP_DIR/${country}_v6.zone" ]; then
                while read -r line; do
                    [ -n "$line" ] && echo "            $line," >> "$NFT_CONF"
                done < "$GEOIP_DIR/${country}_v6.zone"
            fi
        done
        echo "            ::199," >> "$NFT_CONF"
        echo "        }" >> "$NFT_CONF"
        echo "    }" >> "$NFT_CONF"
    fi

    # Базовая цепочка Prerouting (Ловит трафик ЕЩЁ ДО Docker NAT)
    # priority -150 гарант запуска до любого conntrack и nat
    cat << EOF >> "$NFT_CONF"
    chain prerouting {
        type filter hook prerouting priority -150; policy accept;

        # Сбрасываем заблокированные страны по GeoIP сразу
        ip saddr @blocked_v4 drop
EOF

    if [ "$ENABLE_IPV6" = true ]; then
        echo "        ip6 saddr @blocked_v6 drop" >> "$NFT_CONF"
    fi

    # Начинаем цепочку защиты самого хоста (SSH и локальные сервисы)
    cat << EOF >> "$NFT_CONF"
    }

    chain input {
        type filter hook input priority filter; policy drop;

        # Разрешаем loopback
        iifname "lo" accept

        # Разрешаем уже установленные соединения
        ct state established,related accept

        # Разрешаем SSH
        tcp dport $SSH_PORT accept
EOF

    # Вставляем порты VPN (выполняется в Bash, пишется в конфиг корректно)
    [ -n "$tcp_list" ] && echo "        tcp dport { $tcp_list } accept" >> "$NFT_CONF"
    [ -n "$udp_list" ] && echo "        udp dport { $udp_list } accept" >> "$NFT_CONF"

    # Закрываем фигурные скобки цепочки и всей таблицы
    cat << EOF >> "$NFT_CONF"
    }
}
EOF
}

case "$1" in
    install)
        echo "Installing UnlimitedShield..."
        ;;
    reload)
        generate_nft
        nft -f "$NFT_CONF"
        echo "Rules applied successfully."
        ;;
    verify)
        generate_nft
        if nft -c -f "$NFT_CONF"; then
            echo "Configuration is VALID."
        else
            echo "Configuration is INVALID!"
            exit 1
        fi
        ;;
    status)
        nft list table inet unlimited_shield 2>/dev/null || echo "Shield table not found (inactive)."
        ;;
    *)
        echo "Usage: $0 {install|uninstall|update|reload|status|verify}"
        exit 1
        ;;
esac
